-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding THE KUBERNETES MIXIN #228
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildBuildCommand(mixin *kubernetes.Mixin) *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "build", | ||
Short: "Generate Dockerfile contribution for invocation image", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return mixin.Build() | ||
}, | ||
} | ||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildInstallCommand(mixin *kubernetes.Mixin) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "install", | ||
Short: "Use kubectl to apply manifests to a cluster", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return mixin.Install() | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func main() { | ||
cmd := buildRootCommand(os.Stdin) | ||
if err := cmd.Execute(); err != nil { | ||
fmt.Printf("err: %s\n", err) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func buildRootCommand(in io.Reader) *cobra.Command { | ||
mixin := kubernetes.New() | ||
mixin.In = in | ||
cmd := &cobra.Command{ | ||
Use: "kubernetes", | ||
Long: "kuberetes is a porter 👩🏽✈️ mixin that you can you can use to apply kubernetes manifests in your bundle", | ||
PersistentPreRun: func(cmd *cobra.Command, args []string) { | ||
mixin.Out = cmd.OutOrStdout() | ||
mixin.Err = cmd.OutOrStderr() | ||
}, | ||
SilenceUsage: true, | ||
} | ||
|
||
cmd.PersistentFlags().BoolVar(&mixin.Debug, "debug", false, "Enable debug logging") | ||
cmd.AddCommand(buildVersionCommand(mixin)) | ||
cmd.AddCommand(buildBuildCommand(mixin)) | ||
cmd.AddCommand(buildInstallCommand(mixin)) | ||
cmd.AddCommand(buildUpgradeCommand(mixin)) | ||
cmd.AddCommand(buildUnInstallCommand(mixin)) | ||
cmd.AddCommand(buildSchemaCommand(mixin)) | ||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildSchemaCommand(mixin *kubernetes.Mixin) *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "schema", | ||
Short: "Print the json schema for the mixin", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return mixin.PrintSchema() | ||
}, | ||
} | ||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildUnInstallCommand(mixin *kubernetes.Mixin) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "uninstall", | ||
Short: "Use kubectl to delete resources contained in a manifest from a cluster", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return mixin.Uninstall() | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildUpgradeCommand(mixin *kubernetes.Mixin) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "Upgrade", | ||
Short: "Use kubectl to apply manifests to a cluster", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return mixin.Upgrade() | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/deislabs/porter/pkg/kubernetes" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func buildVersionCommand(mixin *kubernetes.Mixin) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "version", | ||
Short: "Print the mixin verison", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
mixin.PrintVersion() | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,12 +50,8 @@ The mixin allows bundle authors to specify the following parameters on install: | |
|-----------|------|-------------|---------| | ||
| `namespace` | string | The namespace in which to create resources | `default` | | ||
| `manifests` | string | The path to the manifests. Can be a file or directory | `/cnab/app/kubernetes` | | ||
| `allow-missing-template-keys` | boolean | If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. | `true` | | ||
| `output` | string | Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file. | | | ||
| `record` | boolean | Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists. | `false` | | ||
| `save-config` | boolean | If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future. | `false` | | ||
| `record` | boolean | Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists. | `false` | | ||
| `selector` | string | Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2) | | | ||
| `template` | string | Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates | | | ||
| `validate` | boolean | If true, use a schema to validate the input before sending it | `true` | | ||
| `wait` | boolean | If true, wait for resources to be gone before returning. This waits for finalizers. | `true` | | ||
|
||
|
@@ -67,15 +63,12 @@ The mixin allows bundle authors to specify the following parameters on install: | |
|-----------|------|-------------|---------| | ||
| `namespace` | string | The namespace in which to create resources. | `default` | | ||
| `manifests` | string | The path to the manifests. Can be a file or directory. | `/cnab/app/kubernetes` | | ||
| `allow-missing-template-keys` | boolean | If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. | `true` | | ||
| `force` | boolean | If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation. Overrides `grace-period`. | `false`| | ||
| `grace-period` | integer | Period of time in seconds given to the resource to terminate gracefully. Ignored if negative. Set to 1 for immediate shutdown. If `force` is true, will result in 0. | -1 | | ||
| `output` | string | Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file. | | | ||
| `force` | boolean | If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation. Overrides `gracePeriod`. | `false`| | ||
| `gracePeriod` | integer | Period of time in seconds given to the resource to terminate gracefully. Ignored if negative. Set to 1 for immediate shutdown. If `force` is true, will result in 0. | -1 | | ||
| `overwrite` | boolean | Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration. | `true` | | ||
| `record` | boolean | Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists. | `false` | | ||
| `save-config` | boolean | If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future. | `false` | | ||
| `prune` | boolean | Automatically delete resource objects, including the uninitialized ones, that do not appear in the configs. | `false` | | ||
| `record` | boolean | Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists. | `false` || | ||
| `selector` | string | Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). | | | ||
| `template` | string | Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates. | | | ||
| `timeout` | integer | The length of time (in seconds) to wait before giving up on a delete, zero means determine a timeout from the size of the object. | 0 | | ||
| `validate` | boolean | If true, use a schema to validate the input before sending it. | `true` | | ||
| `wait` | boolean | If true, wait for resources to be gone before returning. This waits for finalizers. | `true` | | ||
|
@@ -93,13 +86,15 @@ The mixin allows bundle authors to specify the following parameters on delete: | |
| `namespace` | string | The namespace in which to create resources. | `default` | | ||
| `manifests` | string | The path to the manifests. Can be a file or directory. | `/cnab/app/kuberentes` | | ||
| `force` | boolean | If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation. Sets grace period to `0`. | `false` | | ||
| `grace-period` | integer | Period of time in seconds given to the resource to terminate gracefully. Ignored if negative. Set to 1 for immediate shutdown. | `-1` | | ||
| `gracePeriod` | integer | Period of time in seconds given to the resource to terminate gracefully. Ignored if negative. Set to 1 for immediate shutdown. | `-1` | | ||
| `timeout` | integer | The length of time (in seconds) to wait before giving up on a delete, zero means determine a timeout from the size of the object. | 0 | | ||
| `wait` | boolean | If true, wait for resources to be gone before returning. This waits for finalizers. | `true` | | ||
|
||
### Outputs | ||
|
||
This mixin will leverage the `kubectl get` command in order to populate outputs. Given the wide range of objects that can be created, the mixin will support JSON Path to specify how to retrieve values to populate outputs. Bundle authors will specify the object type, name and provide a JSONPath to obtain the data. For example, to obtain the ClusterIP of a a given service, consider the following porter.yaml excerpt: | ||
This mixin will leverage the `kubectl get` command in order to populate outputs. Given the wide range of objects that can be created, the mixin will support JSON Path to specify how to retrieve values to populate outputs. Bundle authors will specify the object type, name and provide a JSONPath to obtain the data. The mixin will not attempt further processing of the data, so if a JSONPath expression is given that results in multiple items, the JSON representing that will be stuck into the output as is. Namespace will default to `default` if not specified | ||
|
||
For example, to obtain the ClusterIP of a a given service, consider the following porter.yaml excerpt: | ||
|
||
```yaml | ||
install: | ||
|
@@ -108,7 +103,8 @@ install: | |
manifests: "/cnab/app/manifests/super-cool-app" | ||
outputs: | ||
- name: cluster_ip | ||
resource_type: "service" | ||
resource_name: "super-cool-service" | ||
jsonpath: "spec.clusterIP" | ||
resourceType: "service" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question on the switch from snakes to camels. Is that something that should be done for all outputs? Or because of k8s? I'm not quite clear on why you made the switch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just for consistency. |
||
resourceName: "super-cool-service" | ||
namespace: "cool" | ||
jsonPath: "spec.clusterIP" | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package kubernetes | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
const kubeVersion = "v1.13.0" | ||
const dockerFileContents = `RUN apt-get update && \ | ||
apt-get install -y apt-transport-https curl && \ | ||
curl -o kubectl https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl && \ | ||
mv kubectl /usr/local/bin && \ | ||
chmod a+x /usr/local/bin/kubectl | ||
` | ||
|
||
// Build generates the relevant Dockerfile output for this mixin | ||
func (m *Mixin) Build() error { | ||
_, err := fmt.Fprintf(m.Out, dockerFileContents, kubeVersion) | ||
return err | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package kubernetes | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/deislabs/porter/pkg/context" | ||
) | ||
|
||
type TestMixin struct { | ||
*Mixin | ||
TestContext *context.TestContext | ||
} | ||
|
||
func NewTestMixin(t *testing.T) *TestMixin { | ||
c := context.NewTestContext(t) | ||
m := New() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Thanks for picking up on this recent change. |
||
m.Context = c.Context | ||
return &TestMixin{ | ||
Mixin: m, | ||
TestContext: c, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've also figured out that we want
SilenceUsage: true,
here as well. Otherwise it prints the help text anytime the an error happens.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅