Skip to content

Commit

Permalink
Feat: bundle outputs (#438)
Browse files Browse the repository at this point in the history
feat(*): add bundle outputs

- add outputs section to the a porter manifest
- place outputs in /cnab/app/outputs in the execution environment, per the CNAB Spec
- place these same outputs under the local/user's $PORTER_HOME/outputs/<claim name> directory, assuming the default Docker driver is being used
- add cli command: 'porter bundle show' to list a bundle's claim and outputs
  • Loading branch information
vdice authored Jul 11, 2019
1 parent 4e6a840 commit c3908ac
Show file tree
Hide file tree
Showing 41 changed files with 1,212 additions and 66 deletions.
2 changes: 2 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ endif

install:
mkdir -p $(HOME)/.porter
cp -R bin/* $(HOME)/.porter/
cp -R bin/bundles $(HOME)/.porter/
cp -R bin/mixins $(HOME)/.porter/
cp bin/porter* $(HOME)/.porter/
ln -f -s $(HOME)/.porter/porter /usr/local/bin/porter

clean: clean-mixins clean-last-testrun
Expand Down
2 changes: 1 addition & 1 deletion build/testdata/bundles/mysql/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Dockerfile
cnab/
.cnab
1 change: 1 addition & 0 deletions build/testdata/bundles/mysql/porter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ install:
- name: mysql-password
secret: "{{ bundle.parameters.mysql-name }}"
key: mysql-password

uninstall:
- helm:
description: "Uninstall MySQL"
Expand Down
2 changes: 2 additions & 0 deletions build/testdata/bundles/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dockerfile
.cnab
11 changes: 11 additions & 0 deletions build/testdata/bundles/terraform/porter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ install:
autoApprove: true
vars:
file_contents: "{{bundle.parameters.file_contents}}"
outputs:
- name: file_contents

upgrade:
- terraform:
description: "Upgrade Terraform assets"
autoApprove: true
vars:
file_contents: "{{ bundle.parameters.file_contents }}"
outputs:
- name: file_contents

status:
- terraform:
Expand All @@ -34,3 +38,10 @@ uninstall:
description: "Uninstall Terraform assets"
vars:
file_contents: "{{bundle.parameters.file_contents}}"

outputs:
- name: file_contents
type: string
applyTo:
- install
- upgrade
4 changes: 4 additions & 0 deletions build/testdata/bundles/terraform/terraform/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "file_contents" {
value = "${var.file_contents}"
description = "Contents of the file 'foo'"
}
2 changes: 1 addition & 1 deletion build/testdata/bundles/wordpress/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Dockerfile
cnab/
.cnab
13 changes: 13 additions & 0 deletions build/testdata/bundles/wordpress/porter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,23 @@ install:
externalDatabase.password: "{{ bundle.dependencies.mysql.outputs.mysql-password }}"
externalDatabase.port: 3306
mariadb.enabled: false
outputs:
- name: wordpress-password
secret: "{{ bundle.parameters.wordpress-name }}-wordpress"
key: wordpress-password

uninstall:
- helm:
description: "Uninstall Wordpress"
purge: true
releases:
- "{{ bundle.parameters.wordpress-name }}"

outputs:
- name: wordpress-password
description: "The Wordpress installation password"
type: string
applyTo:
- "install"
- "upgrade"
sensitive: true
40 changes: 39 additions & 1 deletion cmd/porter/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package main
import (
"strings"

"github.com/spf13/cobra"

"github.com/deislabs/porter/pkg/porter"
"github.com/deislabs/porter/pkg/printer"
"github.com/spf13/cobra"
)

func buildBundlesCommand(p *porter.Porter) *cobra.Command {
Expand All @@ -25,6 +26,7 @@ func buildBundlesCommand(p *porter.Porter) *cobra.Command {
cmd.AddCommand(buildBundleInstallCommand(p))
cmd.AddCommand(buildBundleUpgradeCommand(p))
cmd.AddCommand(buildBundleUninstallCommand(p))
cmd.AddCommand(buildBundleShowCommand(p))

return cmd
}
Expand All @@ -37,6 +39,7 @@ func buildBundleAliasCommands(p *porter.Porter) []*cobra.Command {
buildUpgradeCommand(p),
buildUninstallCommand(p),
buildPublishCommand(p),
buildShowCommand(p),
}
}

Expand Down Expand Up @@ -326,3 +329,38 @@ func buildPublishCommand(p *porter.Porter) *cobra.Command {
}
return cmd
}

func buildBundleShowCommand(p *porter.Porter) *cobra.Command {
opts := porter.ShowOptions{}

cmd := cobra.Command{
Use: "show [CLAIM]",
Short: "Show a bundle",
Long: "Displays info relating to a bundle claim, including status and a listing of outputs.",
Example: ` porter bundle show [CLAIM]
Optional output formats include json and yaml.
`,
PreRunE: func(cmd *cobra.Command, args []string) error {
return opts.Validate(args, p.Context)
},
RunE: func(cmd *cobra.Command, args []string) error {
return p.ShowBundle(opts)
},
}

f := cmd.Flags()
f.StringVarP(&opts.RawFormat, "output", "o", "table",
"Specify an output format. Allowed values: table, json, yaml")

return &cmd
}

func buildShowCommand(p *porter.Porter) *cobra.Command {
cmd := buildBundleShowCommand(p)
cmd.Example = strings.Replace(cmd.Example, "porter bundle show", "porter show", -1)
cmd.Annotations = map[string]string{
"group": "alias",
}
return cmd
}
35 changes: 31 additions & 4 deletions docs/content/authoring-bundles.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Porter generates a bundle from its manifest, porter.yaml. The manifest is made u
* [Bundle Metadata](#bundle-metadata)
* [Mixins](#mixins)
* [Parameters](#parameters)
* [Outputs](#outputs)
* [Credentials](#credentials)
* [Bundle Actions](#bundle-actions)
* [Dependencies](#dependencies)
Expand Down Expand Up @@ -87,11 +88,37 @@ parameters:
* `path`: The path for the file. Required for file paths, there is no default.
* `sensitive`: Optional. Designate this parameter's value as sensitive, for masking in console output.

### Parameter Schema
## Outputs

The [CNAB Spec for parameter definitions](https://github.com/deislabs/cnab-spec/blob/master/101-bundle-json.md#definitions)
has full support for [json schema](https://json-schema.org). We aren't quite there yet but
are working towards it. Here is what Porter supports for defining schema for parameters currently:
Outputs are part of the [CNAB Spec](https://github.com/deislabs/cnab-spec/blob/master/101-bundle-json.md#outputs) to
allow access to outputs generated during the course of executing a bundle. These are global/bundle-wide outputs,
as opposed to step outputs described in [Parameters, Credentials and Outputs](/wiring/). However, as of writing, each
bundle output is only valid if it references a step output declared under one or more [bundle actions](#bundle-actions).

```yaml
outputs:
- name: mysql_user
type: string
description: "MySQL user name"
- name: mysql_password
type: string
applyTo:
- "install"
- "upgrade"
```

* `name`: The name of the output.
* `type`: The data type of the output: string, integer, number, boolean.
* `applyTo`: (Optional) Restrict this output to a given list of actions. If empty or missing, applies to all actions.
* `description`: (Optional) A brief description of the given output.
* `sensitive`: (Optional) Designate an output as sensitive. Defaults to false.

### Definition Schema for Parameters and Outputs

The [CNAB Spec for definitions](https://github.com/deislabs/cnab-spec/blob/master/101-bundle-json.md#definitions)
applies to both parameters and outputs. It has full support for [json schema](https://json-schema.org). We aren't
quite there yet but are working towards it. Here is what Porter supports for defining schema for parameters and outputs
currently:

* `default`: The default value for the parameter. When a default is not provided, the `required` is defaulted to true.
* `required`: Specify if the parameter must be specified when the bundle is executed.
Expand Down
27 changes: 26 additions & 1 deletion docs/content/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ Global Flags:
This command is available both as `porter bundle list` and `porter bundles list`.

```console
$ porter bundle list --help
$ porter bundle list --help
List all bundles installed by Porter.

A listing of bundles currently installed by Porter will be provided, along with
Expand All @@ -226,6 +226,31 @@ Global Flags:
--debug Enable debug logging
```

### Bundle Show

This command is available both as `porter bundle show` and `porter bundles show`.

```console
$ porter bundle show --help
Displays info relating to a bundle claim, including status and a listing of outputs.

Usage:
porter bundles show [CLAIM] [flags]

Examples:
porter bundle show [CLAIM]

Optional output formats include json and yaml.


Flags:
-h, --help help for show
-o, --output string Specify an output format. Allowed values: table, json, yaml (default "table")

Global Flags:
--debug Enable debug logging
```

## Mixin Commands

### Mixins List
Expand Down
8 changes: 8 additions & 0 deletions examples/kubernetes-mixin-example/porter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ install:
resourceType: service
resourceName: nginx-deployment
jsonPath: "{.spec.clusterIP}"

- exec:
description: "Echo the IP Address"
command: bash
arguments:
- -c
- "echo 'You will find the service at: {{bundle.outputs.IP_ADDRESS}}'"

uninstall:
- kubernetes:
description: "Uninstall Hello World"
manifests:
- manifests/nginx
wait: true

outputs:
- name: ip_address
type: string
41 changes: 36 additions & 5 deletions pkg/cnab/config_adapter/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package configadapter

import (
"fmt"
"path/filepath"
"strings"

"github.com/deislabs/cnab-go/bundle/definition"
Expand Down Expand Up @@ -35,17 +36,18 @@ func (c *ManifestConverter) ToBundle() *bundle.Bundle {
},
}

b.Definitions = make(definition.Definitions, len(c.Manifest.Parameters)+len(c.Manifest.Outputs))
b.InvocationImages = []bundle.InvocationImage{image}
b.Definitions, b.Parameters = c.generateBundleParameters()
b.Parameters = c.generateBundleParameters(&b.Definitions)
b.Outputs = c.generateBundleOutputs(&b.Definitions)
b.Credentials = c.generateBundleCredentials()
b.Images = c.generateBundleImages()
b.Custom[config.CustomBundleKey] = c.GenerateStamp()

return b
}

func (c *ManifestConverter) generateBundleParameters() (definition.Definitions, *bundle.ParametersDefinition) {
defs := make(definition.Definitions, len(c.Manifest.Parameters))
func (c *ManifestConverter) generateBundleParameters(defs *definition.Definitions) *bundle.ParametersDefinition {
params := &bundle.ParametersDefinition{
Fields: make(map[string]bundle.ParameterDefinition, len(c.Manifest.Parameters)),
}
Expand Down Expand Up @@ -83,10 +85,39 @@ func (c *ManifestConverter) generateBundleParameters() (definition.Definitions,
}
}

defs[param.Name] = d
(*defs)[param.Name] = d
params.Fields[param.Name] = p
}
return defs, params
return params
}

func (c *ManifestConverter) generateBundleOutputs(defs *definition.Definitions) *bundle.OutputsDefinition {
outputs := &bundle.OutputsDefinition{
Fields: make(map[string]bundle.OutputDefinition, len(c.Manifest.Outputs)),
}

for _, output := range c.Manifest.Outputs {
fmt.Fprintf(c.Out, "Generating output definition %s ====>\n", output.Name)
d := &definition.Schema{
Type: output.Type,
Default: output.Default,
Enum: output.Enum,
Minimum: output.Minimum,
Maximum: output.Maximum,
MinLength: output.MinLength,
MaxLength: output.MaxLength,
}
o := bundle.OutputDefinition{
Definition: output.Name,
Description: output.Description,
ApplyTo: output.ApplyTo,
Path: filepath.Join(config.BundleOutputsDir, output.Name),
}

(*defs)[output.Name] = d
outputs.Fields[output.Name] = o
}
return outputs
}

func (c *ManifestConverter) buildDefaultPorterParameters() []config.ParameterDefinition {
Expand Down
Loading

0 comments on commit c3908ac

Please sign in to comment.