diff --git a/examples/annotated-skaffold.yaml b/examples/annotated-skaffold.yaml index d5e4b7b38c8..db2bf93fcf6 100644 --- a/examples/annotated-skaffold.yaml +++ b/examples/annotated-skaffold.yaml @@ -99,6 +99,12 @@ deploy: # manifests to deploy from files. manifests: - ../examples/getting-started/k8s-* + # kubectl can be passed additional option flags either on every command (Global), + # on creations (Apply) or deletions (Delete). + # flags: + # global: [""] + # apply: [""] + # delete: [""] # manifests to deploy from remote cluster. # The path to where these manifests live in remote kubernetes cluster. @@ -107,6 +113,16 @@ deploy: # - deployment/web-app1 # - namespace:deployment/web-app2 + # kustomize: + # kustomizePath: "kustomization.yaml" + # kustomize deploys manifests with kubectl. + # kubectl can be passed additional option flags either on every command (Global), + # on creations (Apply) or deletions (Delete). + # flags: + # global: [""] + # apply: [""] + # delete: [""] + # helm: # helm releases to deploy. # releases: diff --git a/pkg/skaffold/deploy/kubectl.go b/pkg/skaffold/deploy/kubectl.go index 80fd6e50701..a9d39e8b083 100644 --- a/pkg/skaffold/deploy/kubectl.go +++ b/pkg/skaffold/deploy/kubectl.go @@ -75,7 +75,7 @@ func (k *KubectlDeployer) Deploy(ctx context.Context, out io.Writer, builds []bu return nil, errors.Wrap(err, "replacing images in manifests") } - err = kubectl(manifests.reader(), out, k.kubeContext, "apply", "-f", "-") + err = kubectl(manifests.reader(), out, k.kubeContext, k.Flags.Global, "apply", k.Flags.Apply, "-f", "-") if err != nil { return nil, errors.Wrap(err, "deploying manifests") } @@ -90,7 +90,7 @@ func (k *KubectlDeployer) Cleanup(ctx context.Context, out io.Writer) error { return errors.Wrap(err, "reading manifests") } - if err := kubectl(manifests.reader(), out, k.kubeContext, "delete", "--grace-period=1", "--ignore-not-found=true", "-f", "-"); err != nil { + if err := kubectl(manifests.reader(), out, k.kubeContext, k.Flags.Global, "delete", k.Flags.Delete, "--grace-period=1", "--ignore-not-found=true", "-f", "-"); err != nil { return errors.Wrap(err, "deleting manifests") } @@ -101,8 +101,12 @@ func (k *KubectlDeployer) Dependencies() ([]string, error) { return k.manifestFiles(k.KubectlDeploy.Manifests) } -func kubectl(in io.Reader, out io.Writer, kubeContext string, arg ...string) error { - args := append([]string{"--context", kubeContext}, arg...) +func kubectl(in io.Reader, out io.Writer, kubeContext string, globalFlags []string, command string, commandFlags []string, arg ...string) error { + args := []string{"--context", kubeContext} + args = append(args, globalFlags...) + args = append(args, command) + args = append(args, commandFlags...) + args = append(args, arg...) cmd := exec.Command("kubectl", args...) cmd.Stdin = in @@ -182,10 +186,10 @@ func (k *KubectlDeployer) readRemoteManifest(name string) ([]byte, error) { args = append(args, "--namespace", parts[0]) name = parts[1] } - args = append(args, "get", name, "-o", "yaml") + args = append(args, name, "-o", "yaml") var manifest bytes.Buffer - err := kubectl(nil, &manifest, k.kubeContext, args...) + err := kubectl(nil, &manifest, k.kubeContext, k.Flags.Global, "get", nil, args...) if err != nil { return nil, errors.Wrap(err, "getting manifest") } diff --git a/pkg/skaffold/deploy/kubectl_test.go b/pkg/skaffold/deploy/kubectl_test.go index ea86123c16f..5017fa759cf 100644 --- a/pkg/skaffold/deploy/kubectl_test.go +++ b/pkg/skaffold/deploy/kubectl_test.go @@ -127,6 +127,25 @@ func TestKubectlDeploy(t *testing.T) { }, }, }, + { + description: "additional flags", + shouldErr: true, + cfg: &v1alpha2.KubectlDeploy{ + Manifests: []string{"test/deployment.yaml"}, + Flags: v1alpha2.KubectlFlags{ + Global: []string{"-v=0"}, + Apply: []string{"--overwrite=true"}, + Delete: []string{"ignored"}, + }, + }, + command: testutil.NewFakeCmd("kubectl --context kubecontext -v=0 apply --overwrite=true -f -", fmt.Errorf("")), + builds: []build.Artifact{ + { + ImageName: "leeroy-web", + Tag: "leeroy-web:123", + }, + }, + }, } tmp, cleanup := testutil.TempDir(t) @@ -172,6 +191,18 @@ func TestKubectlCleanup(t *testing.T) { command: testutil.NewFakeCmd("kubectl --context kubecontext delete --grace-period=1 --ignore-not-found=true -f -", errors.New("BUG")), shouldErr: true, }, + { + description: "additional flags", + cfg: &v1alpha2.KubectlDeploy{ + Manifests: []string{"test/deployment.yaml"}, + Flags: v1alpha2.KubectlFlags{ + Global: []string{"-v=0"}, + Apply: []string{"ignored"}, + Delete: []string{"--cascade=false"}, + }, + }, + command: testutil.NewFakeCmd("kubectl --context kubecontext -v=0 delete --cascade=false --grace-period=1 --ignore-not-found=true -f -", nil), + }, } tmp, cleanup := testutil.TempDir(t) diff --git a/pkg/skaffold/deploy/kustomize.go b/pkg/skaffold/deploy/kustomize.go index 36c177afca9..31092a9bbb9 100644 --- a/pkg/skaffold/deploy/kustomize.go +++ b/pkg/skaffold/deploy/kustomize.go @@ -62,7 +62,7 @@ func (k *KustomizeDeployer) Deploy(ctx context.Context, out io.Writer, builds [] if err != nil { return nil, errors.Wrap(err, "replacing images") } - if err := kubectl(manifestList.reader(), out, k.kubeContext, "apply", "-f", "-"); err != nil { + if err := kubectl(manifestList.reader(), out, k.kubeContext, k.Flags.Global, "apply", k.Flags.Apply, "-f", "-"); err != nil { return nil, errors.Wrap(err, "running kubectl") } return parseManifestsForDeploys(manifestList) @@ -88,7 +88,7 @@ func (k *KustomizeDeployer) Cleanup(ctx context.Context, out io.Writer) error { if err != nil { return errors.Wrap(err, "kustomize") } - if err := kubectl(manifests, out, k.kubeContext, "delete", "-f", "-"); err != nil { + if err := kubectl(manifests, out, k.kubeContext, k.Flags.Global, "delete", k.Flags.Delete, "-f", "-"); err != nil { return errors.Wrap(err, "kubectl delete") } return nil diff --git a/pkg/skaffold/schema/v1alpha2/config.go b/pkg/skaffold/schema/v1alpha2/config.go index f6a0f9daa84..7563dcadeb1 100644 --- a/pkg/skaffold/schema/v1alpha2/config.go +++ b/pkg/skaffold/schema/v1alpha2/config.go @@ -112,8 +112,18 @@ type DeployType struct { // KubectlDeploy contains the configuration needed for deploying with `kubectl apply` type KubectlDeploy struct { - Manifests []string `yaml:"manifests,omitempty"` - RemoteManifests []string `yaml:"remoteManifests,omitempty"` + Manifests []string `yaml:"manifests,omitempty"` + RemoteManifests []string `yaml:"remoteManifests,omitempty"` + Flags KubectlFlags `yaml:"flags,omitempty"` +} + +// KubectlFlags describes additional options flags that are passed on the command +// line to kubectl either on every command (Global), on creations (Apply) +// or deletions (Delete). +type KubectlFlags struct { + Global []string `yaml:"global,omitempty"` + Apply []string `yaml:"apply,omitempty"` + Delete []string `yaml:"delete,omitempty"` } // HelmDeploy contains the configuration needed for deploying with helm @@ -122,7 +132,8 @@ type HelmDeploy struct { } type KustomizeDeploy struct { - KustomizePath string `yaml:"kustomizePath,omitempty"` + KustomizePath string `yaml:"kustomizePath,omitempty"` + Flags KubectlFlags `yaml:"flags,omitempty"` } type HelmRelease struct {