From f3a7d854ce1a4afae520fc69701ee2bf1678cb29 Mon Sep 17 00:00:00 2001 From: Nick Kubala Date: Fri, 18 Sep 2020 16:45:52 -0700 Subject: [PATCH] Move deployers into separate packages --- Makefile | 2 +- cmd/skaffold/app/cmd/debug.go | 4 +- cmd/skaffold/app/cmd/filter.go | 7 +- integration/render_test.go | 9 +- pkg/skaffold/debug/debug.go | 9 +- pkg/skaffold/debug/debug_test.go | 4 +- pkg/skaffold/deploy/deploy_mux.go | 43 +--- pkg/skaffold/deploy/{ => helm}/helm.go | 22 +- pkg/skaffold/deploy/{ => helm}/helm_test.go | 26 +-- pkg/skaffold/deploy/helm/parse.go | 89 ++++++++ .../{util_test.go => helm/parse_test.go} | 20 +- pkg/skaffold/deploy/{ => kpt}/kpt.go | 56 ++--- pkg/skaffold/deploy/{ => kpt}/kpt_test.go | 25 ++- pkg/skaffold/deploy/kubectl/cli.go | 23 +- pkg/skaffold/deploy/kubectl/constants.go | 73 ++++++ pkg/skaffold/deploy/{ => kubectl}/kubectl.go | 52 ++--- .../deploy/{ => kubectl}/kubectl_test.go | 211 +++++++----------- .../deploy/{ => kustomize}/kustomize.go | 154 ++----------- .../deploy/{ => kustomize}/kustomize_test.go | 55 ++--- pkg/skaffold/deploy/kustomize/util.go | 141 ++++++++++++ pkg/skaffold/deploy/{ => label}/labeller.go | 6 +- pkg/skaffold/deploy/{ => label}/labels.go | 14 +- .../deploy/{ => label}/labels_test.go | 5 +- .../deploy/{ => status}/status_check.go | 11 +- .../deploy/{ => status}/status_check_test.go | 34 +-- pkg/skaffold/deploy/types/types.go | 40 ++++ pkg/skaffold/deploy/util.go | 172 -------------- pkg/skaffold/deploy/{ => util}/logfile.go | 2 +- .../deploy/{ => util}/logfile_test.go | 2 +- pkg/skaffold/deploy/util/stringset.go | 45 ++++ pkg/skaffold/deploy/util/util.go | 39 ++++ pkg/skaffold/initializer/analyze/helm.go | 2 +- pkg/skaffold/initializer/analyze/kustomize.go | 2 +- pkg/skaffold/initializer/deploy/kustomize.go | 4 +- pkg/skaffold/kubernetes/manifest/gcs.go | 43 ++++ .../kubectl => kubernetes/manifest}/images.go | 4 +- .../manifest}/images_test.go | 2 +- .../kubectl => kubernetes/manifest}/labels.go | 2 +- .../manifest}/labels_test.go | 2 +- .../manifest}/manifests.go | 2 +- .../manifest}/manifests_test.go | 2 +- .../manifest}/namespace_test.go | 2 +- .../manifest}/namespaces.go | 2 +- .../manifest}/transformations.go | 22 +- pkg/skaffold/kubernetes/manifest/util.go | 73 ++++++ .../manifest}/visitor.go | 2 +- .../manifest}/visitor_test.go | 2 +- .../portforward/resource_forwarder_test.go | 12 +- pkg/skaffold/runner/build_deploy.go | 4 +- pkg/skaffold/runner/deploy.go | 4 +- pkg/skaffold/runner/deploy_test.go | 7 +- pkg/skaffold/runner/new.go | 21 +- pkg/skaffold/runner/new_test.go | 16 +- pkg/skaffold/runner/runner.go | 6 +- pkg/skaffold/runner/runner_test.go | 15 +- 55 files changed, 925 insertions(+), 723 deletions(-) rename pkg/skaffold/deploy/{ => helm}/helm.go (97%) rename pkg/skaffold/deploy/{ => helm}/helm_test.go (99%) create mode 100644 pkg/skaffold/deploy/helm/parse.go rename pkg/skaffold/deploy/{util_test.go => helm/parse_test.go} (88%) rename pkg/skaffold/deploy/{ => kpt}/kpt.go (88%) rename pkg/skaffold/deploy/{ => kpt}/kpt_test.go (97%) create mode 100644 pkg/skaffold/deploy/kubectl/constants.go rename pkg/skaffold/deploy/{ => kubectl}/kubectl.go (87%) rename pkg/skaffold/deploy/{ => kubectl}/kubectl_test.go (80%) rename pkg/skaffold/deploy/{ => kustomize}/kustomize.go (65%) rename pkg/skaffold/deploy/{ => kustomize}/kustomize_test.go (91%) create mode 100644 pkg/skaffold/deploy/kustomize/util.go rename pkg/skaffold/deploy/{ => label}/labeller.go (95%) rename pkg/skaffold/deploy/{ => label}/labels.go (93%) rename pkg/skaffold/deploy/{ => label}/labels_test.go (95%) rename pkg/skaffold/deploy/{ => status}/status_check.go (95%) rename pkg/skaffold/deploy/{ => status}/status_check_test.go (95%) create mode 100644 pkg/skaffold/deploy/types/types.go delete mode 100644 pkg/skaffold/deploy/util.go rename pkg/skaffold/deploy/{ => util}/logfile.go (99%) rename pkg/skaffold/deploy/{ => util}/logfile_test.go (99%) create mode 100644 pkg/skaffold/deploy/util/stringset.go create mode 100644 pkg/skaffold/deploy/util/util.go create mode 100644 pkg/skaffold/kubernetes/manifest/gcs.go rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/images.go (97%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/images_test.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/labels.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/labels_test.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/manifests.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/manifests_test.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/namespace_test.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/namespaces.go (98%) rename pkg/skaffold/{deploy => kubernetes/manifest}/transformations.go (60%) create mode 100644 pkg/skaffold/kubernetes/manifest/util.go rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/visitor.go (99%) rename pkg/skaffold/{deploy/kubectl => kubernetes/manifest}/visitor_test.go (99%) diff --git a/Makefile b/Makefile index 6374aaf514c..664d89a9cc2 100644 --- a/Makefile +++ b/Makefile @@ -273,4 +273,4 @@ generate-schemas: # static files $(STATIK_FILES): go.mod docs/content/en/schemas/* - hack/generate-statik.sh + # hack/generate-statik.sh diff --git a/cmd/skaffold/app/cmd/debug.go b/cmd/skaffold/app/cmd/debug.go index 0202043c7be..734ac702dc5 100644 --- a/cmd/skaffold/app/cmd/debug.go +++ b/cmd/skaffold/app/cmd/debug.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" debugging "github.com/GoogleContainerTools/skaffold/pkg/skaffold/debug" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" ) // for tests @@ -44,7 +44,7 @@ func NewCmdDebug() *cobra.Command { func runDebug(ctx context.Context, out io.Writer) error { opts.PortForward.ForwardPods = true - deploy.AddManifestTransform(debugging.ApplyDebuggingTransforms) + manifest.AddManifestTransform(debugging.ApplyDebuggingTransforms) return doDev(ctx, out) } diff --git a/cmd/skaffold/app/cmd/filter.go b/cmd/skaffold/app/cmd/filter.go index 02aeb4f6373..db60e725b92 100644 --- a/cmd/skaffold/app/cmd/filter.go +++ b/cmd/skaffold/app/cmd/filter.go @@ -29,8 +29,7 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" debugging "github.com/GoogleContainerTools/skaffold/pkg/skaffold/debug" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" ) @@ -65,7 +64,7 @@ func runFilter(ctx context.Context, out io.Writer, debuggingFilters bool, buildA if err != nil { return err } - manifestList := kubectl.ManifestList([][]byte{bytes}) + manifestList := manifest.ManifestList([][]byte{bytes}) if debuggingFilters { // TODO(bdealwis): refactor this code debugHelpersRegistry, err := config.GetDebugHelpersRegistry(opts.GlobalConfig) @@ -77,7 +76,7 @@ func runFilter(ctx context.Context, out io.Writer, debuggingFilters bool, buildA return err } - manifestList, err = debugging.ApplyDebuggingTransforms(manifestList, buildArtifacts, deploy.Registries{ + manifestList, err = debugging.ApplyDebuggingTransforms(manifestList, buildArtifacts, manifest.Registries{ DebugHelpersRegistry: debugHelpersRegistry, InsecureRegistries: insecureRegistries, }) diff --git a/integration/render_test.go b/integration/render_test.go index a330351dc66..4b87c73b572 100644 --- a/integration/render_test.go +++ b/integration/render_test.go @@ -31,7 +31,8 @@ import ( "github.com/GoogleContainerTools/skaffold/integration/skaffold" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/helm" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/testutil" @@ -76,7 +77,7 @@ spec: t.NewTempDir(). Write("deployment.yaml", test.input). Chdir() - deployer, err := deploy.NewKubectlDeployer(&runcontext.RunContext{ + deployer, err := kubectl.NewKubectlDeployer(&runcontext.RunContext{ WorkingDir: ".", Cfg: latest.Pipeline{ Deploy: latest.DeployConfig{ @@ -231,7 +232,7 @@ spec: Write("deployment.yaml", test.input). Chdir() - deployer, err := deploy.NewKubectlDeployer(&runcontext.RunContext{ + deployer, err := kubectl.NewKubectlDeployer(&runcontext.RunContext{ WorkingDir: ".", Cfg: latest.Pipeline{ Deploy: latest.DeployConfig{ @@ -419,7 +420,7 @@ spec: } for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { - deployer := deploy.NewHelmDeployer(&runcontext.RunContext{ + deployer := helm.NewHelmDeployer(&runcontext.RunContext{ Cfg: latest.Pipeline{ Deploy: latest.DeployConfig{ DeployType: latest.DeployType{ diff --git a/pkg/skaffold/debug/debug.go b/pkg/skaffold/debug/debug.go index 38a8a7c7ce1..d530eaae007 100644 --- a/pkg/skaffold/debug/debug.go +++ b/pkg/skaffold/debug/debug.go @@ -29,9 +29,8 @@ import ( "k8s.io/client-go/kubernetes/scheme" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" ) @@ -50,7 +49,7 @@ var ( ) // ApplyDebuggingTransforms applies language-platform-specific transforms to a list of manifests. -func ApplyDebuggingTransforms(l kubectl.ManifestList, builds []build.Artifact, registries deploy.Registries) (kubectl.ManifestList, error) { +func ApplyDebuggingTransforms(l manifest.ManifestList, builds []build.Artifact, registries manifest.Registries) (manifest.ManifestList, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -63,8 +62,8 @@ func ApplyDebuggingTransforms(l kubectl.ManifestList, builds []build.Artifact, r return applyDebuggingTransforms(l, retriever, registries.DebugHelpersRegistry) } -func applyDebuggingTransforms(l kubectl.ManifestList, retriever configurationRetriever, debugHelpersRegistry string) (kubectl.ManifestList, error) { - var updated kubectl.ManifestList +func applyDebuggingTransforms(l manifest.ManifestList, retriever configurationRetriever, debugHelpersRegistry string) (manifest.ManifestList, error) { + var updated manifest.ManifestList for _, manifest := range l { obj, _, err := decodeFromYaml(manifest, nil, nil) if err != nil { diff --git a/pkg/skaffold/debug/debug_test.go b/pkg/skaffold/debug/debug_test.go index 8d275d2ccae..62dfc606e78 100644 --- a/pkg/skaffold/debug/debug_test.go +++ b/pkg/skaffold/debug/debug_test.go @@ -24,7 +24,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/testutil" ) @@ -509,7 +509,7 @@ spec: return imageConfiguration{}, nil } - result, err := applyDebuggingTransforms(kubectl.ManifestList{[]byte(test.in)}, retriever, "HELPERS") + result, err := applyDebuggingTransforms(manifest.ManifestList{[]byte(test.in)}, retriever, "HELPERS") t.CheckErrorAndDeepEqual(test.shouldErr, err, test.out, result.String()) }) diff --git a/pkg/skaffold/deploy/deploy_mux.go b/pkg/skaffold/deploy/deploy_mux.go index 6b74b94616e..12b89a9ded5 100644 --- a/pkg/skaffold/deploy/deploy_mux.go +++ b/pkg/skaffold/deploy/deploy_mux.go @@ -20,10 +20,11 @@ import ( "bytes" "context" "io" - "sort" "strings" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" ) // DeployerMux forwards all method calls to the deployers it contains. @@ -31,56 +32,30 @@ import ( // it collects the results and returns it in bulk. type DeployerMux []Deployer -type unit struct{} - -// stringSet helps to de-duplicate a set of strings. -type stringSet map[string]unit - -func newStringSet() stringSet { - return make(map[string]unit) -} - -// insert adds strings to the set. -func (s stringSet) insert(strings ...string) { - for _, item := range strings { - s[item] = unit{} - } -} - -// toList returns the sorted list of inserted strings. -func (s stringSet) toList() []string { - var res []string - for item := range s { - res = append(res, item) - } - sort.Strings(res) - return res -} - func (m DeployerMux) Deploy(ctx context.Context, w io.Writer, as []build.Artifact) ([]string, error) { - seenNamespaces := newStringSet() + seenNamespaces := util.NewStringSet() for _, deployer := range m { namespaces, err := deployer.Deploy(ctx, w, as) if err != nil { return nil, err } - seenNamespaces.insert(namespaces...) + seenNamespaces.Insert(namespaces...) } - return seenNamespaces.toList(), nil + return seenNamespaces.ToList(), nil } func (m DeployerMux) Dependencies() ([]string, error) { - deps := newStringSet() + deps := util.NewStringSet() for _, deployer := range m { result, err := deployer.Dependencies() if err != nil { return nil, err } - deps.insert(result...) + deps.Insert(result...) } - return deps.toList(), nil + return deps.ToList(), nil } func (m DeployerMux) Cleanup(ctx context.Context, w io.Writer) error { @@ -103,5 +78,5 @@ func (m DeployerMux) Render(ctx context.Context, w io.Writer, as []build.Artifac } allResources := strings.Join(resources, "\n---\n") - return outputRenderedManifests(allResources, filepath, w) + return manifest.OutputRenderedManifests(allResources, filepath, w) } diff --git a/pkg/skaffold/deploy/helm.go b/pkg/skaffold/deploy/helm/helm.go similarity index 97% rename from pkg/skaffold/deploy/helm.go rename to pkg/skaffold/deploy/helm/helm.go index 62461190eee..9ae1b48b9e2 100644 --- a/pkg/skaffold/deploy/helm.go +++ b/pkg/skaffold/deploy/helm/helm.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package helm import ( "bufio" @@ -35,7 +35,7 @@ import ( "time" "github.com/blang/semver" - "github.com/cenkalti/backoff/v4" + backoff "github.com/cenkalti/backoff/v4" "github.com/mitchellh/go-homedir" "github.com/sirupsen/logrus" @@ -43,7 +43,11 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/color" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/walk" @@ -90,7 +94,7 @@ type HelmDeployer struct { } // NewHelmDeployer returns a configured HelmDeployer -func NewHelmDeployer(cfg Config, labels map[string]string) *HelmDeployer { +func NewHelmDeployer(cfg kubectl.Config, labels map[string]string) *HelmDeployer { return &HelmDeployer{ HelmDeploy: cfg.Pipeline().Deploy.HelmDeploy, kubeContext: cfg.GetKubeContext(), @@ -111,7 +115,7 @@ func (h *HelmDeployer) Deploy(ctx context.Context, out io.Writer, builds []build logrus.Infof("Deploying with helm v%s ...", hv) - var dRes []Artifact + var dRes []types.Artifact nsMap := map[string]struct{}{} valuesSet := map[string]bool{} @@ -149,7 +153,7 @@ func (h *HelmDeployer) Deploy(ctx context.Context, out io.Writer, builds []build } } - if err := labelDeployResults(h.labels, dRes); err != nil { + if err := label.LabelDeployResults(h.labels, dRes); err != nil { return nil, fmt.Errorf("adding labels: %w", err) } @@ -321,7 +325,7 @@ func (h *HelmDeployer) Render(ctx context.Context, out io.Writer, builds []build renderedManifests.Write(outBuffer.Bytes()) } - return outputRenderedManifests(renderedManifests.String(), filepath, out) + return manifest.OutputRenderedManifests(renderedManifests.String(), filepath, out) } // exec executes the helm command, writing combined stdout/stderr to the provided writer @@ -350,7 +354,7 @@ func (h *HelmDeployer) exec(ctx context.Context, out io.Writer, useSecrets bool, } // deployRelease deploys a single release -func (h *HelmDeployer) deployRelease(ctx context.Context, out io.Writer, r latest.HelmRelease, builds []build.Artifact, valuesSet map[string]bool, helmVersion semver.Version) ([]Artifact, error) { +func (h *HelmDeployer) deployRelease(ctx context.Context, out io.Writer, r latest.HelmRelease, builds []build.Artifact, valuesSet map[string]bool, helmVersion semver.Version) ([]types.Artifact, error) { releaseName, err := util.ExpandEnvTemplate(r.Name, nil) if err != nil { return nil, fmt.Errorf("cannot parse the release name template: %w", err) @@ -413,10 +417,10 @@ func (h *HelmDeployer) deployRelease(ctx context.Context, out io.Writer, r lates } else { if r.UpgradeOnChange != nil && !*r.UpgradeOnChange { logrus.Infof("Release %s already installed...", releaseName) - return []Artifact{}, nil + return []types.Artifact{}, nil } else if r.UpgradeOnChange == nil && r.Remote { logrus.Infof("Release %s not upgraded as it is remote...", releaseName) - return []Artifact{}, nil + return []types.Artifact{}, nil } } diff --git a/pkg/skaffold/deploy/helm_test.go b/pkg/skaffold/deploy/helm/helm_test.go similarity index 99% rename from pkg/skaffold/deploy/helm_test.go rename to pkg/skaffold/deploy/helm/helm_test.go index 8a3573cd982..cd7ec59a089 100644 --- a/pkg/skaffold/deploy/helm_test.go +++ b/pkg/skaffold/deploy/helm/helm_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package helm import ( "context" @@ -26,6 +26,7 @@ import ( "github.com/mitchellh/go-homedir" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" schemautil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/util" @@ -307,9 +308,6 @@ var testDeployCreateNamespaceConfig = latest.HelmDeploy{ }}, } -var testNamespace = "testNamespace" -var testNamespace2 = "testNamespace2" - var validDeployYaml = ` # Source: skaffold-helm/templates/deployment.yaml apiVersion: apps/v1 @@ -485,7 +483,7 @@ func TestHelmDeploy(t *testing.T) { AndRun("helm --kube-context kubecontext upgrade skaffold-helm examples/test --namespace testNamespace -f skaffold-overrides.yaml --set-string image=docker.io:5000/skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184 --set some.key=somevalue --kubeconfig kubeconfig"). AndRun("helm --kube-context kubecontext get all --namespace testNamespace skaffold-helm --kubeconfig kubeconfig"), helm: testDeployConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, { @@ -530,7 +528,7 @@ func TestHelmDeploy(t *testing.T) { AndRun("helm --kube-context kubecontext upgrade skaffold-helm examples/test --namespace testNamespace -f skaffold-overrides.yaml --set-string image=docker.io:5000/skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184 --set some.key=somevalue --kubeconfig kubeconfig"). AndRun("helm --kube-context kubecontext get all --namespace testNamespace skaffold-helm --kubeconfig kubeconfig"), helm: testDeployConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, { @@ -542,7 +540,7 @@ func TestHelmDeploy(t *testing.T) { AndRun("helm --kube-context kubecontext upgrade skaffold-helm examples/test --namespace testNamespace -f skaffold-overrides.yaml --set-string image=docker.io:5000/skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184 --set some.key=somevalue --kubeconfig kubeconfig"). AndRun("helm --kube-context kubecontext get all --namespace testNamespace skaffold-helm --kubeconfig kubeconfig"), helm: testDeployNamespacedConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, { @@ -587,7 +585,7 @@ func TestHelmDeploy(t *testing.T) { AndRun("helm --kube-context kubecontext upgrade skaffold-helm examples/test --namespace testNamespace -f skaffold-overrides.yaml --set-string image=docker.io:5000/skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184 --set some.key=somevalue --kubeconfig kubeconfig"). AndRun("helm --kube-context kubecontext get all --namespace testNamespace skaffold-helm --kubeconfig kubeconfig"), helm: testDeployConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, { @@ -599,7 +597,7 @@ func TestHelmDeploy(t *testing.T) { AndRun("helm --kube-context kubecontext upgrade skaffold-helm examples/test --namespace testNamespace -f skaffold-overrides.yaml --set-string image=docker.io:5000/skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184 --set some.key=somevalue --kubeconfig kubeconfig"). AndRun("helm --kube-context kubecontext get all --namespace testNamespace skaffold-helm --kubeconfig kubeconfig"), helm: testDeployNamespacedConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, { @@ -1012,7 +1010,7 @@ func TestHelmCleanup(t *testing.T) { CmdRunWithOutput("helm version --client", version31). AndRun("helm --kube-context kubecontext delete skaffold-helm --namespace testNamespace --kubeconfig kubeconfig"), helm: testDeployConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, { @@ -1021,7 +1019,7 @@ func TestHelmCleanup(t *testing.T) { CmdRunWithOutput("helm version --client", version31). AndRun("helm --kube-context kubecontext delete skaffold-helm --namespace testNamespace --kubeconfig kubeconfig"), helm: testDeployNamespacedConfig, - namespace: testNamespace, + namespace: kubectl.TestNamespace, builds: testBuilds, }, } @@ -1066,7 +1064,7 @@ func TestParseHelmRelease(t *testing.T) { } for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { - _, err := parseRuntimeObject(testNamespace, test.yaml) + _, err := parseRuntimeObject(kubectl.TestNamespace, test.yaml) t.CheckError(test.shouldErr, err) }) @@ -1421,8 +1419,8 @@ type helmConfig struct { } func (c *helmConfig) ForceDeploy() bool { return c.force } -func (c *helmConfig) GetKubeConfig() string { return testKubeConfig } -func (c *helmConfig) GetKubeContext() string { return testKubeContext } +func (c *helmConfig) GetKubeConfig() string { return kubectl.TestKubeConfig } +func (c *helmConfig) GetKubeContext() string { return kubectl.TestKubeContext } func (c *helmConfig) GetKubeNamespace() string { return c.namespace } func (c *helmConfig) Pipeline() latest.Pipeline { var pipeline latest.Pipeline diff --git a/pkg/skaffold/deploy/helm/parse.go b/pkg/skaffold/deploy/helm/parse.go new file mode 100644 index 00000000000..b53819576e0 --- /dev/null +++ b/pkg/skaffold/deploy/helm/parse.go @@ -0,0 +1,89 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helm + +import ( + "bufio" + "bytes" + "fmt" + "io" + + k8syaml "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/kubernetes/scheme" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" + "github.com/sirupsen/logrus" +) + +func parseReleaseInfo(namespace string, b *bufio.Reader) []types.Artifact { + var results []types.Artifact + + r := k8syaml.NewYAMLReader(b) + for i := 0; ; i++ { + doc, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + logrus.Infof("error parsing object from string: %s", err.Error()) + continue + } + objNamespace, err := getObjectNamespaceIfDefined(doc, namespace) + if err != nil { + logrus.Infof("error parsing object from string: %s", err.Error()) + continue + } + obj, err := parseRuntimeObject(objNamespace, doc) + if err != nil { + if i > 0 { + logrus.Infof(err.Error()) + } + } else { + results = append(results, *obj) + logrus.Debugf("found deployed object: %+v", obj.Obj) + } + } + + return results +} + +func parseRuntimeObject(namespace string, b []byte) (*types.Artifact, error) { + d := scheme.Codecs.UniversalDeserializer() + obj, _, err := d.Decode(b, nil, nil) + if err != nil { + return nil, fmt.Errorf("error decoding parsed yaml: %s", err.Error()) + } + return &types.Artifact{ + Obj: obj, + Namespace: namespace, + }, nil +} + +func getObjectNamespaceIfDefined(doc []byte, ns string) (string, error) { + if i := bytes.Index(doc, []byte("apiVersion")); i >= 0 { + manifests := manifest.ManifestList{doc[i:]} + namespaces, err := manifests.CollectNamespaces() + if err != nil { + return ns, err + } + if len(namespaces) > 0 { + return namespaces[0], nil + } + } + return ns, nil +} diff --git a/pkg/skaffold/deploy/util_test.go b/pkg/skaffold/deploy/helm/parse_test.go similarity index 88% rename from pkg/skaffold/deploy/util_test.go rename to pkg/skaffold/deploy/helm/parse_test.go index bb7826a34c0..e5f99ba5563 100644 --- a/pkg/skaffold/deploy/util_test.go +++ b/pkg/skaffold/deploy/helm/parse_test.go @@ -1,5 +1,5 @@ /* -Copyright 2019 The Skaffold Authors +Copyright 2020 The Skaffold Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,23 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package helm import ( "bufio" "bytes" "testing" - "github.com/google/go-cmp/cmp/cmpopts" - + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" "github.com/GoogleContainerTools/skaffold/testutil" + "github.com/google/go-cmp/cmp/cmpopts" ) func TestParseReleaseInfo(t *testing.T) { tests := []struct { description string yaml []byte - expected []Artifact + expected []types.Artifact }{ { description: "parse valid release info yaml with single artifact with namespace", @@ -55,7 +55,7 @@ spec: selector: app: skaffold-helm release: skaffold-helm`), - expected: []Artifact{{Namespace: "test"}}, + expected: []types.Artifact{{Namespace: "test"}}, }, { description: "parse valid release info yaml with single artifact without namespace sets helm namespace", @@ -79,7 +79,7 @@ spec: selector: app: skaffold-helm release: skaffold-helm`), - expected: []Artifact{{ + expected: []types.Artifact{{ Namespace: "testNamespace", }}, }, @@ -126,7 +126,7 @@ spec: backend: serviceName: skaffold-helm-skaffold-helm servicePort: 80`), - expected: []Artifact{{Namespace: "testNamespace"}, {Namespace: "test"}}, + expected: []types.Artifact{{Namespace: "testNamespace"}, {Namespace: "test"}}, }, { description: "parse invalid release info yaml", @@ -138,9 +138,9 @@ spec: testutil.Run(t, test.description, func(t *testutil.T) { r := bufio.NewReader(bytes.NewBuffer(test.yaml)) - actual := parseReleaseInfo(testNamespace, r) + actual := parseReleaseInfo("testNamespace", r) - t.CheckDeepEqual(test.expected, actual, cmpopts.IgnoreFields(Artifact{}, "Obj")) + t.CheckDeepEqual(test.expected, actual, cmpopts.IgnoreFields(types.Artifact{}, "Obj")) }) } } diff --git a/pkg/skaffold/deploy/kpt.go b/pkg/skaffold/deploy/kpt/kpt.go similarity index 88% rename from pkg/skaffold/deploy/kpt.go rename to pkg/skaffold/deploy/kpt/kpt.go index 978371d9628..64e83c3f112 100644 --- a/pkg/skaffold/deploy/kpt.go +++ b/pkg/skaffold/deploy/kpt/kpt.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package kpt import ( "bytes" @@ -33,8 +33,11 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kustomize" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" + deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" ) @@ -56,12 +59,12 @@ type KptDeployer struct { globalConfig string } -func NewKptDeployer(ctx Config, labels map[string]string) *KptDeployer { +func NewKptDeployer(cfg types.Config, labels map[string]string) *KptDeployer { return &KptDeployer{ - KptDeploy: ctx.Pipeline().Deploy.KptDeploy, - insecureRegistries: ctx.GetInsecureRegistries(), + KptDeploy: cfg.Pipeline().Deploy.KptDeploy, + insecureRegistries: cfg.GetInsecureRegistries(), labels: labels, - globalConfig: ctx.GlobalConfig(), + globalConfig: cfg.GlobalConfig(), } } @@ -89,7 +92,7 @@ func (k *KptDeployer) Deploy(ctx context.Context, out io.Writer, builds []build. return nil, fmt.Errorf("getting applyDir: %w", err) } - outputRenderedManifests(manifests.String(), filepath.Join(applyDir, "resources.yaml"), out) + manifest.OutputRenderedManifests(manifests.String(), filepath.Join(applyDir, "resources.yaml"), out) cmd := exec.CommandContext(ctx, "kpt", kptCommandArgs(applyDir, []string{"live", "apply"}, k.getKptLiveApplyArgs(), nil)...) cmd.Stdout = out @@ -104,9 +107,9 @@ func (k *KptDeployer) Deploy(ctx context.Context, out io.Writer, builds []build. // Dependencies returns a list of files that the deployer depends on. This does NOT include applyDir. // In dev mode, a redeploy will be triggered if one of these files is updated. func (k *KptDeployer) Dependencies() ([]string, error) { - deps := newStringSet() + deps := deployutil.NewStringSet() if len(k.Fn.FnPath) > 0 { - deps.insert(k.Fn.FnPath) + deps.Insert(k.Fn.FnPath) } configDeps, err := getResources(k.Dir) @@ -114,17 +117,17 @@ func (k *KptDeployer) Dependencies() ([]string, error) { return nil, fmt.Errorf("finding dependencies in %s: %w", k.Dir, err) } - deps.insert(configDeps...) + deps.Insert(configDeps...) // Kpt deployer assumes that the kustomization configuration to build lives directly under k.Dir. - kustomizeDeps, err := dependenciesForKustomization(k.Dir) + kustomizeDeps, err := kustomize.DependenciesForKustomization(k.Dir) if err != nil { return nil, fmt.Errorf("finding kustomization directly under %s: %w", k.Dir, err) } - deps.insert(kustomizeDeps...) + deps.Insert(kustomizeDeps...) - return deps.toList(), nil + return deps.ToList(), nil } // Cleanup deletes what was deployed by calling `kpt live destroy`. @@ -151,13 +154,13 @@ func (k *KptDeployer) Render(ctx context.Context, out io.Writer, builds []build. return err } - return outputRenderedManifests(manifests.String(), filepath, out) + return manifest.OutputRenderedManifests(manifests.String(), filepath, out) } // renderManifests handles a majority of the hydration process for manifests. // This involves reading configs from a source directory, running kustomize build, running kpt pipelines, // adding image digests, and adding run-id labels. -func (k *KptDeployer) renderManifests(ctx context.Context, _ io.Writer, builds []build.Artifact) (deploy.ManifestList, error) { +func (k *KptDeployer) renderManifests(ctx context.Context, _ io.Writer, builds []build.Artifact) (manifest.ManifestList, error) { debugHelpersRegistry, err := config.GetDebugHelpersRegistry(k.globalConfig) if err != nil { return nil, fmt.Errorf("retrieving debug helpers registry: %w", err) @@ -202,11 +205,8 @@ func (k *KptDeployer) renderManifests(ctx context.Context, _ io.Writer, builds [ return nil, fmt.Errorf("replacing images in manifests: %w", err) } - for _, transform := range manifestTransforms { - manifests, err = transform(manifests, builds, Registries{k.insecureRegistries, debugHelpersRegistry}) - if err != nil { - return nil, fmt.Errorf("unable to transform manifests: %w", err) - } + if manifests, err = manifest.ApplyTransforms(manifests, builds, k.insecureRegistries, debugHelpersRegistry); err != nil { + return nil, err } return manifests.SetLabels(k.labels) @@ -232,17 +232,17 @@ func (k *KptDeployer) readConfigs(ctx context.Context) error { // kustomizeBuild runs `kustomize build` if a kustomization config exists and outputs to .pipeline. func (k *KptDeployer) kustomizeBuild(ctx context.Context) error { - if _, err := findKustomizationConfig(k.Dir); err != nil { + if _, err := kustomize.FindKustomizationConfig(k.Dir); err != nil { // No kustomization config was found directly under k.Dir, so there is no need to continue. return nil } - cmd := exec.CommandContext(ctx, "kustomize", buildCommandArgs([]string{"-o", filepath.Join(pipeline, k.Dir)}, k.Dir)...) + cmd := exec.CommandContext(ctx, "kustomize", kustomize.BuildCommandArgs([]string{"-o", filepath.Join(pipeline, k.Dir)}, k.Dir)...) if _, err := util.RunCmdOut(cmd); err != nil { return err } - deps, err := dependenciesForKustomization(k.Dir) + deps, err := kustomize.DependenciesForKustomization(k.Dir) if err != nil { return fmt.Errorf("finding kustomization dependencies: %w", err) } @@ -260,8 +260,8 @@ func (k *KptDeployer) kustomizeBuild(ctx context.Context) error { // kptFnRun does a dry run with the specified kpt functions (fn-path XOR image) against .pipeline. // If neither fn-path nor image are specified, functions will attempt to be discovered in .pipeline. // An error occurs if both fn-path and image are specified. -func (k *KptDeployer) kptFnRun(ctx context.Context) (deploy.ManifestList, error) { - var manifests deploy.ManifestList +func (k *KptDeployer) kptFnRun(ctx context.Context) (manifest.ManifestList, error) { + var manifests manifest.ManifestList flags, err := k.getKptFnRunArgs() if err != nil { @@ -283,9 +283,9 @@ func (k *KptDeployer) kptFnRun(ctx context.Context) (deploy.ManifestList, error) // excludeKptFn adds an annotation "config.kubernetes.io/local-config: 'true'" to kpt function. // This will exclude kpt functions from deployed to the cluster in kpt live apply. -func (k *KptDeployer) excludeKptFn(manifest deploy.ManifestList) (deploy.ManifestList, error) { - var newManifest deploy.ManifestList - for _, yByte := range manifest { +func (k *KptDeployer) excludeKptFn(originalManifest manifest.ManifestList) (manifest.ManifestList, error) { + var newManifest manifest.ManifestList + for _, yByte := range originalManifest { // Convert yaml byte config to unstructured.Unstructured jByte, _ := k8syaml.YAMLToJSON(yByte) var obj unstructured.Unstructured diff --git a/pkg/skaffold/deploy/kpt_test.go b/pkg/skaffold/deploy/kpt/kpt_test.go similarity index 97% rename from pkg/skaffold/deploy/kpt_test.go rename to pkg/skaffold/deploy/kpt/kpt_test.go index 127d89a1ddf..21bed3fd768 100644 --- a/pkg/skaffold/deploy/kpt_test.go +++ b/pkg/skaffold/deploy/kpt/kpt_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package kpt import ( "bytes" @@ -28,7 +28,8 @@ import ( "testing" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" - deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" @@ -921,13 +922,13 @@ spec: name: image1`) tests := []struct { description string - manifests deploy.ManifestList - expected deploy.ManifestList + manifests manifest.ManifestList + expected manifest.ManifestList }{ { description: "Add `local-config` annotation to kpt fn", - manifests: deploy.ManifestList{testFn1}, - expected: deploy.ManifestList{[]byte(`apiVersion: v1 + manifests: manifest.ManifestList{testFn1}, + expected: manifest.ManifestList{[]byte(`apiVersion: v1 data: annotation_name: k1 annotation_value: v1 @@ -939,8 +940,8 @@ metadata: }, { description: "Skip preset `local-config` annotation", - manifests: deploy.ManifestList{testFn2}, - expected: deploy.ManifestList{[]byte(`apiVersion: v1 + manifests: manifest.ManifestList{testFn2}, + expected: manifest.ManifestList{[]byte(`apiVersion: v1 kind: ConfigMap metadata: annotations: @@ -952,8 +953,8 @@ data: }, { description: "Valid in kpt fn pipeline.", - manifests: deploy.ManifestList{testFn1, testFn2, testPod}, - expected: deploy.ManifestList{[]byte(`apiVersion: v1 + manifests: manifest.ManifestList{testFn1, testFn2, testPod}, + expected: manifest.ManifestList{[]byte(`apiVersion: v1 data: annotation_name: k1 annotation_value: v1 @@ -995,8 +996,8 @@ type kptConfig struct { } func (c *kptConfig) WorkingDir() string { return c.workingDir } -func (c *kptConfig) GetKubeContext() string { return testKubeContext } -func (c *kptConfig) GetKubeNamespace() string { return testNamespace } +func (c *kptConfig) GetKubeContext() string { return kubectl.TestKubeContext } +func (c *kptConfig) GetKubeNamespace() string { return kubectl.TestNamespace } func (c *kptConfig) Pipeline() latest.Pipeline { var pipeline latest.Pipeline pipeline.Deploy.DeployType.KptDeploy = &c.kpt diff --git a/pkg/skaffold/deploy/kubectl/cli.go b/pkg/skaffold/deploy/kubectl/cli.go index cfae6023663..81bd68beb94 100644 --- a/pkg/skaffold/deploy/kubectl/cli.go +++ b/pkg/skaffold/deploy/kubectl/cli.go @@ -27,22 +27,25 @@ import ( "github.com/sirupsen/logrus" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - pkgkubectl "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" + deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" + kubectl "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" ) // CLI holds parameters to run kubectl. type CLI struct { - *pkgkubectl.CLI + *kubectl.CLI Flags latest.KubectlFlags forceDeploy bool waitForDeletions config.WaitForDeletions - previousApply ManifestList + previousApply manifest.ManifestList } type Config interface { - pkgkubectl.Config + kubectl.Config + deploy.Config ForceDeploy() bool WaitForDeletions() config.WaitForDeletions Mode() config.RunMode @@ -50,7 +53,7 @@ type Config interface { func NewCLI(cfg Config, flags latest.KubectlFlags, defaultNameSpace string) CLI { return CLI{ - CLI: pkgkubectl.NewCLI(cfg, defaultNameSpace), + CLI: kubectl.NewCLI(cfg, defaultNameSpace), Flags: flags, forceDeploy: cfg.ForceDeploy(), waitForDeletions: cfg.WaitForDeletions(), @@ -58,7 +61,7 @@ func NewCLI(cfg Config, flags latest.KubectlFlags, defaultNameSpace string) CLI } // Delete runs `kubectl delete` on a list of manifests. -func (c *CLI) Delete(ctx context.Context, out io.Writer, manifests ManifestList) error { +func (c *CLI) Delete(ctx context.Context, out io.Writer, manifests manifest.ManifestList) error { args := c.args(c.Flags.Delete, "--ignore-not-found=true", "-f", "-") if err := c.Run(ctx, manifests.Reader(), out, "delete", args...); err != nil { return fmt.Errorf("kubectl delete: %w", err) @@ -68,7 +71,7 @@ func (c *CLI) Delete(ctx context.Context, out io.Writer, manifests ManifestList) } // Apply runs `kubectl apply` on a list of manifests. -func (c *CLI) Apply(ctx context.Context, out io.Writer, manifests ManifestList) error { +func (c *CLI) Apply(ctx context.Context, out io.Writer, manifests manifest.ManifestList) error { // Only redeploy modified or new manifests // TODO(dgageot): should we delete a manifest that was deployed and is not anymore? updated := c.previousApply.Diff(manifests) @@ -104,7 +107,7 @@ type getResult struct { } // WaitForDeletions waits for resource marked for deletion to complete their deletion. -func (c *CLI) WaitForDeletions(ctx context.Context, out io.Writer, manifests ManifestList) error { +func (c *CLI) WaitForDeletions(ctx context.Context, out io.Writer, manifests manifest.ManifestList) error { if !c.waitForDeletions.Enabled { return nil } @@ -169,7 +172,7 @@ func (c *CLI) WaitForDeletions(ctx context.Context, out io.Writer, manifests Man } // ReadManifests reads a list of manifests in yaml format. -func (c *CLI) ReadManifests(ctx context.Context, manifests []string) (ManifestList, error) { +func (c *CLI) ReadManifests(ctx context.Context, manifests []string) (manifest.ManifestList, error) { var list []string for _, manifest := range manifests { list = append(list, "-f", manifest) @@ -194,7 +197,7 @@ func (c *CLI) ReadManifests(ctx context.Context, manifests []string) (ManifestLi return nil, fmt.Errorf("kubectl create: %w", err) } - var manifestList ManifestList + var manifestList manifest.ManifestList manifestList.Append(buf) return manifestList, nil diff --git a/pkg/skaffold/deploy/kubectl/constants.go b/pkg/skaffold/deploy/kubectl/constants.go new file mode 100644 index 00000000000..ca374fcc267 --- /dev/null +++ b/pkg/skaffold/deploy/kubectl/constants.go @@ -0,0 +1,73 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubectl + +const ( + KubectlVersion112 = `{"clientVersion":{"major":"1","minor":"12"}}` + KubectlVersion118 = `{"clientVersion":{"major":"1","minor":"18"}}` +) + +var TestKubeConfig = "kubeconfig" +var TestKubeContext = "kubecontext" +var TestNamespace = "testNamespace" +var TestNamespace2 = "testNamespace2" +var TestNamespace2FromEnvTemplate = "test{{.MYENV}}ace2" // needs `MYENV=Namesp` environment variable + +const DeploymentWebYAML = `apiVersion: v1 +kind: Pod +metadata: + name: leeroy-web +spec: + containers: + - name: leeroy-web + image: leeroy-web` + +const DeploymentWebYAMLv1 = `apiVersion: v1 +kind: Pod +metadata: + name: leeroy-web +spec: + containers: + - image: leeroy-web:v1 + name: leeroy-web` + +const DeploymentAppYAML = `apiVersion: v1 +kind: Pod +metadata: + name: leeroy-app +spec: + containers: + - name: leeroy-app + image: leeroy-app` + +const DeploymentAppYAMLv1 = `apiVersion: v1 +kind: Pod +metadata: + name: leeroy-app +spec: + containers: + - image: leeroy-app:v1 + name: leeroy-app` + +const DeploymentAppYAMLv2 = `apiVersion: v1 +kind: Pod +metadata: + name: leeroy-app +spec: + containers: + - image: leeroy-app:v2 + name: leeroy-app` diff --git a/pkg/skaffold/deploy/kubectl.go b/pkg/skaffold/deploy/kubectl/kubectl.go similarity index 87% rename from pkg/skaffold/deploy/kubectl.go rename to pkg/skaffold/deploy/kubectl/kubectl.go index 8da56963b4e..c1acc91f86d 100644 --- a/pkg/skaffold/deploy/kubectl.go +++ b/pkg/skaffold/deploy/kubectl/kubectl.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package kubectl import ( "bytes" @@ -32,10 +32,10 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/color" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" ) @@ -47,24 +47,14 @@ type KubectlDeployer struct { originalImages []build.Artifact workingDir string globalConfig string + gcsManifestDir string defaultRepo *string - kubectl deploy.CLI + kubectl CLI insecureRegistries map[string]bool labels map[string]string skipRender bool } -type Config interface { - deploy.Config - docker.Config - - Pipeline() latest.Pipeline - GetWorkingDir() string - GlobalConfig() string - DefaultRepo() *string - SkipRender() bool -} - // NewKubectlDeployer returns a new KubectlDeployer for a DeployConfig filled // with the needed configuration for `kubectl apply` func NewKubectlDeployer(cfg Config, labels map[string]string) (*KubectlDeployer, error) { @@ -82,7 +72,7 @@ func NewKubectlDeployer(cfg Config, labels map[string]string) (*KubectlDeployer, workingDir: cfg.GetWorkingDir(), globalConfig: cfg.GlobalConfig(), defaultRepo: cfg.DefaultRepo(), - kubectl: deploy.NewCLI(cfg, cfg.Pipeline().Deploy.KubectlDeploy.Flags, defaultNamespace), + kubectl: NewCLI(cfg, cfg.Pipeline().Deploy.KubectlDeploy.Flags, defaultNamespace), insecureRegistries: cfg.GetInsecureRegistries(), skipRender: cfg.SkipRender(), labels: labels, @@ -93,7 +83,7 @@ func NewKubectlDeployer(cfg Config, labels map[string]string) (*KubectlDeployer, // runs `kubectl apply` on those manifests func (k *KubectlDeployer) Deploy(ctx context.Context, out io.Writer, builds []build.Artifact) ([]string, error) { var ( - manifests deploy.ManifestList + manifests manifest.ManifestList err error ) if k.skipRender { @@ -145,10 +135,11 @@ func (k *KubectlDeployer) manifestFiles(manifests []string) ([]string, error) { if len(gcsManifests) != 0 { // return tmp dir of the downloaded manifests - tmpDir, err := downloadManifestsFromGCS(gcsManifests) + tmpDir, err := manifest.DownloadManifestsFromGCS(gcsManifests) if err != nil { return nil, fmt.Errorf("downloading from GCS: %w", err) } + k.gcsManifestDir = tmpDir l, err := util.ExpandPathsGlob(tmpDir, []string{"*"}) if err != nil { return nil, fmt.Errorf("expanding kubectl manifest paths: %w", err) @@ -172,11 +163,11 @@ func (k *KubectlDeployer) manifestFiles(manifests []string) ([]string, error) { } // readManifests reads the manifests to deploy/delete. -func (k *KubectlDeployer) readManifests(ctx context.Context, offline bool) (deploy.ManifestList, error) { +func (k *KubectlDeployer) readManifests(ctx context.Context, offline bool) (manifest.ManifestList, error) { // Get file manifests manifests, err := k.Dependencies() // Clean the temporary directory that holds the manifests downloaded from GCS - defer os.RemoveAll(manifestTmpDir) + defer os.RemoveAll(k.gcsManifestDir) if err != nil { return nil, fmt.Errorf("listing manifests: %w", err) @@ -192,7 +183,7 @@ func (k *KubectlDeployer) readManifests(ctx context.Context, offline bool) (depl } if len(manifests) == 0 { - return deploy.ManifestList{}, nil + return manifest.ManifestList{}, nil } if !offline { @@ -205,7 +196,7 @@ func (k *KubectlDeployer) readManifests(ctx context.Context, offline bool) (depl return nil, errors.New("cannot use offline mode if URL manifests are configured") } - var manifestList deploy.ManifestList + var manifestList manifest.ManifestList for _, manifestFilePath := range manifests { manifestFileContent, err := ioutil.ReadFile(manifestFilePath) if err != nil { @@ -242,10 +233,10 @@ func (k *KubectlDeployer) Render(ctx context.Context, out io.Writer, builds []bu return err } - return outputRenderedManifests(manifests.String(), filepath, out) + return manifest.OutputRenderedManifests(manifests.String(), filepath, out) } -func (k *KubectlDeployer) renderManifests(ctx context.Context, out io.Writer, builds []build.Artifact, offline bool) (deploy.ManifestList, error) { +func (k *KubectlDeployer) renderManifests(ctx context.Context, out io.Writer, builds []build.Artifact, offline bool) (manifest.ManifestList, error) { if err := k.kubectl.CheckVersion(ctx); err != nil { color.Default.Fprintln(out, "kubectl client version:", k.kubectl.Version(ctx)) color.Default.Fprintln(out, err) @@ -283,7 +274,7 @@ func (k *KubectlDeployer) renderManifests(ctx context.Context, out io.Writer, bu if len(builds) == 0 { for _, artifact := range k.originalImages { - tag, err := ApplyDefaultRepo(k.globalConfig, k.defaultRepo, artifact.Tag) + tag, err := deployutil.ApplyDefaultRepo(k.globalConfig, k.defaultRepo, artifact.Tag) if err != nil { return nil, err } @@ -296,14 +287,11 @@ func (k *KubectlDeployer) renderManifests(ctx context.Context, out io.Writer, bu manifests, err = manifests.ReplaceImages(builds) if err != nil { - return nil, fmt.Errorf("replacing images in manifests: %w", err) + return nil, err } - for _, transform := range manifestTransforms { - manifests, err = transform(manifests, builds, Registries{k.insecureRegistries, debugHelpersRegistry}) - if err != nil { - return nil, fmt.Errorf("unable to transform manifests: %w", err) - } + if manifests, err = manifest.ApplyTransforms(manifests, builds, k.insecureRegistries, debugHelpersRegistry); err != nil { + return nil, err } return manifests.SetLabels(k.labels) @@ -320,7 +308,7 @@ func (k *KubectlDeployer) Cleanup(ctx context.Context, out io.Writer) error { // TODO(dgageot): That seems super dangerous and I don't understand // why we need to update resources just before we delete them. if len(k.RemoteManifests) > 0 { - var rm deploy.ManifestList + var rm manifest.ManifestList for _, m := range k.RemoteManifests { manifest, err := k.readRemoteManifest(ctx, m) if err != nil { diff --git a/pkg/skaffold/deploy/kubectl_test.go b/pkg/skaffold/deploy/kubectl/kubectl_test.go similarity index 80% rename from pkg/skaffold/deploy/kubectl_test.go rename to pkg/skaffold/deploy/kubectl/kubectl_test.go index 2b9e762676e..276184850c3 100644 --- a/pkg/skaffold/deploy/kubectl_test.go +++ b/pkg/skaffold/deploy/kubectl/kubectl_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package kubectl import ( "bytes" @@ -29,66 +29,13 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" "github.com/GoogleContainerTools/skaffold/testutil" ) -const ( - testKubeContext = "kubecontext" - testKubeConfig = "kubeconfig" - kubectlVersion112 = `{"clientVersion":{"major":"1","minor":"12"}}` - kubectlVersion118 = `{"clientVersion":{"major":"1","minor":"18"}}` -) - -var testNamespace2FromEnvTemplate = "test{{.MYENV}}ace2" // needs `MYENV=Namesp` environment variable - -const deploymentWebYAML = `apiVersion: v1 -kind: Pod -metadata: - name: leeroy-web -spec: - containers: - - name: leeroy-web - image: leeroy-web` - -const deploymentWebYAMLv1 = `apiVersion: v1 -kind: Pod -metadata: - name: leeroy-web -spec: - containers: - - image: leeroy-web:v1 - name: leeroy-web` - -const deploymentAppYAML = `apiVersion: v1 -kind: Pod -metadata: - name: leeroy-app -spec: - containers: - - name: leeroy-app - image: leeroy-app` - -const deploymentAppYAMLv1 = `apiVersion: v1 -kind: Pod -metadata: - name: leeroy-app -spec: - containers: - - image: leeroy-app:v1 - name: leeroy-app` - -const deploymentAppYAMLv2 = `apiVersion: v1 -kind: Pod -metadata: - name: leeroy-app -spec: - containers: - - image: leeroy-app:v2 - name: leeroy-app` - func TestKubectlDeploy(t *testing.T) { tests := []struct { description string @@ -104,7 +51,7 @@ func TestKubectlDeploy(t *testing.T) { { description: "no manifest", kubectl: latest.KubectlDeploy{}, - commands: testutil.CmdRunOut("kubectl version --client -ojson", kubectlVersion112), + commands: testutil.CmdRunOut("kubectl version --client -ojson", KubectlVersion112), waitForDeletions: true, }, { @@ -116,9 +63,9 @@ func TestKubectlDeploy(t *testing.T) { }, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml --validate=false", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml --validate=false", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f - --validate=false"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -132,9 +79,9 @@ func TestKubectlDeploy(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f - --force --grace-period=0"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -149,9 +96,9 @@ func TestKubectlDeploy(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f -"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -165,9 +112,9 @@ func TestKubectlDeploy(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion118). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run=client -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion118). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run=client -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f -"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -179,12 +126,12 @@ func TestKubectlDeploy(t *testing.T) { description: "deploy success (default namespace)", kubectl: latest.KubectlDeploy{ Manifests: []string{"deployment.yaml"}, - DefaultNamespace: &testNamespace2, + DefaultNamespace: &TestNamespace2, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion118). - AndRunOut("kubectl --context kubecontext --namespace testNamespace2 create --dry-run=client -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion118). + AndRunOut("kubectl --context kubecontext --namespace testNamespace2 create --dry-run=client -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace2 apply -f -"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -197,12 +144,12 @@ func TestKubectlDeploy(t *testing.T) { description: "deploy success (default namespace with env template)", kubectl: latest.KubectlDeploy{ Manifests: []string{"deployment.yaml"}, - DefaultNamespace: &testNamespace2FromEnvTemplate, + DefaultNamespace: &TestNamespace2FromEnvTemplate, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion118). - AndRunOut("kubectl --context kubecontext --namespace testNamespace2 create --dry-run=client -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion118). + AndRunOut("kubectl --context kubecontext --namespace testNamespace2 create --dry-run=client -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace2 apply -f -"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -220,9 +167,9 @@ func TestKubectlDeploy(t *testing.T) { Manifests: []string{"deployment.yaml", "http://remote.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml -f http://remote.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml -f http://remote.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f -"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -236,9 +183,9 @@ func TestKubectlDeploy(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRunErr("kubectl --context kubecontext --namespace testNamespace apply -f -", fmt.Errorf("")), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -258,9 +205,9 @@ func TestKubectlDeploy(t *testing.T) { }, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create -v=0 --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -v=0 -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create -v=0 --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -v=0 -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). AndRunErr("kubectl --context kubecontext --namespace testNamespace apply -v=0 --overwrite=true -f -", fmt.Errorf("")), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -275,13 +222,13 @@ func TestKubectlDeploy(t *testing.T) { t.SetEnvs(test.envs) t.Override(&util.DefaultExecCommand, test.commands) t.NewTempDir(). - Write("deployment.yaml", deploymentWebYAML). + Write("deployment.yaml", DeploymentWebYAML). Touch("empty.ignored"). Chdir() skaffoldNamespaceOption := "" if !test.skipSkaffoldNamespaceOption { - skaffoldNamespaceOption = testNamespace + skaffoldNamespaceOption = TestNamespace } k, err := NewKubectlDeployer(&kubectlConfig{ @@ -318,8 +265,8 @@ func TestKubectlCleanup(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). AndRun("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -"), }, { @@ -328,8 +275,8 @@ func TestKubectlCleanup(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion118). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run=client -oyaml -f deployment.yaml", deploymentWebYAML). + CmdRunOut("kubectl version --client -ojson", KubectlVersion118). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run=client -oyaml -f deployment.yaml", DeploymentWebYAML). AndRun("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -"), }, { @@ -338,8 +285,8 @@ func TestKubectlCleanup(t *testing.T) { Manifests: []string{"deployment.yaml"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). AndRunErr("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -", errors.New("BUG")), shouldErr: true, }, @@ -354,8 +301,8 @@ func TestKubectlCleanup(t *testing.T) { }, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create -v=0 --dry-run -oyaml -f deployment.yaml", deploymentWebYAML). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create -v=0 --dry-run -oyaml -f deployment.yaml", DeploymentWebYAML). AndRun("kubectl --context kubecontext --namespace testNamespace delete -v=0 --grace-period=1 --ignore-not-found=true -f -"), }, } @@ -363,13 +310,13 @@ func TestKubectlCleanup(t *testing.T) { testutil.Run(t, test.description, func(t *testutil.T) { t.Override(&util.DefaultExecCommand, test.commands) t.NewTempDir(). - Write("deployment.yaml", deploymentWebYAML). + Write("deployment.yaml", DeploymentWebYAML). Chdir() k, err := NewKubectlDeployer(&kubectlConfig{ workingDir: ".", kubectl: test.kubectl, - RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: testNamespace}}, + RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: TestNamespace}}, }, nil) t.RequireNoError(err) @@ -394,7 +341,7 @@ func TestKubectlDeployerRemoteCleanup(t *testing.T) { commands: testutil. CmdRun("kubectl --context kubecontext --namespace testNamespace get pod/leeroy-web -o yaml"). AndRun("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -"). - AndRunInput("kubectl --context kubecontext --namespace testNamespace apply -f -", deploymentWebYAML), + AndRunInput("kubectl --context kubecontext --namespace testNamespace apply -f -", DeploymentWebYAML), }, { description: "cleanup error", @@ -404,20 +351,20 @@ func TestKubectlDeployerRemoteCleanup(t *testing.T) { commands: testutil. CmdRun("kubectl --context kubecontext --namespace anotherNamespace get pod/leeroy-web -o yaml"). AndRun("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -"). - AndRunInput("kubectl --context kubecontext --namespace anotherNamespace apply -f -", deploymentWebYAML), + AndRunInput("kubectl --context kubecontext --namespace anotherNamespace apply -f -", DeploymentWebYAML), }, } for _, test := range tests { testutil.Run(t, "cleanup remote", func(t *testutil.T) { t.Override(&util.DefaultExecCommand, test.commands) t.NewTempDir(). - Write("deployment.yaml", deploymentWebYAML). + Write("deployment.yaml", DeploymentWebYAML). Chdir() k, err := NewKubectlDeployer(&kubectlConfig{ workingDir: ".", kubectl: test.kubectl, - RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: testNamespace}}, + RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: TestNamespace}}, }, nil) t.RequireNoError(err) @@ -431,19 +378,19 @@ func TestKubectlDeployerRemoteCleanup(t *testing.T) { func TestKubectlRedeploy(t *testing.T) { testutil.Run(t, "", func(t *testutil.T) { tmpDir := t.NewTempDir(). - Write("deployment-web.yaml", deploymentWebYAML). - Write("deployment-app.yaml", deploymentAppYAML) + Write("deployment-web.yaml", DeploymentWebYAML). + Write("deployment-app.yaml", DeploymentAppYAML) t.Override(&util.DefaultExecCommand, testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-app.yaml")+" -f "+tmpDir.Path("deployment-web.yaml"), deploymentAppYAML+"\n"+deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentAppYAMLv1+"\n---\n"+deploymentWebYAMLv1, ""). - AndRunInput("kubectl --context kubecontext apply -f -", deploymentAppYAMLv1+"\n---\n"+deploymentWebYAMLv1). - AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-app.yaml")+" -f "+tmpDir.Path("deployment-web.yaml"), deploymentAppYAML+"\n"+deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentAppYAMLv2+"\n---\n"+deploymentWebYAMLv1, ""). - AndRunInput("kubectl --context kubecontext apply -f -", deploymentAppYAMLv2). - AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-app.yaml")+" -f "+tmpDir.Path("deployment-web.yaml"), deploymentAppYAML+"\n"+deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentAppYAMLv2+"\n---\n"+deploymentWebYAMLv1, ""), + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-app.yaml")+" -f "+tmpDir.Path("deployment-web.yaml"), DeploymentAppYAML+"\n"+DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentAppYAMLv1+"\n---\n"+DeploymentWebYAMLv1, ""). + AndRunInput("kubectl --context kubecontext apply -f -", DeploymentAppYAMLv1+"\n---\n"+DeploymentWebYAMLv1). + AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-app.yaml")+" -f "+tmpDir.Path("deployment-web.yaml"), DeploymentAppYAML+"\n"+DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentAppYAMLv2+"\n---\n"+DeploymentWebYAMLv1, ""). + AndRunInput("kubectl --context kubecontext apply -f -", DeploymentAppYAMLv2). + AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-app.yaml")+" -f "+tmpDir.Path("deployment-web.yaml"), DeploymentAppYAML+"\n"+DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentAppYAMLv2+"\n---\n"+DeploymentWebYAMLv1, ""), ) deployer, err := NewKubectlDeployer(&kubectlConfig{ @@ -482,33 +429,33 @@ func TestKubectlRedeploy(t *testing.T) { func TestKubectlWaitForDeletions(t *testing.T) { testutil.Run(t, "", func(t *testutil.T) { - tmpDir := t.NewTempDir().Write("deployment-web.yaml", deploymentWebYAML) + tmpDir := t.NewTempDir().Write("deployment-web.yaml", DeploymentWebYAML) t.Override(&util.DefaultExecCommand, testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-web.yaml"), deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, `{ + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-web.yaml"), DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, `{ "items":[ {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-web"}}, {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-app"}}, {"metadata":{"name":"leeroy-front"}} ] }`). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, `{ + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, `{ "items":[ {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-web"}}, {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-app"}}, {"metadata":{"name":"leeroy-front"}} ] }`). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, `{ + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, `{ "items":[ {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-web"}}, {"metadata":{"name":"leeroy-front"}} ] }`). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). - AndRunInput("kubectl --context kubecontext apply -f -", deploymentWebYAMLv1), + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, ""). + AndRunInput("kubectl --context kubecontext apply -f -", DeploymentWebYAMLv1), ) deployer, err := NewKubectlDeployer(&kubectlConfig{ @@ -538,12 +485,12 @@ func TestKubectlWaitForDeletions(t *testing.T) { func TestKubectlWaitForDeletionsFails(t *testing.T) { testutil.Run(t, "", func(t *testutil.T) { - tmpDir := t.NewTempDir().Write("deployment-web.yaml", deploymentWebYAML) + tmpDir := t.NewTempDir().Write("deployment-web.yaml", DeploymentWebYAML) t.Override(&util.DefaultExecCommand, testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-web.yaml"), deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, `{ + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment-web.yaml"), DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext get -f - --ignore-not-found -ojson", DeploymentWebYAMLv1, `{ "items":[ {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-web"}}, {"metadata":{"deletionTimestamp":"2020-07-24T12:40:32Z","name":"leeroy-app"}} @@ -737,7 +684,7 @@ spec: testutil.Run(t, test.description, func(t *testutil.T) { tmpDir := t.NewTempDir().Write("deployment.yaml", test.input) t.Override(&util.DefaultExecCommand, testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). + CmdRunOut("kubectl version --client -ojson", KubectlVersion112). AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f "+tmpDir.Path("deployment.yaml"), test.input)) deployer, err := NewKubectlDeployer(&kubectlConfig{ workingDir: ".", @@ -769,26 +716,26 @@ func TestGCSManifests(t *testing.T) { Manifests: []string{"gs://dev/deployment.yaml"}, }, commands: testutil. - CmdRunOut(fmt.Sprintf("gsutil cp -r %s %s", "gs://dev/deployment.yaml", manifestTmpDir), "log"). - AndRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f "+filepath.Join(manifestTmpDir, "deployment.yaml"), deploymentWebYAML). + CmdRunOut(fmt.Sprintf("gsutil cp -r %s %s", "gs://dev/deployment.yaml", manifest.ManifestTmpDir), "log"). + AndRunOut("kubectl version --client -ojson", KubectlVersion112). + AndRunOut("kubectl --context kubecontext --namespace testNamespace create --dry-run -oyaml -f "+filepath.Join(manifest.ManifestTmpDir, "deployment.yaml"), DeploymentWebYAML). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f -"), skipRender: true, }} for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { t.Override(&util.DefaultExecCommand, test.commands) - if err := os.MkdirAll(manifestTmpDir, os.ModePerm); err != nil { + if err := os.MkdirAll(manifest.ManifestTmpDir, os.ModePerm); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(manifestTmpDir+"/deployment.yaml", []byte(deploymentWebYAML), os.ModePerm); err != nil { + if err := ioutil.WriteFile(manifest.ManifestTmpDir+"/deployment.yaml", []byte(DeploymentWebYAML), os.ModePerm); err != nil { t.Fatal(err) } k, err := NewKubectlDeployer(&kubectlConfig{ workingDir: ".", kubectl: test.kubectl, skipRender: test.skipRender, - RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: testNamespace}}, + RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: TestNamespace}}, }, nil) t.RequireNoError(err) @@ -809,7 +756,7 @@ type kubectlConfig struct { kubectl latest.KubectlDeploy } -func (c *kubectlConfig) GetKubeContext() string { return testKubeContext } +func (c *kubectlConfig) GetKubeContext() string { return "kubecontext" } func (c *kubectlConfig) GetKubeNamespace() string { return c.Opts.Namespace } func (c *kubectlConfig) WorkingDir() string { return c.workingDir } func (c *kubectlConfig) SkipRender() bool { return c.skipRender } diff --git a/pkg/skaffold/deploy/kustomize.go b/pkg/skaffold/deploy/kustomize/kustomize.go similarity index 65% rename from pkg/skaffold/deploy/kustomize.go rename to pkg/skaffold/deploy/kustomize/kustomize.go index 94c4f08e5fc..d7092d4eb04 100644 --- a/pkg/skaffold/deploy/kustomize.go +++ b/pkg/skaffold/deploy/kustomize/kustomize.go @@ -14,17 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package kustomize import ( "context" "fmt" "io" - "io/ioutil" "os" "os/exec" "path/filepath" - "strings" "github.com/segmentio/textio" yamlv3 "gopkg.in/yaml.v3" @@ -32,12 +30,13 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/color" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/warnings" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/yaml" ) var ( @@ -93,13 +92,13 @@ type secretGenerator struct { type KustomizeDeployer struct { *latest.KustomizeDeploy - kubectl deploy.CLI + kubectl kubectl.CLI insecureRegistries map[string]bool labels map[string]string globalConfig string } -func NewKustomizeDeployer(cfg Config, labels map[string]string) (*KustomizeDeployer, error) { +func NewKustomizeDeployer(cfg kubectl.Config, labels map[string]string) (*KustomizeDeployer, error) { defaultNamespace := "" if cfg.Pipeline().Deploy.KustomizeDeploy.DefaultNamespace != nil { var err error @@ -111,7 +110,7 @@ func NewKustomizeDeployer(cfg Config, labels map[string]string) (*KustomizeDeplo return &KustomizeDeployer{ KustomizeDeploy: cfg.Pipeline().Deploy.KustomizeDeploy, - kubectl: deploy.NewCLI(cfg, cfg.Pipeline().Deploy.KustomizeDeploy.Flags, defaultNamespace), + kubectl: kubectl.NewCLI(cfg, cfg.Pipeline().Deploy.KustomizeDeploy.Flags, defaultNamespace), insecureRegistries: cfg.GetInsecureRegistries(), globalConfig: cfg.GlobalConfig(), labels: labels, @@ -146,7 +145,7 @@ func (k *KustomizeDeployer) Deploy(ctx context.Context, out io.Writer, builds [] return namespaces, nil } -func (k *KustomizeDeployer) renderManifests(ctx context.Context, out io.Writer, builds []build.Artifact) (deploy.ManifestList, error) { +func (k *KustomizeDeployer) renderManifests(ctx context.Context, out io.Writer, builds []build.Artifact) (manifest.ManifestList, error) { if err := k.kubectl.CheckVersion(ctx); err != nil { color.Default.Fprintln(out, "kubectl client version:", k.kubectl.Version(ctx)) color.Default.Fprintln(out, err) @@ -171,11 +170,8 @@ func (k *KustomizeDeployer) renderManifests(ctx context.Context, out io.Writer, return nil, fmt.Errorf("replacing images in manifests: %w", err) } - for _, transform := range manifestTransforms { - manifests, err = transform(manifests, builds, Registries{k.insecureRegistries, debugHelpersRegistry}) - if err != nil { - return nil, fmt.Errorf("unable to transform manifests: %w", err) - } + if manifests, err = manifest.ApplyTransforms(manifests, builds, k.insecureRegistries, debugHelpersRegistry); err != nil { + return nil, err } return manifests.SetLabels(k.labels) @@ -197,15 +193,15 @@ func (k *KustomizeDeployer) Cleanup(ctx context.Context, out io.Writer) error { // Dependencies lists all the files that describe what needs to be deployed. func (k *KustomizeDeployer) Dependencies() ([]string, error) { - deps := newStringSet() + deps := deployutil.NewStringSet() for _, kustomizePath := range k.KustomizePaths { - depsForKustomization, err := dependenciesForKustomization(kustomizePath) + depsForKustomization, err := DependenciesForKustomization(kustomizePath) if err != nil { return nil, err } - deps.insert(depsForKustomization...) + deps.Insert(depsForKustomization...) } - return deps.toList(), nil + return deps.ToList(), nil } func (k *KustomizeDeployer) Render(ctx context.Context, out io.Writer, builds []build.Artifact, offline bool, filepath string) error { @@ -213,7 +209,7 @@ func (k *KustomizeDeployer) Render(ctx context.Context, out io.Writer, builds [] if err != nil { return err } - return outputRenderedManifests(manifests.String(), filepath, out) + return manifest.OutputRenderedManifests(manifests.String(), filepath, out) } // Values of `patchesStrategicMerge` can be either: @@ -244,102 +240,6 @@ func (p *patchWrapper) UnmarshalYAML(unmarshal func(interface{}) error) (err err return nil } -func dependenciesForKustomization(dir string) ([]string, error) { - var deps []string - - path, err := findKustomizationConfig(dir) - if err != nil { - // No kustomization config found so assume it's remote and stop traversing - return deps, nil - } - - buf, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - - content := kustomization{} - if err := yaml.Unmarshal(buf, &content); err != nil { - return nil, err - } - - deps = append(deps, path) - - candidates := append(content.Bases, content.Resources...) - candidates = append(candidates, content.Components...) - - for _, candidate := range candidates { - // If the file doesn't exist locally, we can assume it's a remote file and - // skip it, since we can't monitor remote files. Kustomize itself will - // handle invalid/missing files. - local, mode := pathExistsLocally(candidate, dir) - if !local { - continue - } - - if mode.IsDir() { - candidateDeps, err := dependenciesForKustomization(filepath.Join(dir, candidate)) - if err != nil { - return nil, err - } - deps = append(deps, candidateDeps...) - } else { - deps = append(deps, filepath.Join(dir, candidate)) - } - } - - for _, patch := range content.PatchesStrategicMerge { - if patch.Path != "" { - deps = append(deps, filepath.Join(dir, patch.Path)) - } - } - - deps = append(deps, util.AbsolutePaths(dir, content.CRDs)...) - - for _, patch := range content.Patches { - if patch.Path != "" { - deps = append(deps, filepath.Join(dir, patch.Path)) - } - } - - for _, jsonPatch := range content.PatchesJSON6902 { - if jsonPatch.Path != "" { - deps = append(deps, filepath.Join(dir, jsonPatch.Path)) - } - } - - for _, generator := range content.ConfigMapGenerator { - deps = append(deps, util.AbsolutePaths(dir, generator.Files)...) - envs := generator.Envs - if generator.Env != "" { - envs = append(envs, generator.Env) - } - deps = append(deps, util.AbsolutePaths(dir, envs)...) - } - - for _, generator := range content.SecretGenerator { - deps = append(deps, util.AbsolutePaths(dir, generator.Files)...) - envs := generator.Envs - if generator.Env != "" { - envs = append(envs, generator.Env) - } - deps = append(deps, util.AbsolutePaths(dir, envs)...) - } - - return deps, nil -} - -// A Kustomization config must be at the root of the directory. Kustomize will -// error if more than one of these files exists so order doesn't matter. -func findKustomizationConfig(dir string) (string, error) { - for _, candidate := range kustomizeFilePaths { - if local, _ := pathExistsLocally(candidate, dir); local { - return filepath.Join(dir, candidate), nil - } - } - return "", fmt.Errorf("no Kustomization configuration found in directory: %s", dir) -} - func pathExistsLocally(filename string, workingDir string) (bool, os.FileMode) { path := filename if !filepath.IsAbs(filename) { @@ -351,10 +251,10 @@ func pathExistsLocally(filename string, workingDir string) (bool, os.FileMode) { return false, 0 } -func (k *KustomizeDeployer) readManifests(ctx context.Context) (deploy.ManifestList, error) { - var manifests deploy.ManifestList +func (k *KustomizeDeployer) readManifests(ctx context.Context) (manifest.ManifestList, error) { + var manifests manifest.ManifestList for _, kustomizePath := range k.KustomizePaths { - cmd := exec.CommandContext(ctx, "kustomize", buildCommandArgs(k.BuildArgs, kustomizePath)...) + cmd := exec.CommandContext(ctx, "kustomize", BuildCommandArgs(k.BuildArgs, kustomizePath)...) out, err := util.RunCmdOut(cmd) if err != nil { return nil, fmt.Errorf("kustomize build: %w", err) @@ -368,24 +268,6 @@ func (k *KustomizeDeployer) readManifests(ctx context.Context) (deploy.ManifestL return manifests, nil } -func buildCommandArgs(buildArgs []string, kustomizePath string) []string { - var args []string - args = append(args, "build") - - if len(buildArgs) > 0 { - for _, v := range buildArgs { - parts := strings.Split(v, " ") - args = append(args, parts...) - } - } - - if len(kustomizePath) > 0 { - args = append(args, kustomizePath) - } - - return args -} - func IsKustomizationBase(path string) bool { return filepath.Dir(path) == basePath } diff --git a/pkg/skaffold/deploy/kustomize_test.go b/pkg/skaffold/deploy/kustomize/kustomize_test.go similarity index 91% rename from pkg/skaffold/deploy/kustomize_test.go rename to pkg/skaffold/deploy/kustomize/kustomize_test.go index b083a4e93ec..7ec15bf3400 100644 --- a/pkg/skaffold/deploy/kustomize_test.go +++ b/pkg/skaffold/deploy/kustomize/kustomize_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package kustomize import ( "bytes" @@ -27,6 +27,7 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" @@ -50,7 +51,7 @@ func TestKustomizeDeploy(t *testing.T) { KustomizePaths: []string{"."}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). + CmdRunOut("kubectl version --client -ojson", kubectl.KubectlVersion112). AndRunOut("kustomize build .", ""), }, { @@ -59,9 +60,9 @@ func TestKustomizeDeploy(t *testing.T) { KustomizePaths: []string{"."}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kustomize build .", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", kubectl.KubectlVersion112). + AndRunOut("kustomize build .", kubectl.DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", kubectl.DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f - --force --grace-period=0"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -73,12 +74,12 @@ func TestKustomizeDeploy(t *testing.T) { description: "deploy success (default namespace)", kustomize: latest.KustomizeDeploy{ KustomizePaths: []string{"."}, - DefaultNamespace: &testNamespace2, + DefaultNamespace: &kubectl.TestNamespace2, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kustomize build .", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", kubectl.KubectlVersion112). + AndRunOut("kustomize build .", kubectl.DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", kubectl.DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace2 apply -f - --force --grace-period=0"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -91,12 +92,12 @@ func TestKustomizeDeploy(t *testing.T) { description: "deploy success (default namespace with env template)", kustomize: latest.KustomizeDeploy{ KustomizePaths: []string{"."}, - DefaultNamespace: &testNamespace2FromEnvTemplate, + DefaultNamespace: &kubectl.TestNamespace2FromEnvTemplate, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kustomize build .", deploymentWebYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", deploymentWebYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", kubectl.KubectlVersion112). + AndRunOut("kustomize build .", kubectl.DeploymentWebYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace2 get -f - --ignore-not-found -ojson", kubectl.DeploymentWebYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace2 apply -f - --force --grace-period=0"), builds: []build.Artifact{{ ImageName: "leeroy-web", @@ -114,10 +115,10 @@ func TestKustomizeDeploy(t *testing.T) { KustomizePaths: []string{"a", "b"}, }, commands: testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112). - AndRunOut("kustomize build a", deploymentWebYAML). - AndRunOut("kustomize build b", deploymentAppYAML). - AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", deploymentWebYAMLv1+"\n---\n"+deploymentAppYAMLv1, ""). + CmdRunOut("kubectl version --client -ojson", kubectl.KubectlVersion112). + AndRunOut("kustomize build a", kubectl.DeploymentWebYAML). + AndRunOut("kustomize build b", kubectl.DeploymentAppYAML). + AndRunInputOut("kubectl --context kubecontext --namespace testNamespace get -f - --ignore-not-found -ojson", kubectl.DeploymentWebYAMLv1+"\n---\n"+kubectl.DeploymentAppYAMLv1, ""). AndRun("kubectl --context kubecontext --namespace testNamespace apply -f - --force --grace-period=0"), builds: []build.Artifact{ { @@ -141,7 +142,7 @@ func TestKustomizeDeploy(t *testing.T) { skaffoldNamespaceOption := "" if !test.skipSkaffoldNamespaceOption { - skaffoldNamespaceOption = testNamespace + skaffoldNamespaceOption = kubectl.TestNamespace } k, err := NewKustomizeDeployer(&kustomizeConfig{ @@ -179,7 +180,7 @@ func TestKustomizeCleanup(t *testing.T) { KustomizePaths: []string{tmpDir.Root()}, }, commands: testutil. - CmdRunOut("kustomize build "+tmpDir.Root(), deploymentWebYAML). + CmdRunOut("kustomize build "+tmpDir.Root(), kubectl.DeploymentWebYAML). AndRun("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -"), }, { @@ -188,8 +189,8 @@ func TestKustomizeCleanup(t *testing.T) { KustomizePaths: tmpDir.Paths("a", "b"), }, commands: testutil. - CmdRunOut("kustomize build "+tmpDir.Path("a"), deploymentWebYAML). - AndRunOut("kustomize build "+tmpDir.Path("b"), deploymentAppYAML). + CmdRunOut("kustomize build "+tmpDir.Path("a"), kubectl.DeploymentWebYAML). + AndRunOut("kustomize build "+tmpDir.Path("b"), kubectl.DeploymentAppYAML). AndRun("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -"), }, { @@ -198,7 +199,7 @@ func TestKustomizeCleanup(t *testing.T) { KustomizePaths: []string{tmpDir.Root()}, }, commands: testutil. - CmdRunOut("kustomize build "+tmpDir.Root(), deploymentWebYAML). + CmdRunOut("kustomize build "+tmpDir.Root(), kubectl.DeploymentWebYAML). AndRunErr("kubectl --context kubecontext --namespace testNamespace delete --ignore-not-found=true -f -", errors.New("BUG")), shouldErr: true, }, @@ -223,7 +224,7 @@ func TestKustomizeCleanup(t *testing.T) { workingDir: tmpDir.Root(), kustomize: test.kustomize, RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{ - Namespace: testNamespace}}, + Namespace: kubectl.TestNamespace}}, }, nil) t.RequireNoError(err) err = k.Cleanup(context.Background(), ioutil.Discard) @@ -499,7 +500,7 @@ func TestKustomizeBuildCommandArgs(t *testing.T) { for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { - args := buildCommandArgs(test.buildArgs, test.kustomizePath) + args := BuildCommandArgs(test.buildArgs, test.kustomizePath) t.CheckDeepEqual(test.expectedArgs, args) }) } @@ -663,7 +664,7 @@ spec: testutil.Run(t, test.description, func(t *testutil.T) { var kustomizationPaths []string fakeCmd := testutil. - CmdRunOut("kubectl version --client -ojson", kubectlVersion112) + CmdRunOut("kubectl version --client -ojson", kubectl.KubectlVersion112) for _, kustomizationCall := range test.kustomizations { fakeCmd.AndRunOut("kustomize build "+kustomizationCall.folder, kustomizationCall.buildResult) kustomizationPaths = append(kustomizationPaths, kustomizationCall.folder) @@ -676,7 +677,7 @@ spec: kustomize: latest.KustomizeDeploy{ KustomizePaths: kustomizationPaths, }, - RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: testNamespace}}, + RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: kubectl.TestNamespace}}, }, test.labels) t.RequireNoError(err) @@ -699,7 +700,7 @@ type kustomizeConfig struct { func (c *kustomizeConfig) ForceDeploy() bool { return c.force } func (c *kustomizeConfig) WaitForDeletions() config.WaitForDeletions { return c.waitForDeletions } func (c *kustomizeConfig) WorkingDir() string { return c.workingDir } -func (c *kustomizeConfig) GetKubeContext() string { return testKubeContext } +func (c *kustomizeConfig) GetKubeContext() string { return kubectl.TestKubeContext } func (c *kustomizeConfig) GetKubeNamespace() string { return c.Opts.Namespace } func (c *kustomizeConfig) Pipeline() latest.Pipeline { var pipeline latest.Pipeline diff --git a/pkg/skaffold/deploy/kustomize/util.go b/pkg/skaffold/deploy/kustomize/util.go new file mode 100644 index 00000000000..0f8bf74e510 --- /dev/null +++ b/pkg/skaffold/deploy/kustomize/util.go @@ -0,0 +1,141 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kustomize + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "strings" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/yaml" +) + +func DependenciesForKustomization(dir string) ([]string, error) { + var deps []string + + path, err := FindKustomizationConfig(dir) + if err != nil { + // No kustomization config found so assume it's remote and stop traversing + return deps, nil + } + + buf, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + content := kustomization{} + if err := yaml.Unmarshal(buf, &content); err != nil { + return nil, err + } + + deps = append(deps, path) + + candidates := append(content.Bases, content.Resources...) + candidates = append(candidates, content.Components...) + + for _, candidate := range candidates { + // If the file doesn't exist locally, we can assume it's a remote file and + // skip it, since we can't monitor remote files. Kustomize itself will + // handle invalid/missing files. + local, mode := pathExistsLocally(candidate, dir) + if !local { + continue + } + + if mode.IsDir() { + candidateDeps, err := DependenciesForKustomization(filepath.Join(dir, candidate)) + if err != nil { + return nil, err + } + deps = append(deps, candidateDeps...) + } else { + deps = append(deps, filepath.Join(dir, candidate)) + } + } + + for _, patch := range content.PatchesStrategicMerge { + if patch.Path != "" { + deps = append(deps, filepath.Join(dir, patch.Path)) + } + } + + deps = append(deps, util.AbsolutePaths(dir, content.CRDs)...) + + for _, patch := range content.Patches { + if patch.Path != "" { + deps = append(deps, filepath.Join(dir, patch.Path)) + } + } + + for _, jsonPatch := range content.PatchesJSON6902 { + if jsonPatch.Path != "" { + deps = append(deps, filepath.Join(dir, jsonPatch.Path)) + } + } + + for _, generator := range content.ConfigMapGenerator { + deps = append(deps, util.AbsolutePaths(dir, generator.Files)...) + envs := generator.Envs + if generator.Env != "" { + envs = append(envs, generator.Env) + } + deps = append(deps, util.AbsolutePaths(dir, envs)...) + } + + for _, generator := range content.SecretGenerator { + deps = append(deps, util.AbsolutePaths(dir, generator.Files)...) + envs := generator.Envs + if generator.Env != "" { + envs = append(envs, generator.Env) + } + deps = append(deps, util.AbsolutePaths(dir, envs)...) + } + + return deps, nil +} + +// A Kustomization config must be at the root of the directory. Kustomize will +// error if more than one of these files exists so order doesn't matter. +func FindKustomizationConfig(dir string) (string, error) { + for _, candidate := range kustomizeFilePaths { + if local, _ := pathExistsLocally(candidate, dir); local { + return filepath.Join(dir, candidate), nil + } + } + return "", fmt.Errorf("no Kustomization configuration found in directory: %s", dir) +} + +func BuildCommandArgs(buildArgs []string, kustomizePath string) []string { + var args []string + args = append(args, "build") + + if len(buildArgs) > 0 { + for _, v := range buildArgs { + parts := strings.Split(v, " ") + args = append(args, parts...) + } + } + + if len(kustomizePath) > 0 { + args = append(args, kustomizePath) + } + + return args +} diff --git a/pkg/skaffold/deploy/labeller.go b/pkg/skaffold/deploy/label/labeller.go similarity index 95% rename from pkg/skaffold/deploy/labeller.go rename to pkg/skaffold/deploy/label/labeller.go index a242d430225..5d6e8fd909d 100644 --- a/pkg/skaffold/deploy/labeller.go +++ b/pkg/skaffold/deploy/label/labeller.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package label import ( "fmt" @@ -68,3 +68,7 @@ func (d *DefaultLabeller) Labels() map[string]string { func (d *DefaultLabeller) RunIDSelector() string { return fmt.Sprintf("%s=%s", RunIDLabel, d.Labels()[RunIDLabel]) } + +func (d *DefaultLabeller) GetRunID() string { + return d.runID +} diff --git a/pkg/skaffold/deploy/labels.go b/pkg/skaffold/deploy/label/labels.go similarity index 93% rename from pkg/skaffold/deploy/labels.go rename to pkg/skaffold/deploy/label/labels.go index d29f73d6db7..2dc70330d2c 100644 --- a/pkg/skaffold/deploy/labels.go +++ b/pkg/skaffold/deploy/label/labels.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package label import ( "encoding/json" @@ -24,30 +24,24 @@ import ( "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" patch "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" + deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" kubernetesclient "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/client" kubectx "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/context" ) -// Artifact contains all information about a completed deployment -type Artifact struct { - Obj runtime.Object - Namespace string -} - // retry 3 times to give the object time to propagate to the API server const ( tries = 3 sleeptime = 300 * time.Millisecond ) -func labelDeployResults(labels map[string]string, results []Artifact) error { +func LabelDeployResults(labels map[string]string, results []deploy.Artifact) error { if len(labels) == 0 { return nil } @@ -88,7 +82,7 @@ func addLabels(labels map[string]string, accessor metav1.Object) { accessor.SetLabels(kv) } -func updateRuntimeObject(client dynamic.Interface, disco discovery.DiscoveryInterface, labels map[string]string, res Artifact) error { +func updateRuntimeObject(client dynamic.Interface, disco discovery.DiscoveryInterface, labels map[string]string, res deploy.Artifact) error { originalJSON, _ := json.Marshal(res.Obj) modifiedObj := res.Obj.DeepCopyObject() accessor, err := meta.Accessor(modifiedObj) diff --git a/pkg/skaffold/deploy/labels_test.go b/pkg/skaffold/deploy/label/labels_test.go similarity index 95% rename from pkg/skaffold/deploy/labels_test.go rename to pkg/skaffold/deploy/label/labels_test.go index efe8927efd8..f91aa8a0c30 100644 --- a/pkg/skaffold/deploy/labels_test.go +++ b/pkg/skaffold/deploy/label/labels_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package label import ( "testing" @@ -28,6 +28,7 @@ import ( fakeclient "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/scheme" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" kubernetesclient "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/client" "github.com/GoogleContainerTools/skaffold/testutil" ) @@ -106,7 +107,7 @@ func TestLabelDeployResults(t *testing.T) { t.Override(&kubernetesclient.DynamicClient, mockDynamicClient(dynClient)) // Patch labels - labelDeployResults(test.appliedLabels, []Artifact{{Obj: dep}}) + LabelDeployResults(test.appliedLabels, []types.Artifact{{Obj: dep}}) // Check modified value modified, err := dynClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}).Get("foo", metav1.GetOptions{}) diff --git a/pkg/skaffold/deploy/status_check.go b/pkg/skaffold/deploy/status/status_check.go similarity index 95% rename from pkg/skaffold/deploy/status_check.go rename to pkg/skaffold/deploy/status/status_check.go index 93913774bdb..b4fec8a92c0 100644 --- a/pkg/skaffold/deploy/status_check.go +++ b/pkg/skaffold/deploy/status/status_check.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package status import ( "context" @@ -33,6 +33,7 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/diag/validator" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/resource" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" pkgkubectl "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" @@ -78,13 +79,13 @@ type StatusChecker interface { // StatusChecker runs status checks for pods and deployments type statusChecker struct { cfg StatusCheckConfig - labeller *DefaultLabeller + labeller *label.DefaultLabeller deadlineSeconds int muteLogs bool } // NewStatusChecker returns a status checker which runs checks on deployments and pods. -func NewStatusChecker(cfg StatusCheckConfig, labeller *DefaultLabeller) StatusChecker { +func NewStatusChecker(cfg StatusCheckConfig, labeller *label.DefaultLabeller) StatusChecker { return statusChecker{ muteLogs: cfg.Muted().MuteStatusCheck(), cfg: cfg, @@ -150,7 +151,7 @@ func (s statusChecker) statusCheck(ctx context.Context, out io.Writer) (proto.St return getSkaffoldDeployStatus(c, deployments) } -func getDeployments(client kubernetes.Interface, ns string, l *DefaultLabeller, deadlineDuration time.Duration) ([]*resource.Deployment, error) { +func getDeployments(client kubernetes.Interface, ns string, l *label.DefaultLabeller, deadlineDuration time.Duration) ([]*resource.Deployment, error) { deps, err := client.AppsV1().Deployments(ns).List(metav1.ListOptions{ LabelSelector: l.RunIDSelector(), }) @@ -167,7 +168,7 @@ func getDeployments(client kubernetes.Interface, ns string, l *DefaultLabeller, deadline = time.Duration(*d.Spec.ProgressDeadlineSeconds) * time.Second } pd := diag.New([]string{d.Namespace}). - WithLabel(RunIDLabel, l.Labels()[RunIDLabel]). + WithLabel(label.RunIDLabel, l.Labels()[label.RunIDLabel]). WithValidators([]validator.Validator{validator.NewPodValidator(client)}) for k, v := range d.Spec.Template.Labels { diff --git a/pkg/skaffold/deploy/status_check_test.go b/pkg/skaffold/deploy/status/status_check_test.go similarity index 95% rename from pkg/skaffold/deploy/status_check_test.go rename to pkg/skaffold/deploy/status/status_check_test.go index 0fd8172253e..7ade4e0cb7f 100644 --- a/pkg/skaffold/deploy/status_check_test.go +++ b/pkg/skaffold/deploy/status/status_check_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package status import ( "bytes" @@ -33,6 +33,8 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/diag" "github.com/GoogleContainerTools/skaffold/pkg/diag/validator" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/resource" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" @@ -43,7 +45,7 @@ import ( ) func TestGetDeployments(t *testing.T) { - labeller := NewLabeller(true, nil) + labeller := label.NewLabeller(true, nil) tests := []struct { description string deps []*appsv1.Deployment @@ -58,8 +60,8 @@ func TestGetDeployments(t *testing.T) { Name: "dep1", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, - "random": "foo", + label.RunIDLabel: labeller.GetRunID(), + "random": "foo", }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(10)}, @@ -69,7 +71,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep2", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, + label.RunIDLabel: labeller.GetRunID(), }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(20)}, @@ -88,8 +90,8 @@ func TestGetDeployments(t *testing.T) { Name: "dep1", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, - "random": "foo", + label.RunIDLabel: labeller.GetRunID(), + "random": "foo", }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(300)}, @@ -107,7 +109,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep1", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, + label.RunIDLabel: labeller.GetRunID(), }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(100)}, @@ -117,7 +119,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep2", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, + label.RunIDLabel: labeller.GetRunID(), }, }, }, @@ -135,7 +137,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep1", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, + label.RunIDLabel: labeller.GetRunID(), }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(600)}, @@ -157,7 +159,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep1", Namespace: "test", Labels: map[string]string{ - RunIDLabel: labeller.runID, + label.RunIDLabel: labeller.GetRunID(), }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(100)}, @@ -167,7 +169,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep2", Namespace: "test1", Labels: map[string]string{ - RunIDLabel: labeller.runID, + label.RunIDLabel: labeller.GetRunID(), }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(100)}, @@ -201,7 +203,7 @@ func TestGetDeployments(t *testing.T) { Name: "dep1", Namespace: "test", Labels: map[string]string{ - RunIDLabel: "9876-6789", + label.RunIDLabel: "9876-6789", }, }, Spec: appsv1.DeploymentSpec{ProgressDeadlineSeconds: utilpointer.Int32Ptr(100)}, @@ -303,7 +305,7 @@ func TestGetDeployStatus(t *testing.T) { } func TestPrintSummaryStatus(t *testing.T) { - labeller := NewLabeller(true, nil) + labeller := label.NewLabeller(true, nil) tests := []struct { description string namespace string @@ -380,7 +382,7 @@ func TestPrintSummaryStatus(t *testing.T) { } func TestPrintStatus(t *testing.T) { - labeller := NewLabeller(true, nil) + labeller := label.NewLabeller(true, nil) tests := []struct { description string rs []*resource.Deployment @@ -625,4 +627,4 @@ type statusConfig struct { runcontext.RunContext // Embedded to provide the default values. } -func (c *statusConfig) GetKubeContext() string { return testKubeContext } +func (c *statusConfig) GetKubeContext() string { return kubectl.TestKubeContext } diff --git a/pkg/skaffold/deploy/types/types.go b/pkg/skaffold/deploy/types/types.go new file mode 100644 index 00000000000..98b681aaa65 --- /dev/null +++ b/pkg/skaffold/deploy/types/types.go @@ -0,0 +1,40 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "k8s.io/apimachinery/pkg/runtime" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" +) + +type Config interface { + docker.Config + + Pipeline() latest.Pipeline + GetWorkingDir() string + GlobalConfig() string + DefaultRepo() *string + SkipRender() bool +} + +// Artifact contains all information about a completed deployment +type Artifact struct { + Obj runtime.Object + Namespace string +} diff --git a/pkg/skaffold/deploy/util.go b/pkg/skaffold/deploy/util.go deleted file mode 100644 index db78d03e198..00000000000 --- a/pkg/skaffold/deploy/util.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2019 The Skaffold Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package deploy - -import ( - "bufio" - "bytes" - "context" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/sirupsen/logrus" - k8syaml "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/client-go/kubernetes/scheme" - - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" -) - -const ( - manifestsStagingFolder = "manifest_tmp" - renderedManifestsStagingFile = "rendered_manifest.yaml" - gcsPrefix = "gs://" -) - -var manifestTmpDir = filepath.Join(os.TempDir(), manifestsStagingFolder) - -func parseRuntimeObject(namespace string, b []byte) (*Artifact, error) { - d := scheme.Codecs.UniversalDeserializer() - obj, _, err := d.Decode(b, nil, nil) - if err != nil { - return nil, fmt.Errorf("error decoding parsed yaml: %s", err.Error()) - } - return &Artifact{ - Obj: obj, - Namespace: namespace, - }, nil -} - -func parseReleaseInfo(namespace string, b *bufio.Reader) []Artifact { - var results []Artifact - - r := k8syaml.NewYAMLReader(b) - for i := 0; ; i++ { - doc, err := r.Read() - if err == io.EOF { - break - } - if err != nil { - logrus.Infof("error parsing object from string: %s", err.Error()) - continue - } - objNamespace, err := getObjectNamespaceIfDefined(doc, namespace) - if err != nil { - logrus.Infof("error parsing object from string: %s", err.Error()) - continue - } - obj, err := parseRuntimeObject(objNamespace, doc) - if err != nil { - if i > 0 { - logrus.Infof(err.Error()) - } - } else { - results = append(results, *obj) - logrus.Debugf("found deployed object: %+v", obj.Obj) - } - } - - return results -} - -func getObjectNamespaceIfDefined(doc []byte, ns string) (string, error) { - if i := bytes.Index(doc, []byte("apiVersion")); i >= 0 { - manifests := kubectl.ManifestList{doc[i:]} - namespaces, err := manifests.CollectNamespaces() - if err != nil { - return ns, err - } - if len(namespaces) > 0 { - return namespaces[0], nil - } - } - return ns, nil -} - -// Outputs rendered manifests to a file, a writer or a GCS bucket. -func outputRenderedManifests(renderedManifests string, output string, manifestOut io.Writer) error { - switch { - case output == "": - _, err := fmt.Fprintln(manifestOut, renderedManifests) - return err - case strings.HasPrefix(output, gcsPrefix): - tempDir, err := ioutil.TempDir("", manifestsStagingFolder) - if err != nil { - return fmt.Errorf("failed to create the tmp directory: %w", err) - } - defer os.RemoveAll(tempDir) - tempFile := filepath.Join(tempDir, renderedManifestsStagingFile) - if err := dumpToFile(renderedManifests, tempFile); err != nil { - return err - } - gcs := util.Gsutil{} - if err := gcs.Copy(context.Background(), tempFile, output, false); err != nil { - return fmt.Errorf("failed to copy rendered manifests to GCS: %w", err) - } - return nil - default: - return dumpToFile(renderedManifests, output) - } -} - -func dumpToFile(renderedManifests string, filepath string) error { - f, err := os.Create(filepath) - if err != nil { - return fmt.Errorf("opening file for writing manifests: %w", err) - } - defer f.Close() - _, err = f.WriteString(renderedManifests + "\n") - return err -} - -// Returns relative path pointing to the GCS temp dir -func downloadManifestsFromGCS(manifests []string) (string, error) { - if err := os.MkdirAll(manifestTmpDir, os.ModePerm); err != nil { - return "", fmt.Errorf("failed to create the tmp directory: %w", err) - } - for _, manifest := range manifests { - if manifest == "" || !strings.HasPrefix(manifest, gcsPrefix) { - return "", fmt.Errorf("%v is not a valid GCS path", manifest) - } - gcs := util.Gsutil{} - if err := gcs.Copy(context.Background(), manifest, manifestTmpDir, true); err != nil { - return "", fmt.Errorf("failed to download manifests fom GCS: %w", err) - } - } - return manifestTmpDir, nil -} - -// ApplyDefaultRepo applies the default repo to a given image tag. -func ApplyDefaultRepo(globalConfig string, defaultRepo *string, tag string) (string, error) { - repo, err := config.GetDefaultRepo(globalConfig, defaultRepo) - if err != nil { - return "", fmt.Errorf("getting default repo: %w", err) - } - - newTag, err := docker.SubstituteDefaultRepoIntoImage(repo, tag) - if err != nil { - return "", fmt.Errorf("applying default repo to %q: %w", tag, err) - } - - return newTag, nil -} diff --git a/pkg/skaffold/deploy/logfile.go b/pkg/skaffold/deploy/util/logfile.go similarity index 99% rename from pkg/skaffold/deploy/logfile.go rename to pkg/skaffold/deploy/util/logfile.go index 5013c12ffd0..d835a1af885 100644 --- a/pkg/skaffold/deploy/logfile.go +++ b/pkg/skaffold/deploy/util/logfile.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package util import ( "bytes" diff --git a/pkg/skaffold/deploy/logfile_test.go b/pkg/skaffold/deploy/util/logfile_test.go similarity index 99% rename from pkg/skaffold/deploy/logfile_test.go rename to pkg/skaffold/deploy/util/logfile_test.go index 9af6c90321b..04407e891bf 100644 --- a/pkg/skaffold/deploy/logfile_test.go +++ b/pkg/skaffold/deploy/util/logfile_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package util import ( "bytes" diff --git a/pkg/skaffold/deploy/util/stringset.go b/pkg/skaffold/deploy/util/stringset.go new file mode 100644 index 00000000000..94f99f7b151 --- /dev/null +++ b/pkg/skaffold/deploy/util/stringset.go @@ -0,0 +1,45 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import "sort" + +type unit struct{} + +// StringSet helps to de-duplicate a set of strings. +type StringSet map[string]unit + +func NewStringSet() StringSet { + return make(map[string]unit) +} + +// Insert adds strings to the set. +func (s StringSet) Insert(strings ...string) { + for _, item := range strings { + s[item] = unit{} + } +} + +// ToList returns the sorted list of inserted strings. +func (s StringSet) ToList() []string { + var res []string + for item := range s { + res = append(res, item) + } + sort.Strings(res) + return res +} diff --git a/pkg/skaffold/deploy/util/util.go b/pkg/skaffold/deploy/util/util.go new file mode 100644 index 00000000000..54b2c8372d1 --- /dev/null +++ b/pkg/skaffold/deploy/util/util.go @@ -0,0 +1,39 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "fmt" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" +) + +// ApplyDefaultRepo applies the default repo to a given image tag. +func ApplyDefaultRepo(globalConfig string, defaultRepo *string, tag string) (string, error) { + repo, err := config.GetDefaultRepo(globalConfig, defaultRepo) + if err != nil { + return "", fmt.Errorf("getting default repo: %w", err) + } + + newTag, err := docker.SubstituteDefaultRepoIntoImage(repo, tag) + if err != nil { + return "", fmt.Errorf("applying default repo to %q: %w", tag, err) + } + + return newTag, nil +} diff --git a/pkg/skaffold/initializer/analyze/helm.go b/pkg/skaffold/initializer/analyze/helm.go index 290a271252b..1b6ee6962c3 100644 --- a/pkg/skaffold/initializer/analyze/helm.go +++ b/pkg/skaffold/initializer/analyze/helm.go @@ -17,7 +17,7 @@ limitations under the License. package analyze import ( - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/helm" ) // helmAnalyzer is a Visitor during the directory analysis that finds helm charts diff --git a/pkg/skaffold/initializer/analyze/kustomize.go b/pkg/skaffold/initializer/analyze/kustomize.go index 5e5fb4b7036..a0f310f5855 100644 --- a/pkg/skaffold/initializer/analyze/kustomize.go +++ b/pkg/skaffold/initializer/analyze/kustomize.go @@ -19,7 +19,7 @@ package analyze import ( "path/filepath" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kustomize" ) // kustomizeAnalyzer is a Visitor during the directory analysis that finds kustomize files diff --git a/pkg/skaffold/initializer/deploy/kustomize.go b/pkg/skaffold/initializer/deploy/kustomize.go index 653fe8c8634..27d30b85e3e 100644 --- a/pkg/skaffold/initializer/deploy/kustomize.go +++ b/pkg/skaffold/initializer/deploy/kustomize.go @@ -21,7 +21,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + pkgkustomize "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kustomize" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/errors" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" @@ -61,7 +61,7 @@ func (k *kustomize) DeployConfig() (latest.DeployConfig, []latest.Profile) { // if there's only one kustomize path, either leave it blank (if it's the default path), // or generate a config with that single path and return it if len(k.kustomizations) == 1 { - if k.kustomizations[0] == deploy.DefaultKustomizePath { + if k.kustomizations[0] == pkgkustomize.DefaultKustomizePath { kustomizeConfig = &latest.KustomizeDeploy{} } else { kustomizeConfig = &latest.KustomizeDeploy{ diff --git a/pkg/skaffold/kubernetes/manifest/gcs.go b/pkg/skaffold/kubernetes/manifest/gcs.go new file mode 100644 index 00000000000..38cb421d959 --- /dev/null +++ b/pkg/skaffold/kubernetes/manifest/gcs.go @@ -0,0 +1,43 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package manifest + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" +) + +// Returns relative path pointing to the GCS temp dir +func DownloadManifestsFromGCS(manifests []string) (string, error) { + if err := os.MkdirAll(ManifestTmpDir, os.ModePerm); err != nil { + return "", fmt.Errorf("failed to create the tmp directory: %w", err) + } + for _, manifest := range manifests { + if manifest == "" || !strings.HasPrefix(manifest, gcsPrefix) { + return "", fmt.Errorf("%v is not a valid GCS path", manifest) + } + gcs := util.Gsutil{} + if err := gcs.Copy(context.Background(), manifest, ManifestTmpDir, true); err != nil { + return "", fmt.Errorf("failed to download manifests fom GCS: %w", err) + } + } + return ManifestTmpDir, nil +} diff --git a/pkg/skaffold/deploy/kubectl/images.go b/pkg/skaffold/kubernetes/manifest/images.go similarity index 97% rename from pkg/skaffold/deploy/kubectl/images.go rename to pkg/skaffold/kubernetes/manifest/images.go index 07986fe1089..0d845dc468a 100644 --- a/pkg/skaffold/deploy/kubectl/images.go +++ b/pkg/skaffold/kubernetes/manifest/images.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "fmt" @@ -65,7 +65,7 @@ func (l *ManifestList) ReplaceImages(builds []build.Artifact) (ManifestList, err updated, err := l.Visit(replacer) if err != nil { - return nil, fmt.Errorf("replacing images: %w", err) + return nil, fmt.Errorf("replacing images in manifest: %w", err) } replacer.Check() diff --git a/pkg/skaffold/deploy/kubectl/images_test.go b/pkg/skaffold/kubernetes/manifest/images_test.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/images_test.go rename to pkg/skaffold/kubernetes/manifest/images_test.go index 20e1c09654c..95b79ff3eef 100644 --- a/pkg/skaffold/deploy/kubectl/images_test.go +++ b/pkg/skaffold/kubernetes/manifest/images_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "testing" diff --git a/pkg/skaffold/deploy/kubectl/labels.go b/pkg/skaffold/kubernetes/manifest/labels.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/labels.go rename to pkg/skaffold/kubernetes/manifest/labels.go index 731e6870b13..e45dd08bc6d 100644 --- a/pkg/skaffold/deploy/kubectl/labels.go +++ b/pkg/skaffold/kubernetes/manifest/labels.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "fmt" diff --git a/pkg/skaffold/deploy/kubectl/labels_test.go b/pkg/skaffold/kubernetes/manifest/labels_test.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/labels_test.go rename to pkg/skaffold/kubernetes/manifest/labels_test.go index 499b64c1c1f..803f762e061 100644 --- a/pkg/skaffold/deploy/kubectl/labels_test.go +++ b/pkg/skaffold/kubernetes/manifest/labels_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "testing" diff --git a/pkg/skaffold/deploy/kubectl/manifests.go b/pkg/skaffold/kubernetes/manifest/manifests.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/manifests.go rename to pkg/skaffold/kubernetes/manifest/manifests.go index 424b17d7473..d992a1e4c25 100644 --- a/pkg/skaffold/deploy/kubectl/manifests.go +++ b/pkg/skaffold/kubernetes/manifest/manifests.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "bytes" diff --git a/pkg/skaffold/deploy/kubectl/manifests_test.go b/pkg/skaffold/kubernetes/manifest/manifests_test.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/manifests_test.go rename to pkg/skaffold/kubernetes/manifest/manifests_test.go index 47dc54916f6..9c3c5a7465a 100644 --- a/pkg/skaffold/deploy/kubectl/manifests_test.go +++ b/pkg/skaffold/kubernetes/manifest/manifests_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "testing" diff --git a/pkg/skaffold/deploy/kubectl/namespace_test.go b/pkg/skaffold/kubernetes/manifest/namespace_test.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/namespace_test.go rename to pkg/skaffold/kubernetes/manifest/namespace_test.go index c4d35018e38..c508afa88a5 100644 --- a/pkg/skaffold/deploy/kubectl/namespace_test.go +++ b/pkg/skaffold/kubernetes/manifest/namespace_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "testing" diff --git a/pkg/skaffold/deploy/kubectl/namespaces.go b/pkg/skaffold/kubernetes/manifest/namespaces.go similarity index 98% rename from pkg/skaffold/deploy/kubectl/namespaces.go rename to pkg/skaffold/kubernetes/manifest/namespaces.go index 29b3858c88c..55b2687ba1c 100644 --- a/pkg/skaffold/deploy/kubectl/namespaces.go +++ b/pkg/skaffold/kubernetes/manifest/namespaces.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "fmt" diff --git a/pkg/skaffold/deploy/transformations.go b/pkg/skaffold/kubernetes/manifest/transformations.go similarity index 60% rename from pkg/skaffold/deploy/transformations.go rename to pkg/skaffold/kubernetes/manifest/transformations.go index b70589a2e40..3441bdb0c75 100644 --- a/pkg/skaffold/deploy/transformations.go +++ b/pkg/skaffold/kubernetes/manifest/transformations.go @@ -14,11 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deploy +package manifest import ( + "fmt" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" ) type Registries struct { @@ -26,7 +27,7 @@ type Registries struct { DebugHelpersRegistry string } -type ManifestTransform func(l kubectl.ManifestList, builds []build.Artifact, registries Registries) (kubectl.ManifestList, error) +type ManifestTransform func(l ManifestList, builds []build.Artifact, registries Registries) (ManifestList, error) // Transforms are applied to manifests var manifestTransforms []ManifestTransform @@ -35,3 +36,18 @@ var manifestTransforms []ManifestTransform func AddManifestTransform(newTransform ManifestTransform) { manifestTransforms = append(manifestTransforms, newTransform) } + +func GetManifestTransforms() []ManifestTransform { + return manifestTransforms +} + +func ApplyTransforms(manifests ManifestList, builds []build.Artifact, insecureRegistries map[string]bool, debugHelpersRegistry string) (ManifestList, error) { + var err error + for _, transform := range manifestTransforms { + manifests, err = transform(manifests, builds, Registries{insecureRegistries, debugHelpersRegistry}) + if err != nil { + return nil, fmt.Errorf("unable to transform manifests: %w", err) + } + } + return manifests, nil +} diff --git a/pkg/skaffold/kubernetes/manifest/util.go b/pkg/skaffold/kubernetes/manifest/util.go new file mode 100644 index 00000000000..3988014cdad --- /dev/null +++ b/pkg/skaffold/kubernetes/manifest/util.go @@ -0,0 +1,73 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package manifest + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" +) + +const ( + manifestsStagingFolder = "manifest_tmp" + renderedManifestsStagingFile = "rendered_manifest.yaml" + gcsPrefix = "gs://" +) + +var ManifestTmpDir = filepath.Join(os.TempDir(), manifestsStagingFolder) + +// Outputs rendered manifests to a file, a writer or a GCS bucket. +func OutputRenderedManifests(renderedManifests string, output string, manifestOut io.Writer) error { + switch { + case output == "": + _, err := fmt.Fprintln(manifestOut, renderedManifests) + return err + case strings.HasPrefix(output, gcsPrefix): + tempDir, err := ioutil.TempDir("", manifestsStagingFolder) + if err != nil { + return fmt.Errorf("failed to create the tmp directory: %w", err) + } + defer os.RemoveAll(tempDir) + tempFile := filepath.Join(tempDir, renderedManifestsStagingFile) + if err := dumpToFile(renderedManifests, tempFile); err != nil { + return err + } + gcs := util.Gsutil{} + if err := gcs.Copy(context.Background(), tempFile, output, false); err != nil { + return fmt.Errorf("failed to copy rendered manifests to GCS: %w", err) + } + return nil + default: + return dumpToFile(renderedManifests, output) + } +} + +func dumpToFile(renderedManifests string, filepath string) error { + f, err := os.Create(filepath) + if err != nil { + return fmt.Errorf("opening file for writing manifests: %w", err) + } + defer f.Close() + _, err = f.WriteString(renderedManifests + "\n") + return err +} diff --git a/pkg/skaffold/deploy/kubectl/visitor.go b/pkg/skaffold/kubernetes/manifest/visitor.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/visitor.go rename to pkg/skaffold/kubernetes/manifest/visitor.go index 8d7ce3109ad..0b9bc542aac 100644 --- a/pkg/skaffold/deploy/kubectl/visitor.go +++ b/pkg/skaffold/kubernetes/manifest/visitor.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "fmt" diff --git a/pkg/skaffold/deploy/kubectl/visitor_test.go b/pkg/skaffold/kubernetes/manifest/visitor_test.go similarity index 99% rename from pkg/skaffold/deploy/kubectl/visitor_test.go rename to pkg/skaffold/kubernetes/manifest/visitor_test.go index c7cb0e3694c..a6796854775 100644 --- a/pkg/skaffold/deploy/kubectl/visitor_test.go +++ b/pkg/skaffold/kubernetes/manifest/visitor_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubectl +package manifest import ( "fmt" diff --git a/pkg/skaffold/kubernetes/portforward/resource_forwarder_test.go b/pkg/skaffold/kubernetes/portforward/resource_forwarder_test.go index feb38b3829a..ef41e31eb18 100644 --- a/pkg/skaffold/kubernetes/portforward/resource_forwarder_test.go +++ b/pkg/skaffold/kubernetes/portforward/resource_forwarder_test.go @@ -33,7 +33,7 @@ import ( fakekubeclientset "k8s.io/client-go/kubernetes/fake" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" kubernetesclient "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/client" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" @@ -275,7 +275,7 @@ func TestRetrieveServices(t *testing.T) { Name: "svc1", Namespace: "test", Labels: map[string]string{ - deploy.RunIDLabel: "9876-6789", + label.RunIDLabel: "9876-6789", }, }, Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{Port: 8080}}}, @@ -284,7 +284,7 @@ func TestRetrieveServices(t *testing.T) { Name: "svc2", Namespace: "test1", Labels: map[string]string{ - deploy.RunIDLabel: "9876-6789", + label.RunIDLabel: "9876-6789", }, }, Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{Port: 8081}}}, @@ -314,7 +314,7 @@ func TestRetrieveServices(t *testing.T) { Name: "svc1", Namespace: "test", Labels: map[string]string{ - deploy.RunIDLabel: "9876-6789", + label.RunIDLabel: "9876-6789", }, }, Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{Port: 8080}}}, @@ -329,7 +329,7 @@ func TestRetrieveServices(t *testing.T) { Name: "svc1", Namespace: "test", Labels: map[string]string{ - deploy.RunIDLabel: "9876-6789", + label.RunIDLabel: "9876-6789", }, }, }, @@ -346,7 +346,7 @@ func TestRetrieveServices(t *testing.T) { client := fakekubeclientset.NewSimpleClientset(objs...) t.Override(&kubernetesclient.Client, mockClient(client)) - actual, err := retrieveServiceResources(fmt.Sprintf("%s=9876-6789", deploy.RunIDLabel), test.namespaces) + actual, err := retrieveServiceResources(fmt.Sprintf("%s=9876-6789", label.RunIDLabel), test.namespaces) t.CheckNoError(err) t.CheckDeepEqual(test.expected, actual) diff --git a/pkg/skaffold/runner/build_deploy.go b/pkg/skaffold/runner/build_deploy.go index cad5dd672c2..92861851c02 100644 --- a/pkg/skaffold/runner/build_deploy.go +++ b/pkg/skaffold/runner/build_deploy.go @@ -28,7 +28,7 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/color" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" ) @@ -144,7 +144,7 @@ type tagErr struct { // ApplyDefaultRepo applies the default repo to a given image tag. func (r *SkaffoldRunner) ApplyDefaultRepo(tag string) (string, error) { - return deploy.ApplyDefaultRepo(r.runCtx.GlobalConfig(), r.runCtx.DefaultRepo(), tag) + return deployutil.ApplyDefaultRepo(r.runCtx.GlobalConfig(), r.runCtx.DefaultRepo(), tag) } // imageTags generates tags for a list of artifacts diff --git a/pkg/skaffold/runner/deploy.go b/pkg/skaffold/runner/deploy.go index 1e38084bae2..be8024a8d62 100644 --- a/pkg/skaffold/runner/deploy.go +++ b/pkg/skaffold/runner/deploy.go @@ -28,7 +28,7 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/color" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" kubernetesclient "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/client" kubectx "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/context" @@ -66,7 +66,7 @@ See https://skaffold.dev/docs/pipeline-stages/taggers/#how-tagging-works`) } } - deployOut, postDeployFn, err := deploy.WithLogFile(time.Now().Format(deploy.TimeFormat)+".log", out, r.runCtx.Muted()) + deployOut, postDeployFn, err := deployutil.WithLogFile(time.Now().Format(deployutil.TimeFormat)+".log", out, r.runCtx.Muted()) if err != nil { return err } diff --git a/pkg/skaffold/runner/deploy_test.go b/pkg/skaffold/runner/deploy_test.go index fadbbe39088..350b08de3e9 100644 --- a/pkg/skaffold/runner/deploy_test.go +++ b/pkg/skaffold/runner/deploy_test.go @@ -29,7 +29,8 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/status" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/client" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" @@ -67,7 +68,7 @@ func TestDeploy(t *testing.T) { testutil.Run(t, test.description, func(t *testutil.T) { t.SetupFakeKubernetesContext(api.Config{CurrentContext: "cluster1"}) t.Override(&client.Client, mockK8sClient) - t.Override(&newStatusCheck, func(deploy.StatusCheckConfig, *deploy.DefaultLabeller) deploy.StatusChecker { + t.Override(&newStatusCheck, func(status.StatusCheckConfig, *label.DefaultLabeller) status.StatusChecker { return dummyStatusChecker{} }) @@ -117,7 +118,7 @@ func TestDeployNamespace(t *testing.T) { testutil.Run(t, test.description, func(t *testutil.T) { t.SetupFakeKubernetesContext(api.Config{CurrentContext: "cluster1"}) t.Override(&client.Client, mockK8sClient) - t.Override(&newStatusCheck, func(deploy.StatusCheckConfig, *deploy.DefaultLabeller) deploy.StatusChecker { + t.Override(&newStatusCheck, func(status.StatusCheckConfig, *label.DefaultLabeller) status.StatusChecker { return dummyStatusChecker{} }) diff --git a/pkg/skaffold/runner/new.go b/pkg/skaffold/runner/new.go index 905cc7879b5..65cf26ca592 100644 --- a/pkg/skaffold/runner/new.go +++ b/pkg/skaffold/runner/new.go @@ -29,9 +29,14 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/local" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/helm" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kpt" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kustomize" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/filemon" - "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" + pkgkubectl "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" @@ -43,7 +48,7 @@ import ( // NewForConfig returns a new SkaffoldRunner for a SkaffoldConfig func NewForConfig(runCtx *runcontext.RunContext) (*SkaffoldRunner, error) { - kubectlCLI := kubectl.NewCLI(runCtx, "") + kubectlCLI := pkgkubectl.NewCLI(runCtx, "") tagger, err := getTagger(runCtx) if err != nil { @@ -60,7 +65,7 @@ func NewForConfig(runCtx *runcontext.RunContext) (*SkaffoldRunner, error) { tryImportMissing = localBuilder.TryImportMissing() } - labeller := deploy.NewLabeller(runCtx.AddSkaffoldLabels(), runCtx.CustomLabels()) + labeller := label.NewLabeller(runCtx.AddSkaffoldLabels(), runCtx.CustomLabels()) tester := getTester(runCtx, imagesAreLocal) syncer := getSyncer(runCtx) var deployer deploy.Deployer @@ -196,21 +201,21 @@ func getSyncer(cfg sync.Config) sync.Syncer { return sync.NewSyncer(cfg) } -func getDeployer(cfg deploy.Config, labels map[string]string) (deploy.Deployer, error) { +func getDeployer(cfg kubectl.Config, labels map[string]string) (deploy.Deployer, error) { d := cfg.Pipeline().Deploy var deployers deploy.DeployerMux if d.HelmDeploy != nil { - deployers = append(deployers, deploy.NewHelmDeployer(cfg, labels)) + deployers = append(deployers, helm.NewHelmDeployer(cfg, labels)) } if d.KptDeploy != nil { - deployers = append(deployers, deploy.NewKptDeployer(cfg, labels)) + deployers = append(deployers, kpt.NewKptDeployer(cfg, labels)) } if d.KubectlDeploy != nil { - deployer, err := deploy.NewKubectlDeployer(cfg, labels) + deployer, err := kubectl.NewKubectlDeployer(cfg, labels) if err != nil { return nil, err } @@ -218,7 +223,7 @@ func getDeployer(cfg deploy.Config, labels map[string]string) (deploy.Deployer, } if d.KustomizeDeploy != nil { - deployer, err := deploy.NewKustomizeDeployer(cfg, labels) + deployer, err := kustomize.NewKustomizeDeployer(cfg, labels) if err != nil { return nil, err } diff --git a/pkg/skaffold/runner/new_test.go b/pkg/skaffold/runner/new_test.go index b47e464dac7..020d24e81e8 100644 --- a/pkg/skaffold/runner/new_test.go +++ b/pkg/skaffold/runner/new_test.go @@ -22,6 +22,10 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/helm" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kpt" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kustomize" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/testutil" @@ -41,12 +45,12 @@ func TestGetDeployer(tOuter *testing.T) { { description: "helm deployer", cfg: latest.DeployType{HelmDeploy: &latest.HelmDeploy{}}, - expected: deploy.NewHelmDeployer(&runcontext.RunContext{}, nil), + expected: helm.NewHelmDeployer(&runcontext.RunContext{}, nil), }, { description: "kubectl deployer", cfg: latest.DeployType{KubectlDeploy: &latest.KubectlDeploy{}}, - expected: t.RequireNonNilResult(deploy.NewKubectlDeployer(&runcontext.RunContext{ + expected: t.RequireNonNilResult(kubectl.NewKubectlDeployer(&runcontext.RunContext{ Cfg: latest.Pipeline{ Deploy: latest.DeployConfig{ DeployType: latest.DeployType{ @@ -61,7 +65,7 @@ func TestGetDeployer(tOuter *testing.T) { { description: "kustomize deployer", cfg: latest.DeployType{KustomizeDeploy: &latest.KustomizeDeploy{}}, - expected: t.RequireNonNilResult(deploy.NewKustomizeDeployer(&runcontext.RunContext{ + expected: t.RequireNonNilResult(kustomize.NewKustomizeDeployer(&runcontext.RunContext{ Cfg: latest.Pipeline{ Deploy: latest.DeployConfig{ DeployType: latest.DeployType{ @@ -76,7 +80,7 @@ func TestGetDeployer(tOuter *testing.T) { { description: "kpt deployer", cfg: latest.DeployType{KptDeploy: &latest.KptDeploy{}}, - expected: deploy.NewKptDeployer(&runcontext.RunContext{}, nil), + expected: kpt.NewKptDeployer(&runcontext.RunContext{}, nil), }, { description: "multiple deployers", @@ -85,8 +89,8 @@ func TestGetDeployer(tOuter *testing.T) { KptDeploy: &latest.KptDeploy{}, }, expected: deploy.DeployerMux{ - deploy.NewHelmDeployer(&runcontext.RunContext{}, nil), - deploy.NewKptDeployer(&runcontext.RunContext{}, nil), + helm.NewHelmDeployer(&runcontext.RunContext{}, nil), + kpt.NewKptDeployer(&runcontext.RunContext{}, nil), }, }, } diff --git a/pkg/skaffold/runner/runner.go b/pkg/skaffold/runner/runner.go index a772f4b5391..62c31d72394 100644 --- a/pkg/skaffold/runner/runner.go +++ b/pkg/skaffold/runner/runner.go @@ -24,6 +24,8 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/cache" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/status" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/filemon" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubectl" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" @@ -66,7 +68,7 @@ type SkaffoldRunner struct { cache cache.Cache changeSet changeSet runCtx *runcontext.RunContext - labeller *deploy.DefaultLabeller + labeller *label.DefaultLabeller builds []build.Artifact // podSelector is used to determine relevant pods for logging and portForwarding @@ -81,7 +83,7 @@ type SkaffoldRunner struct { // for testing var ( - newStatusCheck = deploy.NewStatusChecker + newStatusCheck = status.NewStatusChecker ) // HasDeployed returns true if this runner has deployed something. diff --git a/pkg/skaffold/runner/runner_test.go b/pkg/skaffold/runner/runner_test.go index 191d928832f..4880a9080b8 100644 --- a/pkg/skaffold/runner/runner_test.go +++ b/pkg/skaffold/runner/runner_test.go @@ -29,6 +29,9 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/helm" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kustomize" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/filemon" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/defaults" @@ -276,7 +279,7 @@ func TestNewForConfig(t *testing.T) { }, expectedBuilder: &local.Builder{}, expectedTester: &test.FullTester{}, - expectedDeployer: &deploy.KubectlDeployer{}, + expectedDeployer: &kubectl.KubectlDeployer{}, }, { description: "bad tagger config", @@ -301,7 +304,7 @@ func TestNewForConfig(t *testing.T) { shouldErr: true, expectedBuilder: &local.Builder{}, expectedTester: &test.FullTester{}, - expectedDeployer: &deploy.KubectlDeployer{}, + expectedDeployer: &kubectl.KubectlDeployer{}, }, { description: "no artifacts, cache", @@ -320,7 +323,7 @@ func TestNewForConfig(t *testing.T) { }, expectedBuilder: &local.Builder{}, expectedTester: &test.FullTester{}, - expectedDeployer: &deploy.KubectlDeployer{}, + expectedDeployer: &kubectl.KubectlDeployer{}, cacheArtifacts: true, }, { @@ -343,9 +346,9 @@ func TestNewForConfig(t *testing.T) { expectedBuilder: &local.Builder{}, expectedTester: &test.FullTester{}, expectedDeployer: deploy.DeployerMux([]deploy.Deployer{ - &deploy.HelmDeployer{}, - &deploy.KubectlDeployer{}, - &deploy.KustomizeDeployer{}, + &helm.HelmDeployer{}, + &kubectl.KubectlDeployer{}, + &kustomize.KustomizeDeployer{}, }), }, }