From 5a8d5026f6675f1890a4f1d3048abab025691883 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 6 Apr 2021 11:15:58 +0200 Subject: [PATCH] Move Kustomize patch tests to Go test suite Signed-off-by: Hidde Beydals --- .github/workflows/e2e.yaml | 20 -- config/testdata/overrides/images.yaml | 34 --- config/testdata/overrides/patches.yaml | 47 ----- .../kustomization_controller_patch_test.go | 195 ++++++++++++++++++ .../kustomization_controller_sops_test.go | 138 +------------ controllers/kustomization_controller_test.go | 186 ++++++++++++----- controllers/testdata/patch/deployment.yaml | 19 ++ controllers/testdata/sops/secret.age.yaml | 17 +- controllers/testdata/sops/secret.yaml | 37 ++-- go.mod | 1 + 10 files changed, 378 insertions(+), 316 deletions(-) delete mode 100644 config/testdata/overrides/images.yaml delete mode 100644 config/testdata/overrides/patches.yaml create mode 100644 controllers/kustomization_controller_patch_test.go create mode 100644 controllers/testdata/patch/deployment.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 77e3db34..dfb3fa2c 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -79,26 +79,6 @@ jobs: kubectl -n impersonation wait kustomizations/podinfo --for=condition=ready --timeout=4m kubectl -n impersonation delete kustomizations/podinfo until kubectl -n impersonation get deploy/podinfo 2>&1 | grep NotFound ; do sleep 2; done - - name: Run images override tests - run: | - kubectl -n images-test apply -f ./config/testdata/overrides/images.yaml - kubectl -n images-test wait kustomizations/podinfo --for=condition=ready --timeout=1m - ACTUAL_TAG=$(kubectl -n images-test get deployments podinfo -o jsonpath='{.spec.template.spec.containers[0].image}' | cut -f2 -d ":") - if [[ $ACTUAL_TAG != "5.0.0" ]]; then echo "Image tag was not overwritten" && exit 1; fi - - name: Run patches override tests - run: | - kubectl -n patches-test apply -f ./config/testdata/overrides/patches.yaml - kubectl -n patches-test wait kustomizations/podinfo --for=condition=ready --timeout=1m - WANT="xxxx" - RESULT=$(kubectl -n patches-test get deployment podinfo -o jsonpath='{.metadata.labels.yyyy}') - if [ "$RESULT" != "$WANT" ]; then - echo -e "$RESULT\n\ndoes not equal\n\n$WANT" && exit 1 - fi - WANT="yyyy" - RESULT=$(kubectl -n patches-test get deployment podinfo -o jsonpath='{.metadata.labels.xxxx}') - if [ "$RESULT" != "$WANT" ]; then - echo -e "$RESULT\n\ndoes not equal\n\$WANT" && exit 1 - fi - name: Logs run: | kubectl -n kustomize-system logs deploy/source-controller diff --git a/config/testdata/overrides/images.yaml b/config/testdata/overrides/images.yaml deleted file mode 100644 index 9d9a0a13..00000000 --- a/config/testdata/overrides/images.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: images-test ---- -apiVersion: source.toolkit.fluxcd.io/v1beta1 -kind: GitRepository -metadata: - name: podinfo - namespace: images-test -spec: - interval: 5m - url: https://github.com/stefanprodan/podinfo - ref: - branch: master ---- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 -kind: Kustomization -metadata: - name: podinfo - namespace: images-test -spec: - targetNamespace: images-test - interval: 5m - path: "./kustomize" - prune: true - sourceRef: - kind: GitRepository - name: podinfo - validation: client - images: - - name: ghcr.io/stefanprodan/podinfo - newName: ghcr.io/stefanprodan/podinfo - newTag: 5.0.0 diff --git a/config/testdata/overrides/patches.yaml b/config/testdata/overrides/patches.yaml deleted file mode 100644 index 7ad2edfe..00000000 --- a/config/testdata/overrides/patches.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: patches-test ---- -apiVersion: source.toolkit.fluxcd.io/v1beta1 -kind: GitRepository -metadata: - name: podinfo - namespace: patches-test -spec: - interval: 5m - url: https://github.com/stefanprodan/podinfo - ref: - branch: master ---- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 -kind: Kustomization -metadata: - name: podinfo - namespace: patches-test -spec: - targetNamespace: patches-test - interval: 5m - path: "./kustomize" - prune: true - sourceRef: - kind: GitRepository - name: podinfo - validation: client - patchesStrategicMerge: - - kind: Deployment - apiVersion: apps/v1 - metadata: - name: podinfo - labels: - xxxx: yyyy - patchesJson6902: - - target: - group: apps - version: v1 - kind: Deployment - name: podinfo - patch: - - op: add - path: /metadata/labels/yyyy - value: xxxx diff --git a/controllers/kustomization_controller_patch_test.go b/controllers/kustomization_controller_patch_test.go new file mode 100644 index 00000000..68bb3dc5 --- /dev/null +++ b/controllers/kustomization_controller_patch_test.go @@ -0,0 +1,195 @@ +/* +Copyright 2021 The Flux 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 controllers + +import ( + "context" + "fmt" + "os" + "time" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/fluxcd/pkg/apis/kustomize" + "github.com/fluxcd/pkg/apis/meta" + "github.com/fluxcd/pkg/testserver" + + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" +) + +const timeout = 10 * time.Second + +var _ = Describe("KustomizationReconciler", func() { + var ( + artifactServer *testserver.ArtifactServer + ) + + BeforeEach(func() { + var err error + artifactServer, err = testserver.NewTempArtifactServer() + Expect(err).ToNot(HaveOccurred()) + artifactServer.Start() + }) + + AfterEach(func() { + artifactServer.Stop() + os.RemoveAll(artifactServer.Root()) + }) + + Context("Kustomize patches", func() { + var ( + namespace *corev1.Namespace + kubeconfig *kustomizev1.KubeConfig + artifactFile string + artifactChecksum string + artifactURL string + kustomization *kustomizev1.Kustomization + ) + BeforeEach(func() { + namespace = &corev1.Namespace{} + namespace.Name = "patch-" + randStringRunes(5) + Expect(k8sClient.Create(context.Background(), namespace)).To(Succeed()) + + kubecfgSecret, err := kubeConfigSecret() + Expect(err).ToNot(HaveOccurred()) + kubecfgSecret.Namespace = namespace.Name + Expect(k8sClient.Create(context.Background(), kubecfgSecret)).To(Succeed()) + kubeconfig = &kustomizev1.KubeConfig{ + SecretRef: meta.LocalObjectReference{ + Name: kubecfgSecret.Name, + }, + } + + artifactFile = "patch-" + randStringRunes(5) + artifactChecksum, err = initArtifact(artifactServer, "testdata/patch", artifactFile) + Expect(err).ToNot(HaveOccurred()) + artifactURL, err = artifactServer.URLForFile(artifactFile) + Expect(err).ToNot(HaveOccurred()) + + gitRepoKey := client.ObjectKey{ + Name: fmt.Sprintf("patch-%s", randStringRunes(5)), + Namespace: namespace.Name, + } + gitRepo := readyGitRepository(gitRepoKey, artifactURL, "main/"+artifactChecksum, artifactChecksum) + Expect(k8sClient.Create(context.Background(), gitRepo)).To(Succeed()) + Expect(k8sClient.Status().Update(context.Background(), gitRepo)).To(Succeed()) + + kustomizationKey := types.NamespacedName{ + Name: "patch-" + randStringRunes(5), + Namespace: namespace.Name, + } + kustomization = &kustomizev1.Kustomization{ + ObjectMeta: metav1.ObjectMeta{ + Name: kustomizationKey.Name, + Namespace: kustomizationKey.Namespace, + }, + Spec: kustomizev1.KustomizationSpec{ + Path: "./", + KubeConfig: kubeconfig, + SourceRef: kustomizev1.CrossNamespaceSourceReference{ + Name: gitRepoKey.Name, + Namespace: gitRepoKey.Namespace, + Kind: sourcev1.GitRepositoryKind, + }, + TargetNamespace: namespace.Name, + }, + } + }) + + AfterEach(func() { + Expect(k8sClient.Delete(context.Background(), namespace)).To(Succeed()) + }) + + It("patches images", func() { + kustomization.Spec.Images = []kustomize.Image{ + { + Name: "podinfo", + NewName: "ghcr.io/stefanprodan/podinfo", + NewTag: "5.2.0", + }, + } + Expect(k8sClient.Create(context.TODO(), kustomization)).To(Succeed()) + + Eventually(func() bool { + var obj kustomizev1.Kustomization + _ = k8sClient.Get(context.Background(), ObjectKey(kustomization), &obj) + return obj.Status.LastAppliedRevision == "main/"+artifactChecksum + }, timeout, time.Second).Should(BeTrue()) + + var deployment appsv1.Deployment + Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) + Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("ghcr.io/stefanprodan/podinfo:5.2.0")) + }) + + It("strategic merge patches", func() { + kustomization.Spec.PatchesStrategicMerge = []apiextensionsv1.JSON{ + { + Raw: []byte(`{"kind":"Deployment","apiVersion":"apps/v1","metadata":{"name":"podinfo","labels":{"xxxx":"yyyy"}}}`), + }, + } + Expect(k8sClient.Create(context.TODO(), kustomization)).To(Succeed()) + + Eventually(func() bool { + var obj kustomizev1.Kustomization + _ = k8sClient.Get(context.Background(), ObjectKey(kustomization), &obj) + return obj.Status.LastAppliedRevision == "main/"+artifactChecksum + }, timeout, time.Second).Should(BeTrue()) + + var deployment appsv1.Deployment + Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) + Expect(deployment.ObjectMeta.Labels["xxxx"]).To(Equal("yyyy")) + }) + + It("JSON6902 patches", func() { + kustomization.Spec.PatchesJSON6902 = []kustomize.JSON6902Patch{ + { + + Patch: []kustomize.JSON6902{ + {Op: "add", Path: "/metadata/labels/yyyy", Value: &apiextensionsv1.JSON{Raw: []byte(`"xxxx"`)}}, + {Op: "replace", Path: "/spec/replicas", Value: &apiextensionsv1.JSON{Raw: []byte("2")}}, + }, + Target: kustomize.Selector{ + Group: "apps", + Version: "v1", + Kind: "Deployment", + Name: "podinfo", + }, + }, + } + Expect(k8sClient.Create(context.TODO(), kustomization)).To(Succeed()) + + Eventually(func() bool { + var obj kustomizev1.Kustomization + _ = k8sClient.Get(context.Background(), ObjectKey(kustomization), &obj) + return obj.Status.LastAppliedRevision == "main/"+artifactChecksum + }, timeout, time.Second).Should(BeTrue()) + + var deployment appsv1.Deployment + Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) + Expect(deployment.ObjectMeta.Labels["yyyy"]).To(Equal("xxxx")) + Expect(*deployment.Spec.Replicas).To(Equal(int32(2))) + }) + }) +}) diff --git a/controllers/kustomization_controller_sops_test.go b/controllers/kustomization_controller_sops_test.go index 7655b8d3..ac0892d4 100644 --- a/controllers/kustomization_controller_sops_test.go +++ b/controllers/kustomization_controller_sops_test.go @@ -1,5 +1,5 @@ /* -Copyright 2021it com The Flux authors +Copyright 2021 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,16 +17,10 @@ limitations under the License. package controllers import ( - "archive/tar" - "compress/gzip" "context" - "crypto/sha1" "fmt" - "io" "io/ioutil" "os" - "path/filepath" - "strings" "time" "github.com/fluxcd/pkg/apis/meta" @@ -37,12 +31,11 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" ) -const timeout = 10 * time.Second - var _ = Describe("KustomizationReconciler", func() { var ( artifactServer *testserver.ArtifactServer @@ -89,37 +82,11 @@ var _ = Describe("KustomizationReconciler", func() { artifactURL, err = artifactServer.URLForFile(artifactFile) Expect(err).ToNot(HaveOccurred()) - gitRepoKey := types.NamespacedName{ - Name: fmt.Sprintf("%s", randStringRunes(5)), + gitRepoKey := client.ObjectKey{ + Name: fmt.Sprintf("sops-%s", randStringRunes(5)), Namespace: namespace.Name, } - gitRepo := &sourcev1.GitRepository{ - ObjectMeta: metav1.ObjectMeta{ - Name: gitRepoKey.Name, - Namespace: gitRepoKey.Namespace, - }, - Spec: sourcev1.GitRepositorySpec{ - URL: "https://github.com/test/repository", - Interval: metav1.Duration{Duration: time.Minute}, - }, - Status: sourcev1.GitRepositoryStatus{ - Conditions: []metav1.Condition{ - { - Type: meta.ReadyCondition, - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: sourcev1.GitOperationSucceedReason, - }, - }, - Artifact: &sourcev1.Artifact{ - Path: artifactURL, - URL: artifactURL, - Revision: "main/" + artifactChecksum, - Checksum: artifactChecksum, - LastUpdateTime: metav1.Now(), - }, - }, - } + gitRepo := readyGitRepository(gitRepoKey, artifactURL, "main/"+artifactChecksum, artifactChecksum) Expect(k8sClient.Create(context.Background(), gitRepo)).To(Succeed()) Expect(k8sClient.Status().Update(context.Background(), gitRepo)).To(Succeed()) @@ -166,11 +133,7 @@ var _ = Describe("KustomizationReconciler", func() { Name: sopsSecretKey.Name, }, }, - PostBuild: &kustomizev1.PostBuild{ - Substitute: map[string]string{ - "FIXTURE_NS": namespace.Name, - }, - }, + TargetNamespace: namespace.Name, }, } Expect(k8sClient.Create(context.Background(), kustomization)).To(Succeed()) @@ -197,92 +160,3 @@ var _ = Describe("KustomizationReconciler", func() { }) }) }) - -func initArtifact(artifactServer *testserver.ArtifactServer, fixture, path string) (string, error) { - if f, err := os.Stat(fixture); os.IsNotExist(err) || !f.IsDir() { - return "", fmt.Errorf("invalid fixture path: %s", fixture) - } - f, err := os.Create(filepath.Join(artifactServer.Root(), path)) - if err != nil { - return "", err - } - defer func() { - if err != nil { - os.Remove(f.Name()) - } - }() - - h := sha1.New() - - mw := io.MultiWriter(h, f) - gw := gzip.NewWriter(mw) - tw := tar.NewWriter(gw) - - if err = filepath.Walk(fixture, func(p string, fi os.FileInfo, err error) error { - if err != nil { - return err - } - - // Ignore anything that is not a file (directories, symlinks) - if !fi.Mode().IsRegular() { - return nil - } - - // Ignore dotfiles - if strings.HasPrefix(fi.Name(), ".") { - return nil - } - - header, err := tar.FileInfoHeader(fi, p) - if err != nil { - return err - } - // The name needs to be modified to maintain directory structure - // as tar.FileInfoHeader only has access to the base name of the file. - // Ref: https://golang.org/src/archive/tar/common.go?#L626 - relFilePath := p - if filepath.IsAbs(fixture) { - relFilePath, err = filepath.Rel(fixture, p) - if err != nil { - return err - } - } - header.Name = relFilePath - - if err := tw.WriteHeader(header); err != nil { - return err - } - - f, err := os.Open(p) - if err != nil { - f.Close() - return err - } - if _, err := io.Copy(tw, f); err != nil { - f.Close() - return err - } - return f.Close() - }); err != nil { - return "", err - } - - if err := tw.Close(); err != nil { - gw.Close() - f.Close() - return "", err - } - if err := gw.Close(); err != nil { - f.Close() - return "", err - } - if err := f.Close(); err != nil { - return "", err - } - - if err := os.Chmod(f.Name(), 0644); err != nil { - return "", err - } - - return fmt.Sprintf("%x", h.Sum(nil)), nil -} diff --git a/controllers/kustomization_controller_test.go b/controllers/kustomization_controller_test.go index 1cfe1954..655963dd 100644 --- a/controllers/kustomization_controller_test.go +++ b/controllers/kustomization_controller_test.go @@ -17,8 +17,15 @@ limitations under the License. package controllers import ( + "archive/tar" + "compress/gzip" "context" + "crypto/sha1" "fmt" + "io" + "os" + "path/filepath" + "strings" "time" . "github.com/onsi/ginkgo" @@ -31,11 +38,13 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" + + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" ) var _ = Describe("KustomizationReconciler", func() { @@ -98,33 +107,7 @@ var _ = Describe("KustomizationReconciler", func() { Name: fmt.Sprintf("%s", randStringRunes(5)), Namespace: namespace.Name, } - repository := &sourcev1.GitRepository{ - ObjectMeta: metav1.ObjectMeta{ - Name: repositoryName.Name, - Namespace: repositoryName.Namespace, - }, - Spec: sourcev1.GitRepositorySpec{ - URL: "https://github.com/test/repository", - Interval: metav1.Duration{Duration: reconciliationInterval}, - }, - Status: sourcev1.GitRepositoryStatus{ - Conditions: []metav1.Condition{ - { - Type: meta.ReadyCondition, - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: sourcev1.GitOperationSucceedReason, - }, - }, - URL: url, - Artifact: &sourcev1.Artifact{ - Path: url, - URL: url, - Revision: t.expectRevision, - LastUpdateTime: metav1.Now(), - }, - }, - } + repository := readyGitRepository(repositoryName, url, t.expectRevision, "") Expect(k8sClient.Create(context.Background(), repository)).Should(Succeed()) Expect(k8sClient.Status().Update(context.Background(), repository)).Should(Succeed()) defer k8sClient.Delete(context.Background(), repository) @@ -303,33 +286,7 @@ spec: Name: fmt.Sprintf("%s", randStringRunes(5)), Namespace: namespace.Name, } - repository := &sourcev1.GitRepository{ - ObjectMeta: metav1.ObjectMeta{ - Name: repositoryName.Name, - Namespace: repositoryName.Namespace, - }, - Spec: sourcev1.GitRepositorySpec{ - URL: "https://github.com/test/repository", - Interval: metav1.Duration{Duration: reconciliationInterval}, - }, - Status: sourcev1.GitRepositoryStatus{ - Conditions: []metav1.Condition{ - { - Type: meta.ReadyCondition, - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: sourcev1.GitOperationSucceedReason, - }, - }, - URL: url, - Artifact: &sourcev1.Artifact{ - Path: url, - URL: url, - Revision: "v1", - LastUpdateTime: metav1.Now(), - }, - }, - } + repository := readyGitRepository(repositoryName, url, "v1", "") Expect(k8sClient.Create(context.Background(), repository)).To(Succeed()) Expect(k8sClient.Status().Update(context.Background(), repository)).To(Succeed()) defer k8sClient.Delete(context.Background(), repository) @@ -435,3 +392,122 @@ func kubeConfigSecret() (*corev1.Secret, error) { }, }, nil } + +func initArtifact(artifactServer *testserver.ArtifactServer, fixture, path string) (string, error) { + if f, err := os.Stat(fixture); os.IsNotExist(err) || !f.IsDir() { + return "", fmt.Errorf("invalid fixture path: %s", fixture) + } + f, err := os.Create(filepath.Join(artifactServer.Root(), path)) + if err != nil { + return "", err + } + defer func() { + if err != nil { + os.Remove(f.Name()) + } + }() + + h := sha1.New() + + mw := io.MultiWriter(h, f) + gw := gzip.NewWriter(mw) + tw := tar.NewWriter(gw) + + if err = filepath.Walk(fixture, func(p string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + // Ignore anything that is not a file (directories, symlinks) + if !fi.Mode().IsRegular() { + return nil + } + + // Ignore dotfiles + if strings.HasPrefix(fi.Name(), ".") { + return nil + } + + header, err := tar.FileInfoHeader(fi, p) + if err != nil { + return err + } + // The name needs to be modified to maintain directory structure + // as tar.FileInfoHeader only has access to the base name of the file. + // Ref: https://golang.org/src/archive/tar/common.go?#L626 + relFilePath := p + if filepath.IsAbs(fixture) { + relFilePath, err = filepath.Rel(fixture, p) + if err != nil { + return err + } + } + header.Name = relFilePath + + if err := tw.WriteHeader(header); err != nil { + return err + } + + f, err := os.Open(p) + if err != nil { + f.Close() + return err + } + if _, err := io.Copy(tw, f); err != nil { + f.Close() + return err + } + return f.Close() + }); err != nil { + return "", err + } + + if err := tw.Close(); err != nil { + gw.Close() + f.Close() + return "", err + } + if err := gw.Close(); err != nil { + f.Close() + return "", err + } + if err := f.Close(); err != nil { + return "", err + } + + if err := os.Chmod(f.Name(), 0644); err != nil { + return "", err + } + + return fmt.Sprintf("%x", h.Sum(nil)), nil +} + +func readyGitRepository(objKey client.ObjectKey, artifactURL, artifactRevision, artifactChecksum string) *sourcev1.GitRepository { + return &sourcev1.GitRepository{ + ObjectMeta: metav1.ObjectMeta{ + Name: objKey.Name, + Namespace: objKey.Namespace, + }, + Spec: sourcev1.GitRepositorySpec{ + URL: "https://github.com/test/repository", + Interval: metav1.Duration{Duration: time.Minute}, + }, + Status: sourcev1.GitRepositoryStatus{ + Conditions: []metav1.Condition{ + { + Type: meta.ReadyCondition, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Reason: sourcev1.GitOperationSucceedReason, + }, + }, + Artifact: &sourcev1.Artifact{ + Path: artifactURL, + URL: artifactURL, + Revision: artifactRevision, + Checksum: artifactChecksum, + LastUpdateTime: metav1.Now(), + }, + }, + } +} diff --git a/controllers/testdata/patch/deployment.yaml b/controllers/testdata/patch/deployment.yaml new file mode 100644 index 00000000..d38011b6 --- /dev/null +++ b/controllers/testdata/patch/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: podinfo + labels: + app: podinfo +spec: + replicas: 1 + selector: + matchLabels: + app: podinfo + template: + metadata: + labels: + app: podinfo + spec: + containers: + - name: podinfo + image: podinfo diff --git a/controllers/testdata/sops/secret.age.yaml b/controllers/testdata/sops/secret.age.yaml index 0e6b7198..17c7172c 100644 --- a/controllers/testdata/sops/secret.age.yaml +++ b/controllers/testdata/sops/secret.age.yaml @@ -2,9 +2,8 @@ apiVersion: v1 kind: Secret metadata: name: sops-age - namespace: ${FIXTURE_NS} stringData: - secret: ENC[AES256_GCM,data:7fIpFCqSZxBl82Y/ePD3QJ0m,iv:yMrwMbWwDZ18RjWye82dWn/CXZKeNIufLiqNWQTbxok=,tag:JEcC7MKwxfGBFuk0gdRWNA==,type:str] + secret: ENC[AES256_GCM,data:RwzrBF8wy16SpfbQoeADeKyz,iv:DuJce2Ebx1Y49DaLCOJ74OOkgiv21roxhz/sZqKCSSs=,tag:Gg9XHapZI5q+rvtgeY6nrg==,type:str] sops: kms: [] gcp_kms: [] @@ -14,14 +13,14 @@ sops: - recipient: age1l44xcng8dqj32nlv6d930qvvrny05hglzcv9qpc7kxjc6902ma4qufys29 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2Q3llZGdyVEtNWFE4SUxq - OVhjelNuTTh0WWR0TGo4dmp4VU1SdkVSblQwCmJkUVlLUllvaWl3S01nTEJQRllw - YTVNcWZpSDJOOTNNaUFYckZhQTJ5cVkKLS0tIFZRREM2NWZrRjZiN3pVdnFoeTdo - cm16SUxUY2dEclV4My9mUFVsWlplRGMKf5d+VZr7Q5cvddhvEPW4pOBjWVhL8UQX - Pch6nsGp2RMC7V/BaknpLmx8iFCXslajzjI13P3KhT1B6QR4ZtkfUA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNeGduOFZjRWw2WTFQdWdu + OS83OEZaN1E1aU1zSThhMlNEZzd0aEYvdURFCnE3bmJ5c3J2cDNEbXhselFPVC9v + NFhMRjZjOHZOdEpoYjdiS0ZPd2pvN1kKLS0tIDZUVEFoblpDNWhnaWxYRTBjaktk + bHRXV0o1K2ZDNm5Mem5SdzNBMTNuNFUKylE2cRLqydjj6e4+4Giwn4y8mIPej+CM + Bab3UWiK1da2rFNTOEnoHl6QDAVxNrWdrrIa5k22SzApT88VtJ4xuQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2021-04-01T10:19:56Z" - mac: ENC[AES256_GCM,data:GEQbue4aXmnytMlM3QbOJxWBn/u3KfWB1q66yy4UGvAUz4E8yV1PUDqx7LDEwYusxu+30Zu/zCtJrrYkrWVGiZwQBguhhXNZu1WLBsvTjt5f6mz9/EvBP2r3j4npp/5QarKGpnL5g6bWxh1bVMTOau8hf4Qn1VcpBcHmmAMzCyA=,iv:FIqAJKZIi8gKUSDwinG4znNsfz2vdLkJLBIxevYDGio=,tag:aZ+rpcn3U9ypr4bU/jMEZQ==,type:str] + lastmodified: "2021-04-06T09:07:05Z" + mac: ENC[AES256_GCM,data:oaM8qFtEP8dOCd/Tr5yb08uetsnDtZO8o1rCayN53ncQ1HUAdhRBrFdmbYx1YTh1mwQVVN6sGYqFZU1LBMVv5pTqvpwd41biJZEg8NznXQWx0GA2Z6HOrblGhFZKrqky3P5xN+6j63zkJizXWgBMKzRvBnsVKxjZGr/lk1vVVv4=,iv:p4y9Fo3SArkEMuoK2d9sQYgNdc0iw/StFhg/5LnhcXM=,tag:61JGbnEw35tv6WnGj46JOw==,type:str] pgp: [] encrypted_regex: ^(data|stringData)$ version: 3.7.0 diff --git a/controllers/testdata/sops/secret.yaml b/controllers/testdata/sops/secret.yaml index fe5ecf59..c6aa991c 100644 --- a/controllers/testdata/sops/secret.yaml +++ b/controllers/testdata/sops/secret.yaml @@ -2,36 +2,35 @@ apiVersion: v1 kind: Secret metadata: name: sops-pgp - namespace: ${FIXTURE_NS} stringData: - secret: ENC[AES256_GCM,data:9+6Vzroi515jTjARa+eqHV6D,iv:DtwcBC0x4KXaAesRstWBVaFCQO2cxDKKFidfykUnNRs=,tag:7RBPloFTMTVggwEjb0ZB9Q==,type:str] + secret: ENC[AES256_GCM,data:rZEmadbj49GoQLlK85hKKAsc,iv:FX4Dfbd173bZQdUgEVRo4q29m/Gz9ob07QHFuiCAufA=,tag:VM6tzAVdGjsythy2Mr5tvw==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: [] - lastmodified: "2021-04-01T10:20:06Z" - mac: ENC[AES256_GCM,data:vxSUzUF1gaYx941Av1KCGkhLrEPNY2GBd8cgke34g/75yaAUZCDF50txTh4t1VlgLvyj0TL459if0J/7cLHOF8a7zoCtYWg3fSTIg8y+1K+94myDpuzRMiXWbsdZdXNtBIJXICUdD5oIg9tBEcYqctwm08wgVQdlTCAjrY00/oo=,iv:cf5SpdXfLD05uQ0bwMBYK5TWXgwLubPbhe9HMBL+Uss=,tag:mY7cdDXmctw5I9FGPj+QKA==,type:str] + lastmodified: "2021-04-06T09:07:19Z" + mac: ENC[AES256_GCM,data:iBg8FY39VSykcWZ/asv86P3VNZkscQdINNOy3UtI5m4OWDpUkyDuq66w7ELiiEXJ3D+b7JKJrsSrYtT7Tn7t+NZGxJcLQFEczozvWgKd2hCikxnMEepCJ3tRcoz7JaItommi1HvA08syGfLA5f6eOxsHQWzmjVdYaVpQ4VGRibk=,iv:VI+Fb7dXV4442IMKZSHOb0GJ/2nNgK9AUTblOZ49Oco=,tag:gJjFguJeE7irKZW7yZi0jw==,type:str] pgp: - - created_at: "2021-04-01T10:20:06Z" + - created_at: "2021-04-06T09:07:19Z" enc: | -----BEGIN PGP MESSAGE----- - hQIMA90SOJihaAjLAQ//WJRMyMrS810ZxeltKQVbxhkAy/0VeHZlj1lqGJGJVAqL - 9PtRnClWNbdU3s3Rkkxh4NTwYk7t/CN9Md7WJ+Kr+e5EzbR045BUAZoJ8EvznykU - f6vDejxlb7ltEr4X1WjN2RDK2q/KrVN9GFB0hg8Wq+g6LS0qgq+Eyu98EJo3wczJ - zYnJ19wf/fyIi1dhEgSq76mUkoxUTSoxEvpg8XkPoMuMpI5PpszhfCK64GUZCOji - TYqbSeD0gSnPvpINbKgQo+SuSMKh63uqgqZ7BEhzx8TK6pE7qzW/B6ttri9WcyU8 - s/2rxwzJRYXgTp2rJ0qyRDvlBSsTV1YzNnFaM+kfO9Vn30JxY4/IXJFCOGefwqrD - V1Q0CG8n3yWTktiN2eydfXaXNlKJB0x4fu8P6BIe7y3nVyGXIb9i63Mj1+ebsA+8 - 7zYl9tEn+96CmtaaoSejTJ8a4vkt2JVcURKFbDufTh3oRN70iGmu8ik0EU0IKuz0 - ANrq14JVH11MTnm2uhpqrC8nr3dein2dYG3bVkbxqccB7/3u07D8760dC6yFdqmU - OeztFtcbz/GuUOxckX/I4EFgnX/8l21YLvVF9yE/CAFzIfLunp63dRhRIbfn7Qkl - V0pb1DdUjCdczuy1xreYsMf3Vv44cVjNdpkqANg+pBaPbzqh3WYskLA6bvSrlhjS - XAHNfqolTH6NJXPXLHz82rd5erZXHFWUG5roD2YrKloKfV93dDQ+4UqqohHS1l3C - 5db1+wVCmE6yrA5A5jrgIqKk8kkNAmz6yBL/yRO3IR2cAC0SXjDdKxCN9MYj - =Qt5P + hQIMA90SOJihaAjLAQ/+LnZo9UHmJ2Llcpq6m5gjo5hbCx6aYTbrvJOFCWeu2oyC + 71XsuTUzBp7TK8SkGrxlJmUodezACQ3rCsKY/r2GI4t9HkVRSuhnc/YQMunm3iG1 + bsgfdV/KBm0Go7dFXy2R1Pt3PuVnuM9MZ59U4SdqYGZDI7vzy2gfH127qa3oIOoF + 2OFfwhUy8nZIVCJ47ExIdrc7Qdk94tbLfwmBAKHFN4Ab0YXasKCpH9O+9/vQ+JJU + 7xy61Nv4dqtEDYU9QTh2ZuT6ZaWikTqCcIv/W7lW1RsT8n7YiRZv9POobKDh5KbP + PyfqvJsLcJB8LHN2kZfwr6Iemuce19kRi+7JL9zMGRJSsq0thJ0ly3JBi48pU27w + jbFnmxlIwfb0EsLBp9lsxw7GoUbooSC/rfI5NVeQ+4lFA4gQn2oz7i4zTYesnwil + lrgMxz49SSluAYsGjrJHc+ABmlDz83K42KtWlNjwaIbDgHMl4EbYUe4pxcynEZ6D + 0csDIsIA15MP0THfTL1F1vkhvdPHNuUlVjFqgWaJAP2CC5KH8IeTCUN72FySEYAB + BJH+VQoRnS942M8VQAfUQyBsfZKtQhyCkU7KEimUjQzy75JWgy8YMX1mviXk52qB + kVHQIjNEuBta58pmNyhxc+6+bz+ABGp+mR9QemUQjmXghH3VjOwnZVj6KMMX4J3S + XgEubPmw6u4nYqb9bLDVyE2uXXA4TVgFDuZxJrbZOn9zF2aQOOGfZX2Gx5xgK+pV + srM1wyJqdP+QL/fWO9ZI38+tyr1T5zOBPpJ/JTrkSJoVeRWpwuI6BUCZhH66nfU= + =+1cf -----END PGP MESSAGE----- fp: 35C1A64CD7FC0AB6EB66756B2445463C3234ECE1 encrypted_regex: ^(data|stringData)$ diff --git a/go.mod b/go.mod index 03415e45..b9b28354 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( google.golang.org/grpc v1.27.1 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect k8s.io/api v0.20.2 + k8s.io/apiextensions-apiserver v0.20.2 k8s.io/apimachinery v0.20.2 k8s.io/cli-runtime v0.20.2 // indirect k8s.io/client-go v0.20.2