From 158e9a18d35981081686bc9dc2c9122eaf31d421 Mon Sep 17 00:00:00 2001 From: Salah Al Saleh Date: Thu, 18 Jan 2024 22:14:18 +0000 Subject: [PATCH 1/4] Support diff airgap bundles --- cmd/kots/cli/admin-console-push-images.go | 9 +- cmd/kots/cli/install.go | 3 +- pkg/apparchive/helm-v1beta2.go | 31 +- pkg/apparchive/installation.go | 19 -- pkg/base/airgap.go | 95 ++++++ .../airgap_test.go} | 8 +- pkg/base/base.go | 23 -- pkg/base/helm.go | 90 ------ pkg/base/images.go | 81 +++-- pkg/base/write_images.go | 18 +- pkg/base/write_images_test.go | 23 +- pkg/image/builder.go | 289 ++++-------------- pkg/{kotsadm/push_images.go => image/push.go} | 215 +++++-------- pkg/image/types/types.go | 38 ++- pkg/kotsadm/copy_images.go | 6 +- pkg/kotsadm/main.go | 30 +- pkg/kotsadm/types/pushkotsadmoptions.go | 43 --- pkg/kotsutil/kots.go | 10 + pkg/midstream/write.go | 93 +++--- pkg/pull/pull.go | 34 +-- pkg/rewrite/rewrite.go | 32 +- .../charts/test-chart/kustomization.yaml | 16 +- .../overlays/midstream/kustomization.yaml | 16 +- .../pull/cases/replicatedhelm/testcase.yaml | 12 + .../cases/replicatedhelm/upstream/config.yaml | 19 ++ .../upstream/subdir/configmap.yaml | 6 + .../upstream/test-chart-0.1.1.tgz | Bin 0 -> 1893 bytes .../replicatedhelm/upstream/test-chart.yaml | 20 ++ .../upstream/userdata/config.yaml | 10 + .../upstream/userdata/license.yaml | 47 +++ .../base/charts/test-chart/Chart.yaml | 6 + .../charts/test-chart/chartHelmSecret.yaml | 14 + .../base/charts/test-chart/kustomization.yaml | 12 + .../base/charts/test-chart/test-1.yaml | 11 + .../base/charts/test-chart/test-2.yaml | 14 + .../base/charts/test-chart/test-3.yaml | 34 +++ .../base/charts/test-chart/test-4.yaml | 20 ++ .../base/charts/test-chart/test-5.yaml | 20 ++ .../base/charts/test-chart/values.yaml | 34 +++ .../wantResults/base/kustomization.yaml | 13 + .../wantResults/base/subdir/configmap.yaml | 6 + .../wantResults/kotsKinds/config.yaml | 24 ++ .../wantResults/kotsKinds/test-chart.yaml | 20 ++ .../kotsKinds/userdata/config.yaml | 12 + .../kotsKinds/userdata/installation.yaml | 18 ++ .../kotsKinds/userdata/license.yaml | 49 +++ .../this-cluster/kustomization.yaml | 4 + .../midstream/backup-label-transformer.yaml | 39 +++ .../overlays/midstream/kustomization.yaml | 17 ++ .../overlays/midstream/pullsecrets.yaml | 42 +++ .../overlays/midstream/secret.yaml | 28 ++ .../kotsadm-replicated-registry-secret.yaml | 17 ++ .../this-cluster/my-app-registry-secret.yaml | 17 ++ .../this-cluster/post-install-job-job.yaml | 32 ++ .../this-cluster/pre-install-job-job.yaml | 32 ++ .../this-cluster/security-scanner-secret.yaml | 14 + ...ecurity-test-example-chart-deployment.yaml | 44 +++ ...est-example-chart-test-connection-pod.yaml | 21 ++ ....helm.release.v1.test-chart.v1-secret.yaml | 18 ++ .../this-cluster/test-config-configmap.yaml | 11 + .../wantResults/upstream/config.yaml | 19 ++ .../upstream/subdir/configmap.yaml | 6 + .../wantResults/upstream/test-chart-0.1.1.tgz | Bin 0 -> 1893 bytes .../wantResults/upstream/test-chart.yaml | 20 ++ .../wantResults/upstream/userdata/config.yaml | 12 + .../upstream/userdata/installation.yaml | 18 ++ .../upstream/userdata/license.yaml | 49 +++ .../test-chart-release-1/kustomization.yaml | 16 +- .../test-chart-release-2/kustomization.yaml | 16 +- .../test-chart-variation-0/kustomization.yaml | 16 +- .../overlays/midstream/kustomization.yaml | 25 -- .../charts/subchart-1/kustomization.yaml | 16 +- .../charts/subsubchart/kustomization.yaml | 16 +- .../charts/subchart-2/kustomization.yaml | 16 +- .../charts/subchart-3/kustomization.yaml | 16 +- .../midstream/charts/chart/kustomization.yaml | 16 +- .../overlays/midstream/kustomization.yaml | 17 -- .../charts/subchart-1/kustomization.yaml | 16 +- .../charts/subsubchart/kustomization.yaml | 16 +- .../charts/subchart-2/kustomization.yaml | 16 +- .../midstream/charts/chart/kustomization.yaml | 16 +- .../charts/fluent-bit/kustomization.yaml | 4 +- .../charts/fluent-bit/kustomization.yaml | 11 - .../overlays/midstream/kustomization.yaml | 19 -- pkg/upstream/push_images.go | 129 -------- pkg/upstream/upgrade.go | 31 +- 86 files changed, 1458 insertions(+), 1073 deletions(-) delete mode 100644 pkg/apparchive/installation.go create mode 100644 pkg/base/airgap.go rename pkg/{upstream/push_images_test.go => base/airgap_test.go} (84%) rename pkg/{kotsadm/push_images.go => image/push.go} (75%) delete mode 100644 pkg/kotsadm/types/pushkotsadmoptions.go create mode 100644 pkg/tests/pull/cases/replicatedhelm/testcase.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/upstream/config.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/upstream/subdir/configmap.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/upstream/test-chart-0.1.1.tgz create mode 100644 pkg/tests/pull/cases/replicatedhelm/upstream/test-chart.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/upstream/userdata/config.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/upstream/userdata/license.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/Chart.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/chartHelmSecret.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/kustomization.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-1.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-2.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-3.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-4.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-5.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/values.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/kustomization.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/base/subdir/configmap.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/config.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/test-chart.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/config.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/installation.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/license.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/downstreams/this-cluster/kustomization.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/backup-label-transformer.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/kustomization.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/pullsecrets.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/secret.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/kotsadm-replicated-registry-secret.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/my-app-registry-secret.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/post-install-job-job.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/pre-install-job-job.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-scanner-secret.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-deployment.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-test-connection-pod.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/sh.helm.release.v1.test-chart.v1-secret.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/test-config-configmap.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/config.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/subdir/configmap.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart-0.1.1.tgz create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/config.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/installation.yaml create mode 100644 pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/license.yaml delete mode 100644 pkg/upstream/push_images.go diff --git a/cmd/kots/cli/admin-console-push-images.go b/cmd/kots/cli/admin-console-push-images.go index 152eabb1ae..29d8f9a1f8 100644 --- a/cmd/kots/cli/admin-console-push-images.go +++ b/cmd/kots/cli/admin-console-push-images.go @@ -10,8 +10,9 @@ import ( "github.com/replicatedhq/kots/pkg/docker/registry" dockerregistry "github.com/replicatedhq/kots/pkg/docker/registry" registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" + "github.com/replicatedhq/kots/pkg/image" + imagetypes "github.com/replicatedhq/kots/pkg/image/types" "github.com/replicatedhq/kots/pkg/k8sutil" - "github.com/replicatedhq/kots/pkg/kotsadm" kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types" "github.com/replicatedhq/kots/pkg/logger" "github.com/spf13/cobra" @@ -53,7 +54,7 @@ func AdminPushImagesCmd() *cobra.Command { } if _, err := os.Stat(imageSource); err == nil { - err = kotsadm.PushImages(imageSource, *options) + err = image.PushImages(imageSource, *options) if err != nil { return errors.Wrap(err, "failed to push images") } @@ -75,7 +76,7 @@ func AdminPushImagesCmd() *cobra.Command { return cmd } -func genAndCheckPushOptions(endpoint string, namespace string, log *logger.CLILogger, v *viper.Viper) (*kotsadmtypes.PushImagesOptions, error) { +func genAndCheckPushOptions(endpoint string, namespace string, log *logger.CLILogger, v *viper.Viper) (*imagetypes.PushImagesOptions, error) { host, err := getHostFromEndpoint(endpoint) if err != nil { return nil, errors.Wrap(err, "failed get host from endpoint") @@ -114,7 +115,7 @@ func genAndCheckPushOptions(endpoint string, namespace string, log *logger.CLILo log.FinishSpinner() } - options := kotsadmtypes.PushImagesOptions{ + options := imagetypes.PushImagesOptions{ KotsadmTag: v.GetString("kotsadm-tag"), Registry: registrytypes.RegistryOptions{ Endpoint: endpoint, diff --git a/cmd/kots/cli/install.go b/cmd/kots/cli/install.go index bf28b2d0b2..556c5a4571 100644 --- a/cmd/kots/cli/install.go +++ b/cmd/kots/cli/install.go @@ -24,6 +24,7 @@ import ( dockerregistry "github.com/replicatedhq/kots/pkg/docker/registry" "github.com/replicatedhq/kots/pkg/handlers" "github.com/replicatedhq/kots/pkg/identity" + "github.com/replicatedhq/kots/pkg/image" "github.com/replicatedhq/kots/pkg/k8sutil" k8sutiltypes "github.com/replicatedhq/kots/pkg/k8sutil/types" "github.com/replicatedhq/kots/pkg/kotsadm" @@ -332,7 +333,7 @@ func InstallCmd() *cobra.Command { } defer os.RemoveAll(airgapRootDir) - err = kotsadm.ExtractAppAirgapArchive(airgapArchive, airgapRootDir, v.GetBool("disable-image-push"), deployOptions.ProgressWriter) + err = image.ExtractAppAirgapArchive(airgapArchive, airgapRootDir, v.GetBool("disable-image-push"), deployOptions.ProgressWriter) if err != nil { return errors.Wrap(err, "failed to extract images") } diff --git a/pkg/apparchive/helm-v1beta2.go b/pkg/apparchive/helm-v1beta2.go index fb43f1cce9..046231c1b2 100644 --- a/pkg/apparchive/helm-v1beta2.go +++ b/pkg/apparchive/helm-v1beta2.go @@ -3,7 +3,6 @@ package apparchive import ( "bytes" "fmt" - "io/ioutil" "os" "path" "path/filepath" @@ -13,9 +12,11 @@ import ( "github.com/pkg/errors" "github.com/replicatedhq/kots/pkg/base" "github.com/replicatedhq/kots/pkg/docker/registry" + dockerregistrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" "github.com/replicatedhq/kots/pkg/image" "github.com/replicatedhq/kots/pkg/kotsutil" "github.com/replicatedhq/kots/pkg/logger" + "github.com/replicatedhq/kots/pkg/midstream" upstreamtypes "github.com/replicatedhq/kots/pkg/upstream/types" "github.com/replicatedhq/kots/pkg/util" kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" @@ -168,7 +169,7 @@ func WriteV1Beta2HelmCharts(opts WriteV1Beta2HelmChartsOptions) error { if len(checkedImages) > 0 { opts.KotsKinds.Installation.Spec.KnownImages = append(opts.KotsKinds.Installation.Spec.KnownImages, checkedImages...) - if err := SaveInstallation(&opts.KotsKinds.Installation, opts.Upstream.GetUpstreamDir(opts.WriteUpstreamOptions)); err != nil { + if err := kotsutil.SaveInstallation(&opts.KotsKinds.Installation, opts.Upstream.GetUpstreamDir(opts.WriteUpstreamOptions)); err != nil { return errors.Wrap(err, "failed to save installation") } } @@ -278,7 +279,7 @@ func templateV1Beta2HelmChartWithValuesToDir(helmChart *kotsv1beta2.HelmChart, c return nil } -func processV1Beta2HelmChartImages(opts WriteV1Beta2HelmChartsOptions, helmChart *kotsv1beta2.HelmChart, chartDir string) (*image.RewriteImagesResult, error) { +func processV1Beta2HelmChartImages(opts WriteV1Beta2HelmChartsOptions, helmChart *kotsv1beta2.HelmChart, chartDir string) (*base.RewriteImagesResult, error) { // template the chart with the builder values to a temp dir and then process images tmpDir, err := os.MkdirTemp("", fmt.Sprintf("kots-images-%s", helmChart.GetDirName())) if err != nil { @@ -297,7 +298,7 @@ func processV1Beta2HelmChartImages(opts WriteV1Beta2HelmChartsOptions, helmChart } builderValuesPath := path.Join(tmpDir, "builder-values.yaml") - if err := ioutil.WriteFile(builderValuesPath, builderValuesContent, 0644); err != nil { + if err := os.WriteFile(builderValuesPath, builderValuesContent, 0644); err != nil { return nil, errors.Wrap(err, "failed to write builder values file") } @@ -316,7 +317,27 @@ func processV1Beta2HelmChartImages(opts WriteV1Beta2HelmChartsOptions, helmChart dockerHubRegistryCreds, _ = registry.GetCredentialsForRegistryFromConfigJSON(dockerhubSecret.Data[".dockerconfigjson"], registry.DockerHubRegistryName) } - result, err := image.RewriteBaseImages(opts.ProcessImageOptions, templatedOutputDir, opts.KotsKinds, opts.KotsKinds.License, dockerHubRegistryCreds, opts.RenderOptions.Log) + var destRegistry *dockerregistrytypes.RegistryOptions + if opts.ProcessImageOptions.RewriteImages { + destRegistry = &dockerregistrytypes.RegistryOptions{ + Endpoint: opts.ProcessImageOptions.RegistrySettings.Hostname, + Namespace: opts.ProcessImageOptions.RegistrySettings.Namespace, + Username: opts.ProcessImageOptions.RegistrySettings.Username, + Password: opts.ProcessImageOptions.RegistrySettings.Password, + } + } + + baseImages, err := image.FindImagesInDir(templatedOutputDir) + if err != nil { + return nil, errors.Wrap(err, "failed to find base images") + } + + kotsKindsImages, err := kotsutil.GetImagesFromKotsKinds(opts.KotsKinds, destRegistry) + if err != nil { + return nil, errors.Wrap(err, "failed to get images from kots kinds") + } + + result, err := midstream.RewriteBaseImages(opts.ProcessImageOptions, baseImages, kotsKindsImages, opts.KotsKinds, opts.KotsKinds.License, dockerHubRegistryCreds, opts.RenderOptions.Log) if err != nil { return nil, errors.Wrap(err, "failed to rewrite base images") } diff --git a/pkg/apparchive/installation.go b/pkg/apparchive/installation.go deleted file mode 100644 index d7925a5d5a..0000000000 --- a/pkg/apparchive/installation.go +++ /dev/null @@ -1,19 +0,0 @@ -package apparchive - -import ( - "os" - "path" - - "github.com/pkg/errors" - "github.com/replicatedhq/kots/pkg/kotsutil" - kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" -) - -func SaveInstallation(installation *kotsv1beta1.Installation, upstreamDir string) error { - filename := path.Join(upstreamDir, "userdata", "installation.yaml") - err := os.WriteFile(filename, kotsutil.MustMarshalInstallation(installation), 0644) - if err != nil { - return errors.Wrap(err, "failed to write installation") - } - return nil -} diff --git a/pkg/base/airgap.go b/pkg/base/airgap.go new file mode 100644 index 0000000000..df97089849 --- /dev/null +++ b/pkg/base/airgap.go @@ -0,0 +1,95 @@ +package base + +import ( + "io" + + "github.com/pkg/errors" + registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" + "github.com/replicatedhq/kots/pkg/image" + imagetypes "github.com/replicatedhq/kots/pkg/image/types" + "github.com/replicatedhq/kots/pkg/imageutil" + "github.com/replicatedhq/kots/pkg/kotsutil" + "github.com/replicatedhq/kots/pkg/logger" + kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" + kustomizetypes "sigs.k8s.io/kustomize/api/types" +) + +type ProcessAirgapImagesOptions struct { + BaseImages []string + KotsKindsImages []string + RootDir string + AirgapRoot string + AirgapBundle string + CreateAppDir bool + PushImages bool + Log *logger.CLILogger + ReplicatedRegistry registrytypes.RegistryOptions + ReportWriter io.Writer + DestinationRegistry registrytypes.RegistryOptions + KotsKinds *kotsutil.KotsKinds +} + +type ProcessAirgapImagesResult struct { + KustomizeImages []kustomizetypes.Image + KnownImages []kotsv1beta1.InstallationImage +} + +func ProcessAirgapImages(opts ProcessAirgapImagesOptions) (*ProcessAirgapImagesResult, error) { + pushOpts := imagetypes.PushImagesOptions{ + Registry: opts.DestinationRegistry, + Log: opts.Log, + ProgressWriter: opts.ReportWriter, + LogForUI: true, + } + + if opts.PushImages { + if opts.AirgapBundle != "" { + err := image.TagAndPushAppImagesFromBundle(opts.AirgapBundle, pushOpts) + if err != nil { + return nil, errors.Wrap(err, "failed to push images from bundle") + } + } else { + err := image.TagAndPushAppImagesFromPath(opts.AirgapRoot, pushOpts) + if err != nil { + return nil, errors.Wrap(err, "failed to push images from dir") + } + } + } + + rewrittenImages := []kustomizetypes.Image{} + for _, image := range append(opts.BaseImages, opts.KotsKindsImages...) { + rewrittenImage, err := imageutil.RewriteDockerRegistryImage(opts.DestinationRegistry, image) + if err != nil { + return nil, errors.Wrapf(err, "failed to rewrite image %s", image) + } + rewrittenImages = append(rewrittenImages, *rewrittenImage) + } + + withAltNames := make([]kustomizetypes.Image, 0) + for _, i := range rewrittenImages { + altNames, err := imageutil.BuildImageAltNames(i) + if err != nil { + return nil, errors.Wrap(err, "failed to build image alt names") + } + withAltNames = append(withAltNames, altNames...) + } + + result := &ProcessAirgapImagesResult{ + KustomizeImages: withAltNames, + // This list is slightly different from the list we get from app specs because of alternative names, + // but it still works because after rewriting image names with private registry, the lists become the same. + KnownImages: installationImagesFromKustomizeImages(withAltNames), + } + return result, nil +} + +func installationImagesFromKustomizeImages(images []kustomizetypes.Image) []kotsv1beta1.InstallationImage { + result := make([]kotsv1beta1.InstallationImage, 0) + for _, i := range images { + result = append(result, kotsv1beta1.InstallationImage{ + Image: imageutil.SrcImageFromKustomizeImage(i), + IsPrivate: true, + }) + } + return result +} diff --git a/pkg/upstream/push_images_test.go b/pkg/base/airgap_test.go similarity index 84% rename from pkg/upstream/push_images_test.go rename to pkg/base/airgap_test.go index 0a7ab0712a..993a56b7d4 100644 --- a/pkg/upstream/push_images_test.go +++ b/pkg/base/airgap_test.go @@ -1,4 +1,4 @@ -package upstream +package base import ( "reflect" @@ -8,7 +8,7 @@ import ( kustomizetypes "sigs.k8s.io/kustomize/api/types" ) -func Test_makeInstallationImages(t *testing.T) { +func Test_installationImagesFromKustomizeImages(t *testing.T) { tests := []struct { name string images []kustomizetypes.Image @@ -49,8 +49,8 @@ func Test_makeInstallationImages(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := makeInstallationImages(tt.images); !reflect.DeepEqual(got, tt.want) { - t.Errorf("makeInstallationImages() = %v, want %v", got, tt.want) + if got := installationImagesFromKustomizeImages(tt.images); !reflect.DeepEqual(got, tt.want) { + t.Errorf("installationImagesFromKustomizeImages() = %v, want %v", got, tt.want) } }) } diff --git a/pkg/base/base.go b/pkg/base/base.go index a2f3f59b84..734706b0a5 100644 --- a/pkg/base/base.go +++ b/pkg/base/base.go @@ -8,7 +8,6 @@ import ( "strconv" "github.com/pkg/errors" - "github.com/replicatedhq/kots/pkg/k8sdoc" "github.com/replicatedhq/kots/pkg/kotsutil" kotsscheme "github.com/replicatedhq/kotskinds/client/kotsclientset/scheme" troubleshootscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme" @@ -285,28 +284,6 @@ func (b Base) ListErrorFiles() []BaseFile { return files } -func FindObjectsWithImages(b *Base) []k8sdoc.K8sDoc { - var objects []k8sdoc.K8sDoc - for _, file := range b.Files { - parsed, err := k8sdoc.ParseYAML(file.Content) - if err != nil { - continue - } - - images := parsed.ListImages() - if len(images) > 0 { - objects = append(objects, parsed) - } - } - - for _, subBase := range b.Bases { - subObjects := FindObjectsWithImages(&subBase) - objects = append(objects, subObjects...) - } - - return objects -} - func PrependBaseFilesPath(files []BaseFile, prefix string) []BaseFile { if prefix == "" { return files diff --git a/pkg/base/helm.go b/pkg/base/helm.go index e61b2e8ea7..278a3b19d6 100644 --- a/pkg/base/helm.go +++ b/pkg/base/helm.go @@ -537,11 +537,6 @@ func kustomizeHelmNamespace(baseFiles []BaseFile, renderOptions *RenderOptions) return updatedBaseFiles, nil } -type HelmSubCharts struct { - ParentName string - SubCharts []string -} - type HelmChartDependency struct { Alias string `yaml:"alias"` Name string `yaml:"name"` @@ -550,88 +545,3 @@ type HelmChartDependency struct { type HelmChartDependencies struct { Dependencies []HelmChartDependency `yaml:"dependencies"` } - -// Returns a list of HelmSubCharts, each of which contains the name of the parent chart and a list of subcharts -// Each item in the subcharts list is a string of repeating terms the form "charts/". -// The first item is just the top level chart (TODO: this should be removed) -// For example: -// - top-level-chart -// - charts/top-level-chart -// - charts/top-level-chart/charts/cool-sub-chart -func FindHelmSubChartsFromBase(baseDir, parentChartName string) (*HelmSubCharts, error) { - type helmName struct { - Name string `yaml:"name"` - } - - charts := make([]string, 0) - searchDir := filepath.Join(baseDir, "charts", parentChartName) - - // If dependencies in the chart are aliased, they will create new directories with the alias name - // in the charts folder and need to be excluded when generating the pullsecrets.yaml. It feels like this - // could replace the logic below that's doing the file tree walking but I'm unsure. - parentChartPath := filepath.Join(searchDir, "Chart.yaml") - parentChartRaw, err := os.ReadFile(parentChartPath) - if err == nil { - parentChart := new(HelmChartDependencies) - err = yaml.Unmarshal(parentChartRaw, parentChart) - if err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal parent chart %s", parentChartPath) - } - for _, dep := range parentChart.Dependencies { - if dep.Alias != "" { - charts = append(charts, dep.Alias) - } else { - charts = append(charts, dep.Name) - } - } - } - - err = filepath.Walk(searchDir, - func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - // ignore anything that's not a chart yaml - if info.Name() != "Chart.yaml" { - return nil - } - - contents, err := os.ReadFile(path) - if err != nil { - return errors.Wrap(err, "failed to read file") - } - - // unmarshal just the name of the chart - var chartInfo helmName - err = yaml.Unmarshal(contents, &chartInfo) - if err != nil { - return nil - } - - if chartInfo.Name == "" { - // probably not a valid chart file - return nil - } - - // use directory names because they are unique - chartName, err := filepath.Rel(baseDir, filepath.Dir(path)) - if err != nil { - return errors.Wrap(err, "failed to get chart name from path") - } - - charts = append(charts, chartName) - - return nil - }) - if err != nil { - if !strings.Contains(err.Error(), "no such file or directory") { - return nil, errors.Wrap(err, "failed to walk upstream dir") - } - } - - return &HelmSubCharts{ - ParentName: parentChartName, - SubCharts: charts, - }, nil -} diff --git a/pkg/base/images.go b/pkg/base/images.go index 946dfcedc4..d2c4383c31 100644 --- a/pkg/base/images.go +++ b/pkg/base/images.go @@ -1,6 +1,7 @@ package base import ( + "sort" "strings" dockerref "github.com/containers/image/v5/docker/reference" @@ -17,55 +18,94 @@ import ( ) type FindPrivateImagesOptions struct { - BaseDir string + BaseImages []string + KotsKindsImages []string AppSlug string ReplicatedRegistry registrytypes.RegistryOptions DockerHubRegistry registrytypes.RegistryOptions Installation *kotsv1beta1.Installation AllImagesPrivate bool - HelmChartPath string - UseHelmInstall map[string]bool - KotsKindsImages []string } type FindPrivateImagesResult struct { Images []kustomizeimage.Image // images to be rewritten - Docs []k8sdoc.K8sDoc // docs that have rewritten images CheckedImages []kotsv1beta1.InstallationImage // all images found in the installation } -func FindPrivateImages(options FindPrivateImagesOptions) (*FindPrivateImagesResult, error) { - checkedImages := makeImageInfoMap(options.Installation.Spec.KnownImages) - upstreamImages, objects, err := image.GetPrivateImages(options.BaseDir, options.KotsKindsImages, checkedImages, options.AllImagesPrivate, options.DockerHubRegistry, options.HelmChartPath, options.UseHelmInstall) +func FindImages(b *Base) ([]string, []k8sdoc.K8sDoc, error) { + uniqueImages := make(map[string]bool) + objectsWithImages := make([]k8sdoc.K8sDoc, 0) // all objects where images are referenced from + + for _, file := range b.Files { + parsed, err := k8sdoc.ParseYAML(file.Content) + if err != nil { + continue + } + + images := parsed.ListImages() + if len(images) > 0 { + objectsWithImages = append(objectsWithImages, parsed) + } + + for _, image := range images { + uniqueImages[image] = true + } + } + + for _, subBase := range b.Bases { + subImages, subObjects, err := FindImages(&subBase) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to find images in sub base %s", subBase.Path) + } + + objectsWithImages = append(objectsWithImages, subObjects...) + + for _, subImage := range subImages { + uniqueImages[subImage] = true + } + } + + result := make([]string, 0, len(uniqueImages)) + for i := range uniqueImages { + result = append(result, i) + } + sort.Strings(result) // sort the images to get an ordered and reproducible output for easier testing + + return result, objectsWithImages, nil +} + +func FindPrivateImages(opts FindPrivateImagesOptions) (*FindPrivateImagesResult, error) { + checkedImages := makeInstallationImageInfoMap(opts.Installation.Spec.KnownImages) + privateImages, err := image.GetPrivateImages(opts.BaseImages, opts.KotsKindsImages, checkedImages, opts.AllImagesPrivate, opts.DockerHubRegistry) if err != nil { return nil, errors.Wrap(err, "failed to list upstream images") } kustomizeImages := make([]kustomizeimage.Image, 0) - for _, upstreamImage := range upstreamImages { - dockerRef, err := dockerref.ParseDockerRef(upstreamImage) + for _, privateImage := range privateImages { + dockerRef, err := dockerref.ParseDockerRef(privateImage) if err != nil { - return nil, errors.Wrapf(err, "failed to parse docker ref %q", upstreamImage) + return nil, errors.Wrapf(err, "failed to parse docker ref %q", privateImage) } registryHost := dockerref.Domain(dockerRef) - if registryHost == options.ReplicatedRegistry.Endpoint { + if registryHost == opts.ReplicatedRegistry.Endpoint { // replicated images are also private, but we don't rewrite those continue } image := kustomizeimage.Image{} - if registryHost == options.ReplicatedRegistry.UpstreamEndpoint { + if registryHost == opts.ReplicatedRegistry.UpstreamEndpoint { // image is using the upstream replicated registry, but a custom registry domain is configured, so rewrite to use the custom domain image = kustomizeimage.Image{ Name: dockerRef.Name(), - NewName: strings.Replace(dockerRef.Name(), registryHost, options.ReplicatedRegistry.Endpoint, 1), + NewName: strings.Replace(dockerRef.Name(), registryHost, opts.ReplicatedRegistry.Endpoint, 1), } } else { // all other private images are rewritten to use the replicated proxy image = kustomizeimage.Image{ Name: dockerRef.Name(), - NewName: registry.MakeProxiedImageURL(options.ReplicatedRegistry.ProxyEndpoint, options.AppSlug, upstreamImage), + NewName: registry.MakeProxiedImageURL(opts.ReplicatedRegistry.ProxyEndpoint, opts.AppSlug, privateImage), } } @@ -86,22 +126,21 @@ func FindPrivateImages(options FindPrivateImagesOptions) (*FindPrivateImagesResu return &FindPrivateImagesResult{ Images: kustomizeImages, - Docs: objects, - CheckedImages: makeInstallationImages(checkedImages), + CheckedImages: installationImagesFromInfoMap(checkedImages), }, nil } -func makeImageInfoMap(images []kotsv1beta1.InstallationImage) map[string]imagetypes.ImageInfo { - result := make(map[string]imagetypes.ImageInfo) +func makeInstallationImageInfoMap(images []kotsv1beta1.InstallationImage) map[string]imagetypes.InstallationImageInfo { + result := make(map[string]imagetypes.InstallationImageInfo) for _, i := range images { - result[i.Image] = imagetypes.ImageInfo{ + result[i.Image] = imagetypes.InstallationImageInfo{ IsPrivate: i.IsPrivate, } } return result } -func makeInstallationImages(images map[string]imagetypes.ImageInfo) []kotsv1beta1.InstallationImage { +func installationImagesFromInfoMap(images map[string]imagetypes.InstallationImageInfo) []kotsv1beta1.InstallationImage { result := make([]kotsv1beta1.InstallationImage, 0) for image, info := range images { result = append(result, kotsv1beta1.InstallationImage{ diff --git a/pkg/base/write_images.go b/pkg/base/write_images.go index 3fd24053ff..0e11d4fa48 100644 --- a/pkg/base/write_images.go +++ b/pkg/base/write_images.go @@ -14,7 +14,8 @@ import ( ) type RewriteImageOptions struct { - BaseDir string + BaseImages []string + KotsKindsImages []string AppSlug string SourceRegistry registrytypes.RegistryOptions DestRegistry registrytypes.RegistryOptions @@ -33,29 +34,22 @@ type RewriteImagesResult struct { func RewriteImages(options RewriteImageOptions) (*RewriteImagesResult, error) { allImagesPrivate := options.IsAirgap - additionalImages := make([]string, 0) - checkedImages := make(map[string]imagetypes.ImageInfo) + checkedImages := make(map[string]imagetypes.InstallationImageInfo) if options.KotsKinds != nil { - kki, err := kotsutil.GetImagesFromKotsKinds(options.KotsKinds, &options.DestRegistry) - if err != nil { - return nil, errors.Wrap(err, "failed to get images from kots kinds") - } - additionalImages = kki - - checkedImages = makeImageInfoMap(options.KotsKinds.Installation.Spec.KnownImages) + checkedImages = makeInstallationImageInfoMap(options.KotsKinds.Installation.Spec.KnownImages) if options.KotsKinds.KotsApplication.Spec.ProxyPublicImages { allImagesPrivate = true } } - newImages, err := image.RewriteImages(options.SourceRegistry, options.DestRegistry, options.AppSlug, options.Log, options.ReportWriter, options.BaseDir, additionalImages, options.CopyImages, allImagesPrivate, checkedImages, options.DockerHubRegistry) + newImages, err := image.RewriteImages(options.SourceRegistry, options.DestRegistry, options.AppSlug, options.Log, options.ReportWriter, options.BaseImages, options.KotsKindsImages, options.CopyImages, allImagesPrivate, checkedImages, options.DockerHubRegistry) if err != nil { return nil, errors.Wrap(err, "failed to save images") } return &RewriteImagesResult{ Images: newImages, - CheckedImages: makeInstallationImages(checkedImages), + CheckedImages: installationImagesFromInfoMap(checkedImages), }, nil } diff --git a/pkg/base/write_images_test.go b/pkg/base/write_images_test.go index 4b1759ac62..ea5ec0982f 100644 --- a/pkg/base/write_images_test.go +++ b/pkg/base/write_images_test.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" + "github.com/replicatedhq/kots/pkg/image" "github.com/replicatedhq/kots/pkg/k8sdoc" "github.com/replicatedhq/kots/pkg/kotsutil" kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" @@ -33,7 +34,6 @@ func Test_RewriteImages(t *testing.T) { baseDir: "./testdata/base-specs", appSlug: "test-app-slug", processOptions: RewriteImageOptions{ - BaseDir: "./testdata/base-specs", SourceRegistry: registrytypes.RegistryOptions{ Endpoint: "registry.replicated.com", ProxyEndpoint: "proxy.replicated.com", @@ -226,7 +226,6 @@ func Test_RewriteImages(t *testing.T) { }, findOptions: FindPrivateImagesOptions{ - BaseDir: "./testdata/base-specs", AppSlug: "test-app-slug", ReplicatedRegistry: registrytypes.RegistryOptions{ Endpoint: "registry.replicated.com", @@ -299,7 +298,6 @@ func Test_RewriteImages(t *testing.T) { baseDir: "./testdata/replicated-registry", appSlug: "test-app-slug", processOptions: RewriteImageOptions{ - BaseDir: "./testdata/replicated-registry", SourceRegistry: registrytypes.RegistryOptions{ Endpoint: "my-registry.example.com", ProxyEndpoint: "my-proxy.example.com", @@ -358,7 +356,6 @@ func Test_RewriteImages(t *testing.T) { }, findOptions: FindPrivateImagesOptions{ - BaseDir: "./testdata/replicated-registry", AppSlug: "test-app-slug", ReplicatedRegistry: registrytypes.RegistryOptions{ Endpoint: "my-registry.example.com", @@ -404,7 +401,6 @@ func Test_RewriteImages(t *testing.T) { baseDir: "./testdata/replicated-registry", appSlug: "test-app-slug", processOptions: RewriteImageOptions{ - BaseDir: "./testdata/replicated-registry", SourceRegistry: registrytypes.RegistryOptions{ Endpoint: "registry.replicated.com", ProxyEndpoint: "proxy.replicated.com", @@ -463,7 +459,6 @@ func Test_RewriteImages(t *testing.T) { }, findOptions: FindPrivateImagesOptions{ - BaseDir: "./testdata/replicated-registry", AppSlug: "test-app-slug", ReplicatedRegistry: registrytypes.RegistryOptions{ Endpoint: "registry.replicated.com", @@ -509,23 +504,29 @@ func Test_RewriteImages(t *testing.T) { t.Run(test.name, func(t *testing.T) { req := require.New(t) + kotsKindsImages, err := kotsutil.GetImagesFromKotsKinds(test.processOptions.KotsKinds, &test.processOptions.DestRegistry) + req.NoError(err) + test.processOptions.KotsKindsImages = kotsKindsImages + + baseImages, err := image.FindImagesInDir(test.baseDir) + req.NoError(err) + test.processOptions.BaseImages = baseImages + gotResult, err := RewriteImages(test.processOptions) req.NoError(err) assert.ElementsMatch(t, test.wantProcessResult.Images, gotResult.Images) assert.ElementsMatch(t, test.wantProcessResult.CheckedImages, gotResult.CheckedImages) - test.findOptions.KotsKindsImages, err = kotsutil.GetImagesFromKotsKinds(test.processOptions.KotsKinds, nil) + kotsKindsImages, err = kotsutil.GetImagesFromKotsKinds(test.processOptions.KotsKinds, nil) // no dest registry req.NoError(err) + test.findOptions.KotsKindsImages = kotsKindsImages + test.findOptions.BaseImages = baseImages gotFindResult, err := FindPrivateImages(test.findOptions) req.NoError(err) - wantDocs, err := loadDocs(test.baseDir) - req.NoError(err) - assert.ElementsMatch(t, test.wantFindResult.Images, gotFindResult.Images) - assert.ElementsMatch(t, wantDocs, gotFindResult.Docs) assert.ElementsMatch(t, test.wantFindResult.CheckedImages, gotFindResult.CheckedImages) }) } diff --git a/pkg/image/builder.go b/pkg/image/builder.go index 43fb105061..a3f4716a86 100644 --- a/pkg/image/builder.go +++ b/pkg/image/builder.go @@ -28,11 +28,9 @@ import ( "github.com/replicatedhq/kots/pkg/image/types" "github.com/replicatedhq/kots/pkg/imageutil" "github.com/replicatedhq/kots/pkg/k8sdoc" - "github.com/replicatedhq/kots/pkg/kotsutil" "github.com/replicatedhq/kots/pkg/logger" regsitrytypes "github.com/replicatedhq/kots/pkg/registry/types" "github.com/replicatedhq/kots/pkg/util" - kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" "golang.org/x/sync/errgroup" kustomizeimage "sigs.k8s.io/kustomize/api/types" ) @@ -41,53 +39,38 @@ var imagePolicy = []byte(`{ "default": [{"type": "insecureAcceptAnything"}] }`) -func RewriteImages(srcRegistry, destRegistry dockerregistrytypes.RegistryOptions, appSlug string, log *logger.CLILogger, reportWriter io.Writer, baseDir string, additionalImages []string, copyImages, allImagesPrivate bool, checkedImages map[string]types.ImageInfo, dockerHubRegistry dockerregistrytypes.RegistryOptions) ([]kustomizeimage.Image, error) { - newImages := []kustomizeimage.Image{} +func RewriteImages(srcRegistry, destRegistry dockerregistrytypes.RegistryOptions, appSlug string, log *logger.CLILogger, reportWriter io.Writer, baseImages []string, kotsKindsImages []string, copyImages, allImagesPrivate bool, checkedImages map[string]types.InstallationImageInfo, dockerHubRegistry dockerregistrytypes.RegistryOptions) ([]kustomizeimage.Image, error) { + rewrittenImages := []kustomizeimage.Image{} savedImages := map[string]bool{} - err := filepath.Walk(baseDir, - func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if info.IsDir() { - return nil - } - - contents, err := os.ReadFile(path) - if err != nil { - return err - } - - newImagesSubset, err := rewriteImagesInFileBetweenRegistries(srcRegistry, destRegistry, appSlug, log, reportWriter, contents, copyImages, allImagesPrivate, checkedImages, savedImages, dockerHubRegistry) - if err != nil { - return errors.Wrapf(err, "failed to copy images mentioned in %s", path) - } - - newImages = append(newImages, newImagesSubset...) - return nil - }) - - if err != nil { - return nil, errors.Wrap(err, "failed to walk upstream dir") + for _, baseImage := range baseImages { + if _, saved := savedImages[baseImage]; saved { + continue + } + rewrittenImage, err := rewriteOneImage(srcRegistry, destRegistry, baseImage, appSlug, reportWriter, log, copyImages, allImagesPrivate, checkedImages, dockerHubRegistry) + if err != nil { + return nil, errors.Wrapf(err, "failed to process base image %s", baseImage) + } + rewrittenImages = append(rewrittenImages, rewrittenImage...) + savedImages[baseImage] = true } - for _, additionalImage := range additionalImages { - newImage, err := rewriteOneImage(srcRegistry, destRegistry, additionalImage, appSlug, reportWriter, log, copyImages, allImagesPrivate, checkedImages, dockerHubRegistry) + for _, kotsKindImage := range kotsKindsImages { + if _, saved := savedImages[kotsKindImage]; saved { + continue + } + rewrittenImage, err := rewriteOneImage(srcRegistry, destRegistry, kotsKindImage, appSlug, reportWriter, log, copyImages, allImagesPrivate, checkedImages, dockerHubRegistry) if err != nil { - return nil, errors.Wrapf(err, "failed to process addditional image %s", additionalImage) + return nil, errors.Wrapf(err, "failed to process kots kind image %s", kotsKindImage) } - newImages = append(newImages, newImage...) + rewrittenImages = append(rewrittenImages, rewrittenImage...) + savedImages[kotsKindImage] = true } - return newImages, nil + return rewrittenImages, nil } -func GetPrivateImages(baseDir string, kotsKindsImages []string, checkedImages map[string]types.ImageInfo, allPrivate bool, dockerHubRegistry dockerregistrytypes.RegistryOptions, parentHelmChartPath string, useHelmInstall map[string]bool) ([]string, []k8sdoc.K8sDoc, error) { - uniqueImages := make(map[string]bool) - objectsWithImages := make([]k8sdoc.K8sDoc, 0) // all objects where images are referenced from - +func GetPrivateImages(baseImages []string, kotsKindsImages []string, checkedImages map[string]types.InstallationImageInfo, allPrivate bool, dockerHubRegistry dockerregistrytypes.RegistryOptions) ([]string, error) { var mtx sync.Mutex const concurrencyLimit = 10 g, _ := errgroup.WithContext(context.Background()) @@ -120,70 +103,69 @@ func GetPrivateImages(baseDir string, kotsKindsImages []string, checkedImages ma return errors.Wrapf(err, "failed to check if kotskinds image %s is private", image) } mtx.Lock() - checkedImages[image] = types.ImageInfo{IsPrivate: isPrivate} + checkedImages[image] = types.InstallationImageInfo{IsPrivate: isPrivate} + mtx.Unlock() + return nil + }) + }(image) + } + + privateImages := []string{} + for _, image := range baseImages { + func(image string) { + g.Go(func() error { + isPrivate, err := isPrivateImage(image) + if err != nil { + return errors.Wrapf(err, "failed to check if image %s is private", image) + } + mtx.Lock() + checkedImages[image] = types.InstallationImageInfo{IsPrivate: isPrivate} + if isPrivate { + privateImages = append(privateImages, image) + } mtx.Unlock() return nil }) }(image) } - err := filepath.Walk(baseDir, + if err := g.Wait(); err != nil { + return nil, errors.Wrap(err, "failed to wait for image checks") + } + + // sort the images to get an ordered and reproducible output for easier testing + sort.Strings(privateImages) + + return privateImages, nil +} + +func FindImagesInDir(dir string) ([]string, error) { + uniqueImages := make(map[string]bool) + + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { - chartName, err := filepath.Rel(baseDir, path) - if err != nil { - logger.Debugf("Failed to remove prefix from %s: %v", path, err) - return nil - } - chartName = filepath.Join(parentHelmChartPath, chartName) - if useHelmInstall[chartName] { - return filepath.SkipDir - } return nil } contents, err := os.ReadFile(path) if err != nil { - logger.Debugf("Failed to read file %s: %v", path, err) - return err + return errors.Wrapf(err, "failed to read file %s", path) } return listImagesInFile(contents, func(images []string, doc k8sdoc.K8sDoc) error { for _, image := range images { - func(image string) { - g.Go(func() error { - isPrivate, err := isPrivateImage(image) - if err != nil { - return errors.Wrapf(err, "failed to check if image %s is private", image) - } - mtx.Lock() - checkedImages[image] = types.ImageInfo{IsPrivate: isPrivate} - if isPrivate { - uniqueImages[image] = true - } - mtx.Unlock() - return nil - }) - }(image) - } - - if len(images) > 0 { - objectsWithImages = append(objectsWithImages, doc) + uniqueImages[image] = true } return nil }) }) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to walk upstream dir") - } - - if err := g.Wait(); err != nil { - return nil, nil, errors.Wrap(err, "failed to wait for image checks") + return nil, errors.Wrap(err, "failed to walk dir") } result := make([]string, 0, len(uniqueImages)) @@ -192,42 +174,7 @@ func GetPrivateImages(baseDir string, kotsKindsImages []string, checkedImages ma } sort.Strings(result) // sort the images to get an ordered and reproducible output for easier testing - return result, objectsWithImages, nil -} - -func rewriteImagesInFileBetweenRegistries(srcRegistry, destRegistry dockerregistrytypes.RegistryOptions, appSlug string, log *logger.CLILogger, reportWriter io.Writer, fileData []byte, copyImages, allImagesPrivate bool, checkedImages map[string]types.ImageInfo, savedImages map[string]bool, dockerHubRegistry dockerregistrytypes.RegistryOptions) ([]kustomizeimage.Image, error) { - newImages := []kustomizeimage.Image{} - - err := listImagesInFile(fileData, func(images []string, doc k8sdoc.K8sDoc) error { - for _, image := range images { - if _, saved := savedImages[image]; saved { - continue - } - - if copyImages { - log.ChildActionWithSpinner("Transferring image %s", image) - } else { - log.ChildActionWithSpinner("Found image %s", image) - } - - newImage, err := rewriteOneImage(srcRegistry, destRegistry, image, appSlug, reportWriter, log, copyImages, allImagesPrivate, checkedImages, dockerHubRegistry) - if err != nil { - log.FinishChildSpinner() - return errors.Wrapf(err, "failed to transfer image %s", image) - } - - if newImage != nil { - newImages = append(newImages, newImage...) - } - - log.FinishChildSpinner() - savedImages[image] = true - } - - return nil - }) - - return newImages, err + return result, nil } type processImagesFunc func([]string, k8sdoc.K8sDoc) error @@ -250,7 +197,7 @@ func listImagesInFile(contents []byte, handler processImagesFunc) error { return nil } -func rewriteOneImage(srcRegistry, destRegistry dockerregistrytypes.RegistryOptions, image string, appSlug string, reportWriter io.Writer, log *logger.CLILogger, copyImages, allImagesPrivate bool, checkedImages map[string]types.ImageInfo, dockerHubRegistry dockerregistrytypes.RegistryOptions) ([]kustomizeimage.Image, error) { +func rewriteOneImage(srcRegistry, destRegistry dockerregistrytypes.RegistryOptions, image string, appSlug string, reportWriter io.Writer, log *logger.CLILogger, copyImages, allImagesPrivate bool, checkedImages map[string]types.InstallationImageInfo, dockerHubRegistry dockerregistrytypes.RegistryOptions) ([]kustomizeimage.Image, error) { sourceCtx := &containerstypes.SystemContext{DockerDisableV1Ping: true} // allow pulling images from http/invalid https docker repos @@ -270,7 +217,7 @@ func rewriteOneImage(srcRegistry, destRegistry dockerregistrytypes.RegistryOptio } isPrivate = p } - checkedImages[image] = types.ImageInfo{ + checkedImages[image] = types.InstallationImageInfo{ IsPrivate: isPrivate, } } @@ -292,7 +239,7 @@ func rewriteOneImage(srcRegistry, destRegistry dockerregistrytypes.RegistryOptio // normalize image to make sure only either a digest or a tag exist but not both parsedSrc, err := reference.ParseDockerRef(sourceImage) if err != nil { - return nil, errors.Wrap(err, "failed to normalize source image") + return nil, errors.Wrapf(err, "failed to normalize source image %s", sourceImage) } sourceImage = parsedSrc.String() @@ -512,7 +459,7 @@ func IsPrivateImage(image string, dockerHubRegistry dockerregistrytypes.Registry continue } - logger.Debugf("Marking image '%s' as private because: %v", image, err.Error()) + logger.Infof("Marking image '%s' as private because: %v", image, err.Error()) // if the registry is unreachable (which might be due to a firewall, proxy, etc..), // we won't be able to determine if the error is due to a missing auth or not. @@ -593,111 +540,3 @@ type ProcessImageOptions struct { CreateAppDir bool ReportWriter io.Writer } - -// RewriteBaseImages Will rewrite images found in base and copy them (if necessary) to the configured registry. -func RewriteBaseImages(options ProcessImageOptions, baseDir string, kotsKinds *kotsutil.KotsKinds, license *kotsv1beta1.License, dockerHubRegistryCreds registry.Credentials, log *logger.CLILogger) (*RewriteImagesResult, error) { - replicatedRegistryInfo := registry.GetRegistryProxyInfo(license, &kotsKinds.Installation, &kotsKinds.KotsApplication) - - rewriteImageOptions := RewriteImagesBetweenRegistriesOptions{ - BaseDir: baseDir, - Log: log, - SourceRegistry: dockerregistrytypes.RegistryOptions{ - Endpoint: replicatedRegistryInfo.Registry, - ProxyEndpoint: replicatedRegistryInfo.Proxy, - }, - DockerHubRegistry: dockerregistrytypes.RegistryOptions{ - Username: dockerHubRegistryCreds.Username, - Password: dockerHubRegistryCreds.Password, - }, - DestRegistry: dockerregistrytypes.RegistryOptions{ - Endpoint: options.RegistrySettings.Hostname, - Namespace: options.RegistrySettings.Namespace, - Username: options.RegistrySettings.Username, - Password: options.RegistrySettings.Password, - }, - ReportWriter: options.ReportWriter, - KotsKinds: kotsKinds, - IsAirgap: options.IsAirgap, - CopyImages: options.CopyImages, - } - if license != nil { - rewriteImageOptions.AppSlug = license.Spec.AppSlug - rewriteImageOptions.SourceRegistry.Username = license.Spec.LicenseID - rewriteImageOptions.SourceRegistry.Password = license.Spec.LicenseID - } - - rewriteResult, err := RewriteImagesBetweenRegistries(rewriteImageOptions) - if err != nil { - return nil, errors.Wrap(err, "failed to rewrite images") - } - - return rewriteResult, nil -} - -type RewriteImagesBetweenRegistriesOptions struct { - BaseDir string - AppSlug string - SourceRegistry dockerregistrytypes.RegistryOptions - DestRegistry dockerregistrytypes.RegistryOptions - DockerHubRegistry dockerregistrytypes.RegistryOptions - CopyImages bool - IsAirgap bool - Log *logger.CLILogger - ReportWriter io.Writer - KotsKinds *kotsutil.KotsKinds -} - -type RewriteImagesResult struct { - Images []kustomizeimage.Image // images to be rewritten - CheckedImages []kotsv1beta1.InstallationImage // all images found in the installation -} - -func RewriteImagesBetweenRegistries(options RewriteImagesBetweenRegistriesOptions) (*RewriteImagesResult, error) { - allImagesPrivate := options.IsAirgap - additionalImages := make([]string, 0) - checkedImages := make(map[string]types.ImageInfo) - - if options.KotsKinds != nil { - kki, err := kotsutil.GetImagesFromKotsKinds(options.KotsKinds, &options.DestRegistry) - if err != nil { - return nil, errors.Wrap(err, "failed to get images from kots kinds") - } - additionalImages = kki - - checkedImages = makeImageInfoMap(options.KotsKinds.Installation.Spec.KnownImages) - if options.KotsKinds.KotsApplication.Spec.ProxyPublicImages { - allImagesPrivate = true - } - } - - newImages, err := RewriteImages(options.SourceRegistry, options.DestRegistry, options.AppSlug, options.Log, options.ReportWriter, options.BaseDir, additionalImages, options.CopyImages, allImagesPrivate, checkedImages, options.DockerHubRegistry) - if err != nil { - return nil, errors.Wrap(err, "failed to save images") - } - - return &RewriteImagesResult{ - Images: newImages, - CheckedImages: makeInstallationImages(checkedImages), - }, nil -} - -func makeImageInfoMap(images []kotsv1beta1.InstallationImage) map[string]types.ImageInfo { - result := make(map[string]types.ImageInfo) - for _, i := range images { - result[i.Image] = types.ImageInfo{ - IsPrivate: i.IsPrivate, - } - } - return result -} - -func makeInstallationImages(images map[string]types.ImageInfo) []kotsv1beta1.InstallationImage { - result := make([]kotsv1beta1.InstallationImage, 0) - for image, info := range images { - result = append(result, kotsv1beta1.InstallationImage{ - Image: image, - IsPrivate: info.IsPrivate, - }) - } - return result -} diff --git a/pkg/kotsadm/push_images.go b/pkg/image/push.go similarity index 75% rename from pkg/kotsadm/push_images.go rename to pkg/image/push.go index 2893168bf4..4d4b26d716 100644 --- a/pkg/kotsadm/push_images.go +++ b/pkg/image/push.go @@ -1,4 +1,4 @@ -package kotsadm +package image import ( "archive/tar" @@ -23,17 +23,14 @@ import ( dockerarchive "github.com/replicatedhq/kots/pkg/docker/archive" dockerregistry "github.com/replicatedhq/kots/pkg/docker/registry" dockertypes "github.com/replicatedhq/kots/pkg/docker/types" - "github.com/replicatedhq/kots/pkg/image" imagetypes "github.com/replicatedhq/kots/pkg/image/types" "github.com/replicatedhq/kots/pkg/imageutil" - "github.com/replicatedhq/kots/pkg/kotsadm/types" "github.com/replicatedhq/kots/pkg/kotsutil" "k8s.io/client-go/kubernetes/scheme" - kustomizetypes "sigs.k8s.io/kustomize/api/types" ) // Pushes Admin Console images from airgap bundle to private registry -func PushImages(airgapArchive string, options types.PushImagesOptions) error { +func PushImages(airgapArchive string, options imagetypes.PushImagesOptions) error { airgapRootDir, err := ioutil.TempDir("", "kotsadm-airgap") if err != nil { return errors.Wrap(err, "failed to create temp dir") @@ -46,12 +43,12 @@ func PushImages(airgapArchive string, options types.PushImagesOptions) error { } if isAppArchive(airgapRootDir) { - _, err := TagAndPushAppImagesFromPath(airgapRootDir, options) + err := TagAndPushAppImagesFromPath(airgapRootDir, options) if err != nil { return errors.Wrap(err, "failed to push app images") } } else { - err = pushKotsadmImagesFromPath(airgapRootDir, options) + err := pushKotsadmImagesFromPath(airgapRootDir, options) if err != nil { return errors.Wrap(err, "failed to push kotsadm images") } @@ -102,7 +99,7 @@ func ExtractAppAirgapArchive(archive string, destDir string, excludeImages bool, } err = func() error { - writeProgressLine(progressWriter, fmt.Sprintf("Extracting %s", dstFileName)) + WriteProgressLine(progressWriter, fmt.Sprintf("Extracting %s", dstFileName)) dstFile, err := os.Create(dstFileName) if err != nil { @@ -124,7 +121,7 @@ func ExtractAppAirgapArchive(archive string, destDir string, excludeImages bool, return nil } -func pushKotsadmImagesFromPath(rootDir string, options types.PushImagesOptions) error { +func pushKotsadmImagesFromPath(rootDir string, options imagetypes.PushImagesOptions) error { fileInfos, err := ioutil.ReadDir(rootDir) if err != nil { return errors.Wrap(err, "failed to read dir") @@ -144,7 +141,7 @@ func pushKotsadmImagesFromPath(rootDir string, options types.PushImagesOptions) return nil } -func processImageNames(rootDir string, format string, options types.PushImagesOptions) error { +func processImageNames(rootDir string, format string, options imagetypes.PushImagesOptions) error { fileInfos, err := ioutil.ReadDir(filepath.Join(rootDir, format)) if err != nil { return errors.Wrap(err, "failed to read dir") @@ -164,7 +161,7 @@ func processImageNames(rootDir string, format string, options types.PushImagesOp return nil } -func processImageTags(rootDir string, format string, imageName string, options types.PushImagesOptions) error { +func processImageTags(rootDir string, format string, imageName string, options imagetypes.PushImagesOptions) error { fileInfos, err := ioutil.ReadDir(filepath.Join(rootDir, format, imageName)) if err != nil { return errors.Wrap(err, "failed to read dir") @@ -184,7 +181,7 @@ func processImageTags(rootDir string, format string, imageName string, options t return nil } -func pushOneImage(rootDir string, format string, imageName string, tag string, options types.PushImagesOptions) error { +func pushOneImage(rootDir string, format string, imageName string, tag string, options imagetypes.PushImagesOptions) error { destCtx := &containerstypes.SystemContext{ DockerInsecureSkipTLSVerify: containerstypes.OptionalBoolTrue, DockerDisableV1Ping: true, @@ -218,9 +215,9 @@ func pushOneImage(rootDir string, format string, imageName string, tag string, o return errors.Wrapf(err, "failed to parse local image name: %s:%s", format, imageFile) } - writeProgressLine(options.ProgressWriter, fmt.Sprintf("Pushing %s", destStr)) + WriteProgressLine(options.ProgressWriter, fmt.Sprintf("Pushing %s", destStr)) - _, err = image.CopyImageWithGC(context.Background(), destRef, localRef, ©.Options{ + _, err = CopyImageWithGC(context.Background(), destRef, localRef, ©.Options{ RemoveSignatures: true, SignBy: "", ReportWriter: options.ProgressWriter, @@ -235,14 +232,14 @@ func pushOneImage(rootDir string, format string, imageName string, tag string, o return nil } -func writeProgressLine(progressWriter io.Writer, line string) { +func WriteProgressLine(progressWriter io.Writer, line string) { fmt.Fprint(progressWriter, fmt.Sprintf("%s\n", line)) } -func TagAndPushAppImagesFromPath(airgapRootDir string, options types.PushImagesOptions) ([]kustomizetypes.Image, error) { +func TagAndPushAppImagesFromPath(airgapRootDir string, options imagetypes.PushImagesOptions) error { airgap, err := kotsutil.FindAirgapMetaInDir(airgapRootDir) if err != nil { - return nil, errors.Wrap(err, "failed to find airgap meta") + return errors.Wrap(err, "failed to find airgap meta") } switch airgap.Spec.Format { @@ -251,21 +248,21 @@ func TagAndPushAppImagesFromPath(airgapRootDir string, options types.PushImagesO case dockertypes.FormatDockerArchive, "": return PushAppImagesFromDockerArchivePath(airgapRootDir, options) default: - return nil, errors.Errorf("Airgap bundle format '%s' is not supported", airgap.Spec.Format) + return errors.Errorf("Airgap bundle format '%s' is not supported", airgap.Spec.Format) } } -func TagAndPushAppImagesFromBundle(airgapBundle string, options types.PushImagesOptions) ([]kustomizetypes.Image, error) { +func TagAndPushAppImagesFromBundle(airgapBundle string, options imagetypes.PushImagesOptions) error { airgap, err := kotsutil.FindAirgapMetaInBundle(airgapBundle) if err != nil { - return nil, errors.Wrap(err, "failed to find airgap meta") + return errors.Wrap(err, "failed to find airgap meta") } switch airgap.Spec.Format { case dockertypes.FormatDockerRegistry: extractedBundle, err := ioutil.TempDir("", "extracted-airgap-kots") if err != nil { - return nil, errors.Wrap(err, "failed to create temp dir for unarchived airgap bundle") + return errors.Wrap(err, "failed to create temp dir for unarchived airgap bundle") } defer os.RemoveAll(extractedBundle) @@ -275,39 +272,37 @@ func TagAndPushAppImagesFromBundle(airgapBundle string, options types.PushImages }, } if err := tarGz.Unarchive(airgapBundle, extractedBundle); err != nil { - return nil, errors.Wrap(err, "falied to unarchive airgap bundle") + return errors.Wrap(err, "falied to unarchive airgap bundle") } return PushAppImagesFromTempRegistry(extractedBundle, airgap.Spec.SavedImages, options) case dockertypes.FormatDockerArchive, "": return PushAppImagesFromDockerArchiveBundle(airgapBundle, options) default: - return nil, errors.Errorf("Airgap bundle format '%s' is not supported", airgap.Spec.Format) + return errors.Errorf("Airgap bundle format '%s' is not supported", airgap.Spec.Format) } } -func PushAppImagesFromTempRegistry(airgapRootDir string, imageList []string, options types.PushImagesOptions) ([]kustomizetypes.Image, error) { +func PushAppImagesFromTempRegistry(airgapRootDir string, imageList []string, options imagetypes.PushImagesOptions) error { tempRegistry := &dockerregistry.TempRegistry{} if err := tempRegistry.Start(filepath.Join(airgapRootDir, "images")); err != nil { - return nil, errors.Wrap(err, "failed to start temp registry") + return errors.Wrap(err, "failed to start temp registry") } defer tempRegistry.Stop() - rewrittenImages := []kustomizetypes.Image{} - imageInfos := make(map[string]*types.ImageInfo) - + imageInfos := make(map[string]*imagetypes.ImageInfo) for _, image := range imageList { - layerInfo := make(map[string]*types.LayerInfo) + layerInfo := make(map[string]*imagetypes.LayerInfo) if options.LogForUI { layers, err := tempRegistry.GetImageLayers(image) if err != nil { - return nil, errors.Wrapf(err, "failed to get image layers for %s", image) + return errors.Wrapf(err, "failed to get image layers for %s", image) } layerInfo, err = layerInfoFromLayers(layers) if err != nil { - return nil, errors.Wrap(err, "failed to get layer info") + return errors.Wrap(err, "failed to get layer info") } } - imageInfos[image] = &types.ImageInfo{ + imageInfos[image] = &imagetypes.ImageInfo{ Format: dockertypes.FormatDockerRegistry, Layers: layerInfo, Status: "queued", @@ -325,26 +320,25 @@ func PushAppImagesFromTempRegistry(airgapRootDir string, imageList []string, opt for imageID, imageInfo := range imageInfos { srcRef, err := tempRegistry.SrcRef(imageID) if err != nil { - return nil, errors.Wrapf(err, "failed to parse source image %s", imageID) + return errors.Wrapf(err, "failed to parse source image %s", imageID) } destImage, err := imageutil.DestImage(options.Registry, imageID) if err != nil { - return nil, errors.Wrapf(err, "failed to get destination image for %s", imageID) + return errors.Wrapf(err, "failed to get destination image for %s", imageID) } destStr := fmt.Sprintf("docker://%s", destImage) destRef, err := alltransports.ParseImageName(destStr) if err != nil { - return nil, errors.Wrapf(err, "failed to parse dest image %s", destStr) + return errors.Wrapf(err, "failed to parse dest image %s", destStr) } rewrittenImage, err := imageutil.RewriteDockerRegistryImage(options.Registry, imageID) if err != nil { - return nil, errors.Wrapf(err, "failed to rewrite image %s", imageID) + return errors.Wrapf(err, "failed to rewrite image %s", imageID) } - rewrittenImages = append(rewrittenImages, *rewrittenImage) - pushAppImageOpts := types.PushAppImageOptions{ + pushAppImageOpts := imagetypes.PushAppImageOptions{ ImageID: imageID, ImageInfo: imageInfo, Log: options.Log, @@ -364,16 +358,15 @@ func PushAppImagesFromTempRegistry(airgapRootDir string, imageList []string, opt }, } if err := pushAppImage(pushAppImageOpts); err != nil { - return nil, errors.Wrapf(err, "failed to push app image %s", imageID) + return errors.Wrapf(err, "failed to push app image %s", imageID) } } - return rewrittenImages, nil + return nil } -func PushAppImagesFromDockerArchivePath(airgapRootDir string, options types.PushImagesOptions) ([]kustomizetypes.Image, error) { - rewrittenImages := []kustomizetypes.Image{} - imageInfos := make(map[string]*types.ImageInfo) +func PushAppImagesFromDockerArchivePath(airgapRootDir string, options imagetypes.PushImagesOptions) error { + imageInfos := make(map[string]*imagetypes.ImageInfo) imagesDir := filepath.Join(airgapRootDir, "images") walkErr := filepath.Walk(imagesDir, @@ -386,7 +379,7 @@ func PushAppImagesFromDockerArchivePath(airgapRootDir string, options types.Push return nil } - layerInfo := make(map[string]*types.LayerInfo) + layerInfo := make(map[string]*imagetypes.LayerInfo) if options.LogForUI { layers, err := dockerarchive.GetImageLayers(path) if err != nil { @@ -398,7 +391,7 @@ func PushAppImagesFromDockerArchivePath(airgapRootDir string, options types.Push } } - imageInfos[path] = &types.ImageInfo{ + imageInfos[path] = &imagetypes.ImageInfo{ Format: dockertypes.FormatDockerArchive, Layers: layerInfo, Status: "queued", @@ -406,7 +399,7 @@ func PushAppImagesFromDockerArchivePath(airgapRootDir string, options types.Push return nil }) if walkErr != nil { - return nil, errors.Wrap(walkErr, "failed to walk images dir") + return errors.Wrap(walkErr, "failed to walk images dir") } reportWriter := options.ProgressWriter @@ -422,22 +415,21 @@ func PushAppImagesFromDockerArchivePath(airgapRootDir string, options types.Push pathWithoutRoot := imagePath[len(formatRoot)+1:] rewrittenImage, err := imageutil.RewriteDockerArchiveImage(options.Registry, strings.Split(pathWithoutRoot, string(os.PathSeparator))) if err != nil { - return nil, errors.Wrap(err, "failed to rewrite docker archive image") + return errors.Wrap(err, "failed to rewrite docker archive image") } - rewrittenImages = append(rewrittenImages, rewrittenImage) srcRef, err := alltransports.ParseImageName(fmt.Sprintf("%s:%s", dockertypes.FormatDockerArchive, imagePath)) if err != nil { - return nil, errors.Wrap(err, "failed to parse src image name") + return errors.Wrap(err, "failed to parse src image name") } destStr := fmt.Sprintf("docker://%s", imageutil.DestImageFromKustomizeImage(rewrittenImage)) destRef, err := alltransports.ParseImageName(destStr) if err != nil { - return nil, errors.Wrapf(err, "failed to parse dest image name %s", destStr) + return errors.Wrapf(err, "failed to parse dest image name %s", destStr) } - pushAppImageOpts := types.PushAppImageOptions{ + pushAppImageOpts := imagetypes.PushAppImageOptions{ ImageID: imagePath, ImageInfo: imageInfo, Log: options.Log, @@ -456,32 +448,32 @@ func PushAppImagesFromDockerArchivePath(airgapRootDir string, options types.Push }, } if err := pushAppImage(pushAppImageOpts); err != nil { - return nil, errors.Wrapf(err, "failed to push app image %s", imagePath) + return errors.Wrapf(err, "failed to push app image %s", imagePath) } } - return rewrittenImages, nil + return nil } -func PushAppImagesFromDockerArchiveBundle(airgapBundle string, options types.PushImagesOptions) ([]kustomizetypes.Image, error) { +func PushAppImagesFromDockerArchiveBundle(airgapBundle string, options imagetypes.PushImagesOptions) error { if options.LogForUI { - writeProgressLine(options.ProgressWriter, "Reading image information from bundle...") + WriteProgressLine(options.ProgressWriter, "Reading image information from bundle...") } imageInfos, err := getImageInfosFromBundle(airgapBundle, options.LogForUI) if err != nil { - return nil, errors.Wrap(err, "failed to get images info from bundle") + return errors.Wrap(err, "failed to get images info from bundle") } fileReader, err := os.Open(airgapBundle) if err != nil { - return nil, errors.Wrap(err, "failed to open file") + return errors.Wrap(err, "failed to open file") } defer fileReader.Close() gzipReader, err := gzip.NewReader(fileReader) if err != nil { - return nil, errors.Wrap(err, "failed to get new gzip reader") + return errors.Wrap(err, "failed to get new gzip reader") } defer gzipReader.Close() @@ -493,8 +485,6 @@ func PushAppImagesFromDockerArchiveBundle(airgapBundle string, options types.Pus defer wc.Close() } - rewrittenImages := []kustomizetypes.Image{} - tarReader := tar.NewReader(gzipReader) for { header, err := tarReader.Next() @@ -502,7 +492,7 @@ func PushAppImagesFromDockerArchiveBundle(airgapBundle string, options types.Pus break } if err != nil { - return nil, errors.Wrap(err, "failed to get read archive") + return errors.Wrap(err, "failed to get read archive") } if header.Typeflag != tar.TypeReg { @@ -516,49 +506,48 @@ func PushAppImagesFromDockerArchiveBundle(airgapBundle string, options types.Pus } if options.LogForUI { - writeProgressLine(reportWriter, fmt.Sprintf("Extracting image %s", imagePath)) + WriteProgressLine(reportWriter, fmt.Sprintf("Extracting image %s", imagePath)) } tmpFile, err := ioutil.TempFile("", "kotsadm-app-image-") if err != nil { - return nil, errors.Wrap(err, "failed to create temp file") + return errors.Wrap(err, "failed to create temp file") } defer tmpFile.Close() defer os.Remove(tmpFile.Name()) _, err = io.Copy(tmpFile, tarReader) if err != nil { - return nil, errors.Wrapf(err, "failed to write file %q", imagePath) + return errors.Wrapf(err, "failed to write file %q", imagePath) } // Close file to flush all data before pushing to registry if err := tmpFile.Close(); err != nil { - return nil, errors.Wrap(err, "failed to close tmp file") + return errors.Wrap(err, "failed to close tmp file") } pathParts := strings.Split(imagePath, string(os.PathSeparator)) if len(pathParts) < 3 { - return nil, errors.Errorf("not enough path parts in %q", imagePath) + return errors.Errorf("not enough path parts in %q", imagePath) } rewrittenImage, err := imageutil.RewriteDockerArchiveImage(options.Registry, pathParts[2:]) if err != nil { - return nil, errors.Wrap(err, "failed to rewrite docker archive image") + return errors.Wrap(err, "failed to rewrite docker archive image") } - rewrittenImages = append(rewrittenImages, rewrittenImage) srcRef, err := alltransports.ParseImageName(fmt.Sprintf("%s:%s", dockertypes.FormatDockerArchive, tmpFile.Name())) if err != nil { - return nil, errors.Wrap(err, "failed to parse src image name") + return errors.Wrap(err, "failed to parse src image name") } destStr := fmt.Sprintf("docker://%s", imageutil.DestImageFromKustomizeImage(rewrittenImage)) destRef, err := alltransports.ParseImageName(destStr) if err != nil { - return nil, errors.Wrapf(err, "failed to parse dest image name %s", destStr) + return errors.Wrapf(err, "failed to parse dest image name %s", destStr) } - pushAppImageOpts := types.PushAppImageOptions{ + pushAppImageOpts := imagetypes.PushAppImageOptions{ ImageID: imagePath, ImageInfo: imageInfo, Log: options.Log, @@ -577,28 +566,28 @@ func PushAppImagesFromDockerArchiveBundle(airgapBundle string, options types.Pus }, } if err := pushAppImage(pushAppImageOpts); err != nil { - return nil, errors.Wrapf(err, "failed to push app image %s", imagePath) + return errors.Wrapf(err, "failed to push app image %s", imagePath) } } - return rewrittenImages, nil + return nil } -func pushAppImage(opts types.PushAppImageOptions) error { +func pushAppImage(opts imagetypes.PushAppImageOptions) error { opts.ImageInfo.UploadStart = time.Now() if opts.LogForUI { fmt.Printf("Pushing image %s\n", opts.ImageID) // still log in console for future reference opts.ReportWriter.Write([]byte(fmt.Sprintf("+file.begin:%s\n", opts.ImageID))) } else { destImageStr := opts.CopyImageOptions.DestRef.DockerReference().String() // this is better for debugging from the cli than the image id - writeProgressLine(opts.ReportWriter, fmt.Sprintf("Pushing image %s", destImageStr)) + WriteProgressLine(opts.ReportWriter, fmt.Sprintf("Pushing image %s", destImageStr)) } var retryAttempts int = 5 var copyError error for i := 0; i < retryAttempts; i++ { - copyError = image.CopyImage(opts.CopyImageOptions) + copyError = CopyImage(opts.CopyImageOptions) if copyError == nil { break // image copy succeeded, exit the retry loop } else { @@ -623,51 +612,7 @@ func pushAppImage(opts types.PushAppImageOptions) error { return nil } -func GetImagesFromBundle(airgapBundle string, options types.PushImagesOptions) ([]kustomizetypes.Image, error) { - if options.LogForUI { - writeProgressLine(options.ProgressWriter, "Reading image information from bundle...") - } - - airgap, err := kotsutil.FindAirgapMetaInBundle(airgapBundle) - if err != nil { - return nil, errors.Wrap(err, "failed to find airgap meta") - } - - rewrittenImages := []kustomizetypes.Image{} - - switch airgap.Spec.Format { - case dockertypes.FormatDockerRegistry: - for _, savedImage := range airgap.Spec.SavedImages { - rewrittenImage, err := imageutil.RewriteDockerRegistryImage(options.Registry, savedImage) - if err != nil { - return nil, errors.Wrapf(err, "failed to rewrite image %s", savedImage) - } - rewrittenImages = append(rewrittenImages, *rewrittenImage) - } - case dockertypes.FormatDockerArchive, "": - imageInfos, err := getImageInfosFromBundle(airgapBundle, false) - if err != nil { - return nil, errors.Wrap(err, "failed to get images info from bundle") - } - for imagePath, _ := range imageInfos { - pathParts := strings.Split(imagePath, string(os.PathSeparator)) - if len(pathParts) < 3 { - return nil, errors.Errorf("not enough path parts in %q", imagePath) - } - rewrittenImage, err := imageutil.RewriteDockerArchiveImage(options.Registry, pathParts[2:]) - if err != nil { - return nil, errors.Wrap(err, "failed to rewrite docker archive image") - } - rewrittenImages = append(rewrittenImages, rewrittenImage) - } - default: - return nil, errors.Errorf("Airgap bundle format '%s' is not supported", airgap.Spec.Format) - } - - return rewrittenImages, nil -} - -func getImageInfosFromBundle(airgapBundle string, getLayerInfo bool) (map[string]*types.ImageInfo, error) { +func getImageInfosFromBundle(airgapBundle string, getLayerInfo bool) (map[string]*imagetypes.ImageInfo, error) { fileReader, err := os.Open(airgapBundle) if err != nil { return nil, errors.Wrap(err, "failed to open file") @@ -680,7 +625,7 @@ func getImageInfosFromBundle(airgapBundle string, getLayerInfo bool) (map[string } defer gzipReader.Close() - imageInfos := make(map[string]*types.ImageInfo) + imageInfos := make(map[string]*imagetypes.ImageInfo) tarReader := tar.NewReader(gzipReader) foundImagesFolder := false @@ -710,7 +655,7 @@ func getImageInfosFromBundle(airgapBundle string, getLayerInfo bool) (map[string continue } - layerInfo := make(map[string]*types.LayerInfo) + layerInfo := make(map[string]*imagetypes.LayerInfo) if getLayerInfo { layers, err := dockerarchive.GetImageLayersFromReader(tarReader) if err != nil { @@ -727,7 +672,7 @@ func getImageInfosFromBundle(airgapBundle string, getLayerInfo bool) (map[string return nil, errors.Errorf("not enough parts in image path: %q", header.Name) } - imageInfos[header.Name] = &types.ImageInfo{ + imageInfos[header.Name] = &imagetypes.ImageInfo{ Format: dockertypes.FormatDockerArchive, Layers: layerInfo, Status: "queued", @@ -736,11 +681,11 @@ func getImageInfosFromBundle(airgapBundle string, getLayerInfo bool) (map[string return imageInfos, nil } -func layerInfoFromLayers(layers []dockertypes.Layer) (map[string]*types.LayerInfo, error) { - layerInfo := make(map[string]*types.LayerInfo) +func layerInfoFromLayers(layers []dockertypes.Layer) (map[string]*imagetypes.LayerInfo, error) { + layerInfo := make(map[string]*imagetypes.LayerInfo) for _, layer := range layers { layerID := strings.TrimPrefix(layer.Digest, "sha256:") - layerInfo[layerID] = &types.LayerInfo{ + layerInfo[layerID] = &imagetypes.LayerInfo{ ID: layerID, Size: layer.Size, } @@ -748,7 +693,7 @@ func layerInfoFromLayers(layers []dockertypes.Layer) (map[string]*types.LayerInf return layerInfo, nil } -func reportWriterWithProgress(imageInfos map[string]*types.ImageInfo, reportWriter io.Writer) io.WriteCloser { +func reportWriterWithProgress(imageInfos map[string]*imagetypes.ImageInfo, reportWriter io.Writer) io.WriteCloser { pipeReader, pipeWriter := io.Pipe() go func() { currentLayerID := "" @@ -834,7 +779,7 @@ type ProgressImage struct { EndTime time.Time `json:"endTime"` } -func progressLayerEnded(imageID, layerID string, imageInfos map[string]*types.ImageInfo) { +func progressLayerEnded(imageID, layerID string, imageInfos map[string]*imagetypes.ImageInfo) { imageInfo := imageInfos[imageID] if imageInfo == nil { return @@ -850,7 +795,7 @@ func progressLayerEnded(imageID, layerID string, imageInfos map[string]*types.Im layer.UploadEnd = time.Now() } -func progressLayerStarted(imageID, layerID string, imageInfos map[string]*types.ImageInfo) { +func progressLayerStarted(imageID, layerID string, imageInfos map[string]*imagetypes.ImageInfo) { imageInfo := imageInfos[imageID] if imageInfo == nil { return @@ -866,7 +811,7 @@ func progressLayerStarted(imageID, layerID string, imageInfos map[string]*types. layer.UploadStart = time.Now() } -func progressFileStarted(imageID string, imageInfos map[string]*types.ImageInfo) { +func progressFileStarted(imageID string, imageInfos map[string]*imagetypes.ImageInfo) { imageInfo := imageInfos[imageID] if imageInfo == nil { return @@ -876,7 +821,7 @@ func progressFileStarted(imageID string, imageInfos map[string]*types.ImageInfo) imageInfo.UploadStart = time.Now() } -func progressFileEnded(imageID string, imageInfos map[string]*types.ImageInfo) { +func progressFileEnded(imageID string, imageInfos map[string]*imagetypes.ImageInfo) { imageInfo := imageInfos[imageID] if imageInfo == nil { return @@ -886,7 +831,7 @@ func progressFileEnded(imageID string, imageInfos map[string]*types.ImageInfo) { imageInfo.UploadEnd = time.Now() } -func progressFileFailed(imageID string, imageInfos map[string]*types.ImageInfo, errorStr string) { +func progressFileFailed(imageID string, imageInfos map[string]*imagetypes.ImageInfo, errorStr string) { imageInfo := imageInfos[imageID] if imageInfo == nil { return @@ -897,7 +842,7 @@ func progressFileFailed(imageID string, imageInfos map[string]*types.ImageInfo, imageInfo.UploadEnd = time.Now() } -func writeCurrentProgress(line string, imageInfos map[string]*types.ImageInfo, reportWriter io.Writer) { +func writeCurrentProgress(line string, imageInfos map[string]*imagetypes.ImageInfo, reportWriter io.Writer) { report := ProgressReport{ Type: "progressReport", CompatibilityMessage: line, @@ -933,7 +878,7 @@ func pathToDisplayName(path string) string { return image + ":" + tag // TODO: support for SHAs } -func countLayersUploaded(image *types.ImageInfo) int64 { +func countLayersUploaded(image *imagetypes.ImageInfo) int64 { count := int64(0) for _, layer := range image.Layers { if !layer.UploadEnd.IsZero() { diff --git a/pkg/image/types/types.go b/pkg/image/types/types.go index e0a28015f6..94064da553 100644 --- a/pkg/image/types/types.go +++ b/pkg/image/types/types.go @@ -2,8 +2,11 @@ package types import ( "io" + "time" "github.com/containers/image/v5/types" + registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" + "github.com/replicatedhq/kots/pkg/logger" ) type RegistryAuth struct { @@ -11,7 +14,7 @@ type RegistryAuth struct { Password string } -type ImageInfo struct { +type InstallationImageInfo struct { IsPrivate bool } @@ -24,3 +27,36 @@ type CopyImageOptions struct { SkipDestTLSVerify bool ReportWriter io.Writer } + +type PushImagesOptions struct { + Registry registrytypes.RegistryOptions + KotsadmTag string + Log *logger.CLILogger + ProgressWriter io.Writer + LogForUI bool +} + +type PushAppImageOptions struct { + ImageID string + ImageInfo *ImageInfo + Log *logger.CLILogger + LogForUI bool + ReportWriter io.Writer + CopyImageOptions CopyImageOptions +} + +type ImageInfo struct { + Format string + Status string + Error string + Layers map[string]*LayerInfo + UploadStart time.Time + UploadEnd time.Time +} + +type LayerInfo struct { + ID string + Size int64 + UploadStart time.Time + UploadEnd time.Time +} diff --git a/pkg/kotsadm/copy_images.go b/pkg/kotsadm/copy_images.go index 7f9cfc8d2e..815a7d0c76 100644 --- a/pkg/kotsadm/copy_images.go +++ b/pkg/kotsadm/copy_images.go @@ -12,15 +12,15 @@ import ( "github.com/pkg/errors" "github.com/replicatedhq/kots/pkg/docker/registry" "github.com/replicatedhq/kots/pkg/image" + imagetypes "github.com/replicatedhq/kots/pkg/image/types" "github.com/replicatedhq/kots/pkg/k8sutil" kotsadmobjects "github.com/replicatedhq/kots/pkg/kotsadm/objects" - "github.com/replicatedhq/kots/pkg/kotsadm/types" kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types" "k8s.io/client-go/kubernetes" ) // Copies Admin Console images from public registry to private registry -func CopyImages(options types.PushImagesOptions, kotsNamespace string) error { +func CopyImages(options imagetypes.PushImagesOptions, kotsNamespace string) error { clientset, err := k8sutil.GetClientset() if err != nil { return errors.Wrap(err, "failed to get clientset") @@ -45,7 +45,7 @@ func CopyImages(options types.PushImagesOptions, kotsNamespace string) error { return errors.Errorf("failed to find image %s in destination list", imageName) } - writeProgressLine(options.ProgressWriter, fmt.Sprintf("Copying %s to %s", sourceImage, destImage)) + image.WriteProgressLine(options.ProgressWriter, fmt.Sprintf("Copying %s to %s", sourceImage, destImage)) sourceCtx, err := getCopyImagesSourceContext(clientset, kotsNamespace) if err != nil { diff --git a/pkg/kotsadm/main.go b/pkg/kotsadm/main.go index bdd7d53557..ae7f7fc776 100644 --- a/pkg/kotsadm/main.go +++ b/pkg/kotsadm/main.go @@ -2,8 +2,6 @@ package kotsadm import ( "context" - "encoding/json" - "io/ioutil" "os" "path" "path/filepath" @@ -15,6 +13,8 @@ import ( "github.com/replicatedhq/kots/pkg/docker/registry" registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" "github.com/replicatedhq/kots/pkg/identity" + "github.com/replicatedhq/kots/pkg/image" + imagetypes "github.com/replicatedhq/kots/pkg/image/types" "github.com/replicatedhq/kots/pkg/ingress" "github.com/replicatedhq/kots/pkg/k8sutil" "github.com/replicatedhq/kots/pkg/kotsadm/types" @@ -30,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" - kustomizetypes "sigs.k8s.io/kustomize/api/types" ) func init() { @@ -153,11 +152,9 @@ func Upgrade(clientset *kubernetes.Clientset, upgradeOptions types.UpgradeOption func Deploy(deployOptions types.DeployOptions, log *logger.CLILogger) error { airgapPath := "" - var images []kustomizetypes.Image if deployOptions.AirgapRootDir != "" && deployOptions.RegistryConfig.OverrideRegistry != "" { - var err error - pushOptions := types.PushImagesOptions{ + pushOptions := imagetypes.PushImagesOptions{ Registry: registrytypes.RegistryOptions{ Endpoint: deployOptions.RegistryConfig.OverrideRegistry, Namespace: deployOptions.RegistryConfig.OverrideNamespace, @@ -167,13 +164,8 @@ func Deploy(deployOptions types.DeployOptions, log *logger.CLILogger) error { ProgressWriter: deployOptions.ProgressWriter, } - if deployOptions.DisableImagePush { - images, err = GetImagesFromBundle(deployOptions.AirgapBundle, pushOptions) - if err != nil { - return errors.Wrap(err, "failed to get images from bundle") - } - } else { - images, err = TagAndPushAppImagesFromPath(deployOptions.AirgapRootDir, pushOptions) + if !deployOptions.DisableImagePush { + err := image.TagAndPushAppImagesFromPath(deployOptions.AirgapRootDir, pushOptions) if err != nil { return errors.Wrap(err, "failed to tag and push app images from path") } @@ -227,21 +219,9 @@ func Deploy(deployOptions types.DeployOptions, log *logger.CLILogger) error { if airgapPath != "" { deployOptions.AppImagesPushed = true - b, err := json.Marshal(images) - if err != nil { - return errors.Wrap(err, "failed to marshal images data") - } - err = ioutil.WriteFile(filepath.Join(airgapPath, "images.json"), b, 0644) - if err != nil { - return errors.Wrap(err, "failed to write images data") - } - if err := ensureConfigFromFile(deployOptions, clientset, "kotsadm-airgap-meta", filepath.Join(airgapPath, "airgap.yaml")); err != nil { return errors.Wrap(err, "failed to create config from airgap.yaml") } - if err := ensureConfigFromFile(deployOptions, clientset, "kotsadm-airgap-images", filepath.Join(airgapPath, "images.json")); err != nil { - return errors.Wrap(err, "failed to create config from images.json") - } if err := ensureWaitForAirgapConfig(deployOptions, clientset, "kotsadm-airgap-app"); err != nil { return errors.Wrap(err, "failed to create config from app.tar.gz") } diff --git a/pkg/kotsadm/types/pushkotsadmoptions.go b/pkg/kotsadm/types/pushkotsadmoptions.go deleted file mode 100644 index ccda67ebda..0000000000 --- a/pkg/kotsadm/types/pushkotsadmoptions.go +++ /dev/null @@ -1,43 +0,0 @@ -package types - -import ( - "io" - "time" - - registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" - imagetypes "github.com/replicatedhq/kots/pkg/image/types" - "github.com/replicatedhq/kots/pkg/logger" -) - -type PushImagesOptions struct { - Registry registrytypes.RegistryOptions - KotsadmTag string - Log *logger.CLILogger - ProgressWriter io.Writer - LogForUI bool -} - -type PushAppImageOptions struct { - ImageID string - ImageInfo *ImageInfo - Log *logger.CLILogger - LogForUI bool - ReportWriter io.Writer - CopyImageOptions imagetypes.CopyImageOptions -} - -type ImageInfo struct { - Format string - Status string - Error string - Layers map[string]*LayerInfo - UploadStart time.Time - UploadEnd time.Time -} - -type LayerInfo struct { - ID string - Size int64 - UploadStart time.Time - UploadEnd time.Time -} diff --git a/pkg/kotsutil/kots.go b/pkg/kotsutil/kots.go index f4a5afbaa2..7e132f7c91 100644 --- a/pkg/kotsutil/kots.go +++ b/pkg/kotsutil/kots.go @@ -1496,3 +1496,13 @@ func MustMarshalInstallation(installation *kotsv1beta1.Installation) []byte { return b.Bytes() } + +// this is here to avoid a circular dependency +func SaveInstallation(installation *kotsv1beta1.Installation, upstreamDir string) error { + filename := path.Join(upstreamDir, "userdata", "installation.yaml") + err := os.WriteFile(filename, MustMarshalInstallation(installation), 0644) + if err != nil { + return errors.Wrap(err, "failed to write installation") + } + return nil +} diff --git a/pkg/midstream/write.go b/pkg/midstream/write.go index 9a58634b0a..2839d7ce50 100644 --- a/pkg/midstream/write.go +++ b/pkg/midstream/write.go @@ -2,7 +2,6 @@ package midstream import ( "context" - "encoding/json" "fmt" "io" "io/ioutil" @@ -10,7 +9,6 @@ import ( "path/filepath" "github.com/pkg/errors" - "github.com/replicatedhq/kots/pkg/apparchive" "github.com/replicatedhq/kots/pkg/base" "github.com/replicatedhq/kots/pkg/disasterrecovery" "github.com/replicatedhq/kots/pkg/docker/registry" @@ -21,7 +19,6 @@ import ( "github.com/replicatedhq/kots/pkg/kotsutil" "github.com/replicatedhq/kots/pkg/logger" "github.com/replicatedhq/kots/pkg/template" - "github.com/replicatedhq/kots/pkg/upstream" "github.com/replicatedhq/kots/pkg/util" kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" yaml "gopkg.in/yaml.v2" @@ -47,7 +44,6 @@ type WriteOptions struct { HTTPProxyEnvValue string HTTPSProxyEnvValue string NoProxyEnvValue string - UseHelmInstall map[string]bool NewHelmCharts []*kotsv1beta1.HelmChart ProcessImageOptions image.ProcessImageOptions License *kotsv1beta1.License @@ -76,6 +72,26 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { dockerHubRegistryCreds, _ = registry.GetCredentialsForRegistryFromConfigJSON(dockerhubSecret.Data[".dockerconfigjson"], registry.DockerHubRegistryName) } + var destRegistry *dockerregistrytypes.RegistryOptions + if opts.ProcessImageOptions.RewriteImages { + destRegistry = &dockerregistrytypes.RegistryOptions{ + Endpoint: opts.ProcessImageOptions.RegistrySettings.Hostname, + Namespace: opts.ProcessImageOptions.RegistrySettings.Namespace, + Username: opts.ProcessImageOptions.RegistrySettings.Username, + Password: opts.ProcessImageOptions.RegistrySettings.Password, + } + } + + baseImages, objects, err := base.FindImages(opts.Base) + if err != nil { + return nil, errors.Wrap(err, "failed to find base images") + } + + kotsKindsImages, err := kotsutil.GetImagesFromKotsKinds(opts.RenderedKotsKinds, destRegistry) + if err != nil { + return nil, errors.Wrap(err, "failed to get images from kots kinds") + } + if opts.ProcessImageOptions.RewriteImages { // A target registry is configured. Rewrite all images and copy them (if necessary) to the configured registry. if opts.ProcessImageOptions.RegistrySettings.IsReadOnly { @@ -88,7 +104,7 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { if opts.ProcessImageOptions.AirgapRoot == "" { // This is an online installation. Pull and rewrite images from online and copy them (if necessary) to the configured registry. - rewriteResult, err := RewriteBaseImages(opts.ProcessImageOptions, opts.BaseDir, opts.RenderedKotsKinds, opts.License, dockerHubRegistryCreds, opts.Log) + rewriteResult, err := RewriteBaseImages(opts.ProcessImageOptions, baseImages, kotsKindsImages, opts.RenderedKotsKinds, opts.License, dockerHubRegistryCreds, opts.Log) if err != nil { return nil, errors.Wrap(err, "failed to rewrite base images") } @@ -96,7 +112,7 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { opts.RenderedKotsKinds.Installation.Spec.KnownImages = rewriteResult.CheckedImages } else { // This is an airgapped installation. Copy and rewrite images from the airgap bundle to the configured registry. - result, err := ProcessAirgapImages(opts.ProcessImageOptions, opts.RenderedKotsKinds, opts.License, opts.Log) + result, err := ProcessAirgapImages(opts.ProcessImageOptions, baseImages, kotsKindsImages, opts.RenderedKotsKinds, opts.License, opts.Log) if err != nil { return nil, errors.Wrap(err, "failed to process airgap images") } @@ -104,8 +120,6 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { opts.RenderedKotsKinds.Installation.Spec.KnownImages = result.KnownImages } - objects = base.FindObjectsWithImages(opts.Base) - // Use target registry credentials to create image pull secrets for all objects that have images. pullSecretRegistries = []string{opts.ProcessImageOptions.RegistrySettings.Hostname} pullSecretUsername = opts.ProcessImageOptions.RegistrySettings.Username @@ -118,13 +132,12 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { } } else if opts.License != nil { // A target registry is NOT configured. Find and rewrite private images to be proxied through proxy.replicated.com - findResult, err := findPrivateImages(opts, dockerHubRegistryCreds) + findResult, err := findPrivateImages(opts, baseImages, kotsKindsImages, dockerHubRegistryCreds) if err != nil { return nil, errors.Wrap(err, "failed to find private images") } images = findResult.Images opts.RenderedKotsKinds.Installation.Spec.KnownImages = findResult.CheckedImages - objects = findResult.Docs // Use license to create image pull secrets for all objects that have private images. pullSecretRegistries = registry.GetRegistryProxyInfo(opts.License, &opts.RenderedKotsKinds.Installation, &opts.RenderedKotsKinds.KotsApplication).ToSlice() @@ -153,7 +166,7 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { } pullSecrets.DockerHubSecret = dockerhubSecret - if err := apparchive.SaveInstallation(&opts.RenderedKotsKinds.Installation, opts.UpstreamDir); err != nil { + if err := kotsutil.SaveInstallation(&opts.RenderedKotsKinds.Installation, opts.UpstreamDir); err != nil { return nil, errors.Wrap(err, "failed to save installation") } @@ -170,12 +183,13 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { } // RewriteBaseImages Will rewrite images found in base and copy them (if necessary) to the configured registry. -func RewriteBaseImages(options image.ProcessImageOptions, baseDir string, kotsKinds *kotsutil.KotsKinds, license *kotsv1beta1.License, dockerHubRegistryCreds registry.Credentials, log *logger.CLILogger) (*base.RewriteImagesResult, error) { +func RewriteBaseImages(options image.ProcessImageOptions, baseImages []string, kotsKindsImages []string, kotsKinds *kotsutil.KotsKinds, license *kotsv1beta1.License, dockerHubRegistryCreds registry.Credentials, log *logger.CLILogger) (*base.RewriteImagesResult, error) { replicatedRegistryInfo := registry.GetRegistryProxyInfo(license, &kotsKinds.Installation, &kotsKinds.KotsApplication) rewriteImageOptions := base.RewriteImageOptions{ - BaseDir: baseDir, - Log: log, + BaseImages: baseImages, + KotsKindsImages: kotsKindsImages, + Log: log, SourceRegistry: dockerregistrytypes.RegistryOptions{ Endpoint: replicatedRegistryInfo.Registry, ProxyEndpoint: replicatedRegistryInfo.Proxy, @@ -211,16 +225,18 @@ func RewriteBaseImages(options image.ProcessImageOptions, baseDir string, kotsKi } // processAirgapImages Will rewrite images found in the airgap bundle/airgap root and copy them (if necessary) to the configured registry. -func ProcessAirgapImages(options image.ProcessImageOptions, kotsKinds *kotsutil.KotsKinds, license *kotsv1beta1.License, log *logger.CLILogger) (*upstream.ProcessAirgapImagesResult, error) { +func ProcessAirgapImages(options image.ProcessImageOptions, baseImages []string, kotsKindsImages []string, kotsKinds *kotsutil.KotsKinds, license *kotsv1beta1.License, log *logger.CLILogger) (*base.ProcessAirgapImagesResult, error) { replicatedRegistryInfo := registry.GetRegistryProxyInfo(license, &kotsKinds.Installation, &kotsKinds.KotsApplication) - processAirgapImageOptions := upstream.ProcessAirgapImagesOptions{ - RootDir: options.RootDir, - AirgapRoot: options.AirgapRoot, - AirgapBundle: options.AirgapBundle, - CreateAppDir: options.CreateAppDir, - PushImages: !options.RegistrySettings.IsReadOnly && options.PushImages, - Log: log, + processAirgapImageOptions := base.ProcessAirgapImagesOptions{ + BaseImages: baseImages, + KotsKindsImages: kotsKindsImages, + RootDir: options.RootDir, + AirgapRoot: options.AirgapRoot, + AirgapBundle: options.AirgapBundle, + CreateAppDir: options.CreateAppDir, + PushImages: !options.RegistrySettings.IsReadOnly && options.PushImages, + Log: log, ReplicatedRegistry: dockerregistrytypes.RegistryOptions{ Endpoint: replicatedRegistryInfo.Registry, ProxyEndpoint: replicatedRegistryInfo.Proxy, @@ -233,27 +249,15 @@ func ProcessAirgapImages(options image.ProcessImageOptions, kotsKinds *kotsutil. Username: options.RegistrySettings.Username, Password: options.RegistrySettings.Password, }, + KotsKinds: kotsKinds, } if license != nil { processAirgapImageOptions.ReplicatedRegistry.Username = license.Spec.LicenseID processAirgapImageOptions.ReplicatedRegistry.Password = license.Spec.LicenseID } - imagesData, err := os.ReadFile(filepath.Join(options.AirgapRoot, "images.json")) - if err != nil && !os.IsNotExist(err) { - return nil, errors.Wrap(err, "failed to load images file") - } - if err == nil { - var images []kustomizetypes.Image - err := json.Unmarshal(imagesData, &images) - if err != nil && !os.IsNotExist(err) { - return nil, errors.Wrap(err, "failed to unmarshal images data") - } - processAirgapImageOptions.UseKnownImages = true - processAirgapImageOptions.KnownImages = images - } - - result, err := upstream.ProcessAirgapImages(processAirgapImageOptions) + // TODO NOW: move this to base package + result, err := base.ProcessAirgapImages(processAirgapImageOptions) if err != nil { return nil, errors.Wrap(err, "failed to process airgap images") } @@ -262,18 +266,14 @@ func ProcessAirgapImages(options image.ProcessImageOptions, kotsKinds *kotsutil. } // findPrivateImages Finds and rewrites private images to be proxied through proxy.replicated.com -func findPrivateImages(opts WriteOptions, dockerHubRegistryCreds registry.Credentials) (*base.FindPrivateImagesResult, error) { +func findPrivateImages(opts WriteOptions, baseImages []string, kotsKindsImages []string, dockerHubRegistryCreds registry.Credentials) (*base.FindPrivateImagesResult, error) { replicatedRegistryInfo := registry.GetRegistryProxyInfo(opts.License, &opts.RenderedKotsKinds.Installation, &opts.RenderedKotsKinds.KotsApplication) allPrivate := opts.RenderedKotsKinds.KotsApplication.Spec.ProxyPublicImages - kotsKindsImages, err := kotsutil.GetImagesFromKotsKinds(opts.RenderedKotsKinds, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to get images from kots kinds") - } - findPrivateImagesOptions := base.FindPrivateImagesOptions{ - BaseDir: opts.BaseDir, - AppSlug: opts.License.Spec.AppSlug, + BaseImages: baseImages, + KotsKindsImages: kotsKindsImages, + AppSlug: opts.License.Spec.AppSlug, ReplicatedRegistry: dockerregistrytypes.RegistryOptions{ Endpoint: replicatedRegistryInfo.Registry, ProxyEndpoint: replicatedRegistryInfo.Proxy, @@ -285,9 +285,6 @@ func findPrivateImages(opts WriteOptions, dockerHubRegistryCreds registry.Creden }, Installation: &opts.RenderedKotsKinds.Installation, AllImagesPrivate: allPrivate, - HelmChartPath: opts.Base.Path, - UseHelmInstall: opts.UseHelmInstall, - KotsKindsImages: kotsKindsImages, } findResult, err := base.FindPrivateImages(findPrivateImagesOptions) if err != nil { diff --git a/pkg/pull/pull.go b/pkg/pull/pull.go index aadd810968..416109e238 100644 --- a/pkg/pull/pull.go +++ b/pkg/pull/pull.go @@ -361,7 +361,7 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { } if processImageOptions.RewriteImages && processImageOptions.AirgapRoot != "" { // if this is an airgap install, we still need to process the images - if _, err = midstream.ProcessAirgapImages(processImageOptions, renderedKotsKinds, fetchOptions.License, log); err != nil { + if _, err = midstream.ProcessAirgapImages(processImageOptions, nil, nil, renderedKotsKinds, fetchOptions.License, log); err != nil { return "", errors.Wrap(err, "failed to process airgap images") } } @@ -442,7 +442,7 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { renderedKotsKinds.Installation.Spec.YAMLErrors = files - if err := apparchive.SaveInstallation(&renderedKotsKinds.Installation, u.GetUpstreamDir(writeUpstreamOptions)); err != nil { + if err := kotsutil.SaveInstallation(&renderedKotsKinds.Installation, u.GetUpstreamDir(writeUpstreamOptions)); err != nil { log.FinishSpinnerWithError() return "", errors.Wrap(err, "failed to save installation") } @@ -509,26 +509,6 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { Log: log, } - // the UseHelmInstall map blocks visibility into charts and subcharts when searching for private images - // any chart name listed here will be skipped when writing midstream kustomization.yaml and pullsecret.yaml - // when using Helm Install, each chart gets it's own kustomization and pullsecret yaml and MUST be skipped when processing higher level directories! - // for writing Common Midstream, every chart and subchart is in this map as Helm Midstreams will be processed later in the code - commonWriteMidstreamOptions.UseHelmInstall = map[string]bool{} - for _, v := range v1Beta1HelmCharts { - chartBaseName := v.GetDirName() - commonWriteMidstreamOptions.UseHelmInstall[chartBaseName] = v.Spec.UseHelmInstall - if v.Spec.UseHelmInstall { - subcharts, err := base.FindHelmSubChartsFromBase(writeBaseOptions.BaseDir, chartBaseName) - if err != nil { - log.FinishSpinnerWithError() - return "", errors.Wrapf(err, "failed to find subcharts for parent chart %s", chartBaseName) - } - for _, subchart := range subcharts.SubCharts { - commonWriteMidstreamOptions.UseHelmInstall[subchart] = v.Spec.UseHelmInstall - } - } - } - writeMidstreamOptions := commonWriteMidstreamOptions writeMidstreamOptions.MidstreamDir = filepath.Join(u.GetOverlaysDir(writeUpstreamOptions), "midstream") writeMidstreamOptions.BaseDir = filepath.Join(u.GetBaseDir(writeUpstreamOptions), commonBase.Path) @@ -543,13 +523,6 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { helmMidstreams := []midstream.Midstream{} for _, helmBase := range helmBases { - // we must look at the current chart for private images, but must ignore subcharts - // to do this, we remove only the current helmBase name from the UseHelmInstall map to unblock visibility into the chart directory - // this ensures only the current chart resources are added to kustomization.yaml and pullsecret.yaml - // copy the bool setting in the map to restore it after this process loop - previousUseHelmInstall := writeMidstreamOptions.UseHelmInstall[helmBase.Path] - writeMidstreamOptions.UseHelmInstall[helmBase.Path] = false - helmBaseCopy := helmBase.DeepCopy() processImageOptionsCopy := processImageOptions @@ -567,9 +540,6 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { return "", errors.Wrapf(err, "failed to write helm midstream %s", helmBase.Path) } - // add this chart back into UseHelmInstall to make sure it's not processed again - writeMidstreamOptions.UseHelmInstall[helmBase.Path] = previousUseHelmInstall - helmMidstreams = append(helmMidstreams, *helmMidstream) } diff --git a/pkg/rewrite/rewrite.go b/pkg/rewrite/rewrite.go index e552f0f846..8419129ee6 100644 --- a/pkg/rewrite/rewrite.go +++ b/pkg/rewrite/rewrite.go @@ -167,7 +167,7 @@ func Rewrite(rewriteOptions RewriteOptions) error { renderedKotsKinds.Installation.Spec.YAMLErrors = files - if err := apparchive.SaveInstallation(&renderedKotsKinds.Installation, u.GetUpstreamDir(writeUpstreamOptions)); err != nil { + if err := kotsutil.SaveInstallation(&renderedKotsKinds.Installation, u.GetUpstreamDir(writeUpstreamOptions)); err != nil { return errors.Wrap(err, "failed to save installation") } } @@ -242,25 +242,6 @@ func Rewrite(rewriteOptions RewriteOptions) error { Log: log, } - // the UseHelmInstall map blocks visibility into charts and subcharts when searching for private images - // any chart name listed here will be skipped when writing midstream kustomization.yaml and pullsecret.yaml - // when using Helm Install, each chart gets it's own kustomization and pullsecret yaml and MUST be skipped when processing higher level directories! - // for writing Common Midstream, every chart and subchart is in this map as Helm Midstreams will be processed later in the code - commonWriteMidstreamOptions.UseHelmInstall = map[string]bool{} - for _, v := range v1Beta1HelmCharts { - chartBaseName := v.GetDirName() - commonWriteMidstreamOptions.UseHelmInstall[chartBaseName] = v.Spec.UseHelmInstall - if v.Spec.UseHelmInstall { - subcharts, err := base.FindHelmSubChartsFromBase(writeBaseOptions.BaseDir, chartBaseName) - if err != nil { - return errors.Wrapf(err, "failed to find subcharts for parent chart %s", chartBaseName) - } - for _, subchart := range subcharts.SubCharts { - commonWriteMidstreamOptions.UseHelmInstall[subchart] = v.Spec.UseHelmInstall - } - } - } - processImageOptions := image.ProcessImageOptions{ AppSlug: rewriteOptions.AppSlug, Namespace: rewriteOptions.K8sNamespace, @@ -289,14 +270,6 @@ func Rewrite(rewriteOptions RewriteOptions) error { helmMidstreams := []midstream.Midstream{} for _, helmBase := range helmBases { - // we must look at the current chart for private images, but must ignore subcharts - // to do this, we remove only the current helmBase name from the UseHelmInstall map to unblock visibility into the chart directory - // this ensures only the current chart resources are added to kustomization.yaml and pullsecret.yaml - // chartName := strings.Split(helmBase.Path, "/")[len(strings.Split(helmBase.Path, "/"))-1] - // copy the bool setting in the map to restore it after this process loop - previousUseHelmInstall := writeMidstreamOptions.UseHelmInstall[helmBase.Path] - writeMidstreamOptions.UseHelmInstall[helmBase.Path] = false - helmBaseCopy := helmBase.DeepCopy() processImageOptionsCopy := processImageOptions @@ -313,9 +286,6 @@ func Rewrite(rewriteOptions RewriteOptions) error { return errors.Wrapf(err, "failed to write helm midstream %s", helmBase.Path) } - // add this chart back into UseHelmInstall to make sure it's not processed again - writeMidstreamOptions.UseHelmInstall[helmBase.Path] = previousUseHelmInstall - helmMidstreams = append(helmMidstreams, *helmMidstream) } diff --git a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/kustomization.yaml b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/kustomization.yaml index a3aeaaba3f..d2e0b83c25 100644 --- a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/kustomization.yaml +++ b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: proxy.replicated.com/nginx -- name: docker.io/library/nginx - newName: proxy.replicated.com/nginx -- name: library/nginx - newName: proxy.replicated.com/nginx -- name: docker.io/nginx - newName: proxy.replicated.com/nginx - name: alpine newName: proxy.replicated.com/alpine - name: docker.io/library/alpine @@ -28,6 +20,14 @@ images: newName: proxy.replicated.com/busybox - name: docker.io/busybox newName: proxy.replicated.com/busybox +- name: nginx + newName: proxy.replicated.com/nginx +- name: docker.io/library/nginx + newName: proxy.replicated.com/nginx +- name: library/nginx + newName: proxy.replicated.com/nginx +- name: docker.io/nginx + newName: proxy.replicated.com/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/kustomization.yaml b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/kustomization.yaml index 99f888674d..6500b04fc1 100644 --- a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/kustomization.yaml +++ b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: proxy.replicated.com/nginx -- name: docker.io/library/nginx - newName: proxy.replicated.com/nginx -- name: library/nginx - newName: proxy.replicated.com/nginx -- name: docker.io/nginx - newName: proxy.replicated.com/nginx - name: alpine newName: proxy.replicated.com/alpine - name: docker.io/library/alpine @@ -28,6 +20,14 @@ images: newName: proxy.replicated.com/busybox - name: docker.io/busybox newName: proxy.replicated.com/busybox +- name: nginx + newName: proxy.replicated.com/nginx +- name: docker.io/library/nginx + newName: proxy.replicated.com/nginx +- name: library/nginx + newName: proxy.replicated.com/nginx +- name: docker.io/nginx + newName: proxy.replicated.com/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/replicatedhelm/testcase.yaml b/pkg/tests/pull/cases/replicatedhelm/testcase.yaml new file mode 100644 index 0000000000..69bc1b5b28 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/testcase.yaml @@ -0,0 +1,12 @@ +Name: test replicated helm pull without rewrite +PullOptions: + Namespace: app-namespace + ExcludeAdminConsole: true + IsAirgap: true + Silent: true + LocalPath: cases/replicatedhelm/upstream + RootDir: cases/replicatedhelm/results + SharedPassword: dummy-pass + RewriteImages: false + Downstreams: + - this-cluster \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/upstream/config.yaml b/pkg/tests/pull/cases/replicatedhelm/upstream/config.yaml new file mode 100644 index 0000000000..f115c91567 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/upstream/config.yaml @@ -0,0 +1,19 @@ +apiVersion: kots.io/v1beta1 +kind: Config +metadata: + name: my-app +spec: + groups: + - name: setup + title: Setup + items: + - name: hostname + type: text + title: Hostname + help_text: | + Use this field to provide a hostname for your Example Application installation. + required: true + - name: helm + title: Include helm + type: text + default: "no" diff --git a/pkg/tests/pull/cases/replicatedhelm/upstream/subdir/configmap.yaml b/pkg/tests/pull/cases/replicatedhelm/upstream/subdir/configmap.yaml new file mode 100644 index 0000000000..fa4697178f --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/upstream/subdir/configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-config +data: + configOptionHostname: {{repl ConfigOption "hostname" }} diff --git a/pkg/tests/pull/cases/replicatedhelm/upstream/test-chart-0.1.1.tgz b/pkg/tests/pull/cases/replicatedhelm/upstream/test-chart-0.1.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..50af594dde61c3d3c8fd961eef2e6a11ef45c1aa GIT binary patch literal 1893 zcmV-r2b%aFiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PI*>Z``;Q_A`IQsr|5R5NR~Nrg}5%Z0p8x3_D2?EEWNWIwLWr zNQH-*v9@S`dqGm8xp>lSx@m$%%?Dkm!*ls~Zj?iEiKw`BqceX^J6@}uuRF3V%Z?8Z z!#&Hg&3iUJIocT?9v$r;9cCv-_@Y%$>qtQPmI}2ByZsi*|xmqeEhv*OwWzPIs@V`nA)XI!;N|APeZnfO0A93O1P|IzsPG5){B*n@MN@>V&B z+aH2@=@cp3gV&WLkOUmwoxZ$GrpDIXIV@l*6?%em6pCAf8Ml&86cRWC6NH8nVF6M* z1D$C--?~xUA*GC23~AxawA$q`W=z(+#GC(kQBrg{TuiTw zyS7NE9Rt{dS2MI$7G7?J5cq)OCCn>B2t{w7jGtrbTIRWwfhW#kcemH!x>f2Hg+)g> z{Pc6kYYP#9Y}zXIV3HBqnG|>`L@+66cH5wkQ;7ug3SEU3IP`SDBOy>_T2*+wghlSK zV9-D1;B1S5(W%zPg&Z2d#;LblWP=tR+kX?Zp(d zaX{#R>!Q~sz-L>03Oq8B1SM*;USnuU>M}51U^DDB1BiveW7L@9bVEBocZ;I6(sgG> zJG^&;)>Hb6HEol_ewJk(;q7FCH+&+MbP_4z4p3OrES?iMy}S(17J2bXtM0}a_oGxu z9XYI5aJH>Jr7NR7!RGWELYu?5S0&)*CB!Osrdo1nFRs0_8tZa+w$GTr`a257&jX~lR^$0J8?L~gcR$0s`(bEkPJgg3W=?p03GX&@J6ZiQ^7)?T&HmW5m<6S%?w91P?o5p0u z6&aA)dp03?RketB>&S057!9ar(i&Z(b_8?jDp1ln)jPyOm8U?hsJ!@>QcJ%nsSlve zv``qBbG>HC%Cc5RYh4T*qm-FTT?Xz-YEQz84=si7wHKgKAQ89S(_p{F+63znL~B(C z6UzfOQ->CQSVH|n+B2=?a*ssQ24AlG_ZsVvaL4=4UdrCYk1f)#UBP(k3<<8JF1NaS zE%i-I`Q+0*K+W%0CbBH#VOyd*yMFV=NhN;?!EudNpmx4Cz_TpKj$|)`{7+LdZ3?_a zg~AydQ;jpqC#)E9KmE)YpH8Kgt_z>PcPaiZW2OHas`JQCe#JiUbN%1($;n3lceFpw z9{ayO3&W79&1&gv453fFD_uc49(xOE^3D(uziRyC2T=3G<%^FV5*Ov`(pQMkftt$gV zJJkzbF~twHro)$O@$2;fSODXPPoBOT<5Hs?XV{(ulec8%`<;vrJrP!hc>e&*Kq~G(~=VxzjE?&QTe|vU%b@lw_{fp=C-e=i( zAcS}l`q7#?Uzvp7=U!lUgVXgdy^DHpT%Z1gdoMos#)h^o52<&#A#rKlCBy2$#KAz{ zL2zBH8abLsJtBqJtW56yIm@!$O|cQf{2)Et5IX15p?wfo6YuTI$oiX^Yze8xkV}HI zDV2OMlOc{KT-=%I^wM`BIUIb}rME=r1NYmu>02 z#+5O5tD$Al7Z|r#d4;q88d{5w$bKoZ1E$xe__7KRr-acOMfiESz-Jws1h_4SbJl<0 zmp_YOtihPTyu@fw574BgZerpouMfvavDMt)T>n@4zqCSC%TgPQU!}De#^?V3A00gS z|9^OV^4R}Z_>x@OV2WO_PjfS^pw@^q+EG?xQg=4e|0C#kFbv$3*dPyWUB;4Qb(v;-ID&xxgtH6KtomdXP8D3V+Afu%DN frohqv=ZW%hJdVfldl~-@00960RrxUP03ZMWc=fEQ literal 0 HcmV?d00001 diff --git a/pkg/tests/pull/cases/replicatedhelm/upstream/test-chart.yaml b/pkg/tests/pull/cases/replicatedhelm/upstream/test-chart.yaml new file mode 100644 index 0000000000..8dc7b76547 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/upstream/test-chart.yaml @@ -0,0 +1,20 @@ +apiVersion: kots.io/v1beta1 +kind: HelmChart +metadata: + name: test-chart +spec: + # exclude: 'repl{{ ConfigOptionEquals "helm" "no" }}' + # chart identifies a matching chart from a .tgz + chart: + name: test-chart + chartVersion: 0.1.1 + useHelmInstall: false + namespace: helmns + + # values are used in the customer environment, as a pre-render step + # these values will be supplied to helm template + values: {} + + # builder values provide a way to render the chart with all images + # and manifests. this is used in replicated to create airgap packages + builder: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/upstream/userdata/config.yaml b/pkg/tests/pull/cases/replicatedhelm/upstream/userdata/config.yaml new file mode 100644 index 0000000000..fbbf7d0972 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/upstream/userdata/config.yaml @@ -0,0 +1,10 @@ +apiVersion: kots.io/v1beta1 +kind: ConfigValues +metadata: + creationTimestamp: null + name: my-app +spec: + values: + hostname: + value: "my-app.somebigbank.com" +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/upstream/userdata/license.yaml b/pkg/tests/pull/cases/replicatedhelm/upstream/userdata/license.yaml new file mode 100644 index 0000000000..25cc45c08b --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/upstream/userdata/license.yaml @@ -0,0 +1,47 @@ +apiVersion: kots.io/v1beta1 +kind: License +metadata: + name: testcustomer +spec: + appSlug: my-app + channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 + channelName: My Channel + customerName: Test Customer + endpoint: https://replicated.app + entitlements: + bool_field: + title: Bool Field + value: true + valueType: Boolean + expires_at: + description: License Expiration + title: Expiration + value: "2030-07-27T00:00:00Z" + valueType: String + hidden_field: + isHidden: true + title: Hidden Field + value: this is secret + valueType: String + int_field: + title: Int Field + value: 123 + valueType: Integer + string_field: + title: StringField + value: single line text + valueType: String + text_field: + title: Text Field + value: |- + multi + line + text + valueType: Text + isAirgapSupported: true + isGitOpsSupported: true + isSnapshotSupported: true + licenseID: 1vusOokxAVp1tkRGuyxnF23PJcq + licenseSequence: 7 + licenseType: prod + signature: eyJsaWNlbnNlRGF0YSI6ImV5SmhjR2xXWlhKemFXOXVJam9pYTI5MGN5NXBieTkyTVdKbGRHRXhJaXdpYTJsdVpDSTZJa3hwWTJWdWMyVWlMQ0p0WlhSaFpHRjBZU0k2ZXlKdVlXMWxJam9pZEdWemRHTjFjM1J2YldWeUluMHNJbk53WldNaU9uc2liR2xqWlc1elpVbEVJam9pTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54SWl3aWJHbGpaVzV6WlZSNWNHVWlPaUp3Y205a0lpd2lZM1Z6ZEc5dFpYSk9ZVzFsSWpvaVZHVnpkQ0JEZFhOMGIyMWxjaUlzSW1Gd2NGTnNkV2NpT2lKdGVTMWhjSEFpTENKamFHRnVibVZzU1VRaU9pSXhkblZ6U1ZsYVRFRldlRTFITm5FM05qQlBTbTFTUzJvMWFUVWlMQ0pqYUdGdWJtVnNUbUZ0WlNJNklrMTVJRU5vWVc1dVpXd2lMQ0pzYVdObGJuTmxVMlZ4ZFdWdVkyVWlPamNzSW1WdVpIQnZhVzUwSWpvaWFIUjBjSE02THk5eVpYQnNhV05oZEdWa0xtRndjQ0lzSW1WdWRHbDBiR1Z0Wlc1MGN5STZleUppYjI5c1gyWnBaV3hrSWpwN0luUnBkR3hsSWpvaVFtOXZiQ0JHYVdWc1pDSXNJblpoYkhWbElqcDBjblZsTENKMllXeDFaVlI1Y0dVaU9pSkNiMjlzWldGdUluMHNJbVY0Y0dseVpYTmZZWFFpT25zaWRHbDBiR1VpT2lKRmVIQnBjbUYwYVc5dUlpd2laR1Z6WTNKcGNIUnBiMjRpT2lKTWFXTmxibk5sSUVWNGNHbHlZWFJwYjI0aUxDSjJZV3gxWlNJNklqSXdNekF0TURjdE1qZFVNREE2TURBNk1EQmFJaXdpZG1Gc2RXVlVlWEJsSWpvaVUzUnlhVzVuSW4wc0ltaHBaR1JsYmw5bWFXVnNaQ0k2ZXlKMGFYUnNaU0k2SWtocFpHUmxiaUJHYVdWc1pDSXNJblpoYkhWbElqb2lkR2hwY3lCcGN5QnpaV055WlhRaUxDSjJZV3gxWlZSNWNHVWlPaUpUZEhKcGJtY2lMQ0pwYzBocFpHUmxiaUk2ZEhKMVpYMHNJbWx1ZEY5bWFXVnNaQ0k2ZXlKMGFYUnNaU0k2SWtsdWRDQkdhV1ZzWkNJc0luWmhiSFZsSWpveE1qTXNJblpoYkhWbFZIbHdaU0k2SWtsdWRHVm5aWElpZlN3aWMzUnlhVzVuWDJacFpXeGtJanA3SW5ScGRHeGxJam9pVTNSeWFXNW5SbWxsYkdRaUxDSjJZV3gxWlNJNkluTnBibWRzWlNCc2FXNWxJSFJsZUhRaUxDSjJZV3gxWlZSNWNHVWlPaUpUZEhKcGJtY2lmU3dpZEdWNGRGOW1hV1ZzWkNJNmV5SjBhWFJzWlNJNklsUmxlSFFnUm1sbGJHUWlMQ0oyWVd4MVpTSTZJbTExYkhScFhHNXNhVzVsWEc1MFpYaDBJaXdpZG1Gc2RXVlVlWEJsSWpvaVZHVjRkQ0o5ZlN3aWFYTkJhWEpuWVhCVGRYQndiM0owWldRaU9uUnlkV1VzSW1selIybDBUM0J6VTNWd2NHOXlkR1ZrSWpwMGNuVmxMQ0pwYzFOdVlYQnphRzkwVTNWd2NHOXlkR1ZrSWpwMGNuVmxmWDA9IiwiaW5uZXJTaWduYXR1cmUiOiJleUpzYVdObGJuTmxVMmxuYm1GMGRYSmxJam9pYUhneE1XTXZUR1ozUTNoVE5YRmtRWEJGU1hGdVRrMU9NMHBLYTJzNFZHZFhSVVpzVDFKVlJ6UjJjR1YzZEZoV1YzbG1lamRZY0hBd1ExazJZamRyUVRSS2N6TklhR3d3YkZJMFdUQTFMemN2UVVkQ2FEZFZNSGczUkhaTVozUXpVM00wYm5GTFZTdFhXRXBTVHpKWVFVRnZSME4xZFRWR1RGcHJRVWhYY1RSUVFtMXphSFY2Y1ZsdmNucHhlbGhGWVZWVlpFUlVkVXhDTW1nNWFIZ3dXRWhQUmxwUk16bHVkbTlPUjJaT2R5OTRTVmRaZEhSUGRYZHZhMncyTVZsb1JVeFZlRmQxU1ZSRmMwTlVhM2xtTVRNd09IazVSbFJzWlRKeVYyZEVlSEZNYTBSUFNXVXlPRWwzUzJSQkwySXdWVUl5VEZGbVRWcHdWemwyUTNCSkwybHlWek5uYmpaeU5WWjNWMjB2U1dweWJtNDNSelJrVmpadVYzcFRkMGhQUTJSdWEwMTRNRXQ1VVVOa0wxQjFaWEpUYjNSdVEwOXRTMDEzWlRSTGJqaERkMU5YVVRRNGRURkRNbTFpV1VzeGRYTlpOM1YzUFQwaUxDSndkV0pzYVdOTFpYa2lPaUl0TFMwdExVSkZSMGxPSUZCVlFreEpReUJMUlZrdExTMHRMVnh1VFVsSlFrbHFRVTVDWjJ0eGFHdHBSemwzTUVKQlVVVkdRVUZQUTBGUk9FRk5TVWxDUTJkTFEwRlJSVUZ6TkhKdlVIcDFhV1JNZVhOMmIxWTJkemxhTkZ4dVdHRmliME5tWTJNeGFHZFZhQ3N3V1VkS2NFNURSVXhyTjBaTFF5OTJhemR6ZERsR05tY3dUMjlrU0VSbGVYZFJXa2hLZFU1TVpsUnNRbEJHUTJOaU5seHVObTlzVEZOeWNGQTRjbFUzU0d4SGJsRkVSMFJNYVhkS1EyaGtSRGRVVUdSM2FXdHBkMHRGY201aldqaEdaalZsU25vd2RETmlUWFpyVDJaVVluSkJiRnh1WWtGQ1kwbzVNVmxVT1hKdVVXOXFkVWN4UldKUVRqaEZWblI2TWxZNE5IZHViR2Q0TUhCd2JEVjRPSFpOYlhwcE1ISnVibEZVV1VGamJ6WnFhMnBJTTF4dVRuTlVkWE4xUzFkdlJGUjVNWE5yZGtSUk9IbEJZV0ptWTNNME4zWnNRazAwU0RGT1JFNHZSSFJhWWxZdllubDJia0o2YkM4eFZrVnpURmRqWlZWcFRGeHVSWEYxT0VkeWF5dFFVRGQyUkdSd2JFUjNjWFpQV2t4RmRYazNkamhuUm01U09WUlVSV3ByTlVvNWRuWlVTR2RtU25VemVubEVPR2xLWTBSRE5YcHFPVnh1YjFGSlJFRlJRVUpjYmkwdExTMHRSVTVFSUZCVlFreEpReUJMUlZrdExTMHRMVnh1SWl3aWEyVjVVMmxuYm1GMGRYSmxJam9pWlhsS2VtRlhaSFZaV0ZJeFkyMVZhVTlwU2pCUldIQjJXVE5LVms1NmFGaFNSMlJzVVRKb2NtTklXa1ZVVlRsRldqQktXVTFGUmtaVFJFNUZVMGhLYkUxclRUTkxNSEJFVkROR2VGTnROVVJVVlRWVlltMDFiVnBGUm5sWldIQjZaRVJqTVZaSGFFeFBXRUpVVWtacmRrd3diek5aTUZaSlVteFdWRXd5T1VoV1JXeHNWa1ZPTUZSSE1WWlJNR04zVkd4R2JGa3pTblJUUm1zMFZVWk9hMVpWU2pCVU1WbDNZbXQwY0ZSclZuQmpia0poVFZjNWFtSldiSEZaYTNob1UyeHNWV0pGUmtWWGJVWnZWakZLVUZkcWJGSmhXRVp1V2xkb1EyRnVRak5TUjNNd1lWWkpOVTVXVmxkV1ZUVnlUMGhLYjFsVlRYbGhiVGcwVjBkYWVGbHFWbFppYlhoeFpFWkZkMDU1Y3pCaFZsSkpWRVpPTm1WRk1IcGxWWFJ2VFVaR1ZtRXdWVFJSVnpsSFVsaEtVRTFZUmxCU01WcFJVMVJDTmxsV2FIcFdWWEJ0WTBSU2JFMVVRazlPVjNSU1ZucFdUMU5XWTNaU1ZYUkZVMGhzYlU5VmJGaGtNMUl3WTFWc1lXTlhSakJTYTA1RVlVWmtjbUo2VmtSU00wSllUREkxUmsxWVl6SmxWM1JKVlZoQk1sVXhTbEppU0Zwd1VrVXdNRlpFVWt0VU1rWnNVVmQwYzFSV1VrMVVWV055V1RCYVRHSXpaRTlUVm05NVlraE9SR1JzVG5aUmFrWmFaVmRPVGxOVlNteGFiRXB1Wld0U2RVMHhSVGxRVTBselNXMWtjMkl5U21oaVJYUnNaVlZzYTBscWIybFpiVkpzV2xSVk1rNVVXWGRaTWxwcFRrUk9hazlYU1hsUFIwcHRUMVJvYkZsWFRtaGFiVVV5VGtSWmFXWlJQVDBpZlE9PSJ9 diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/Chart.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/Chart.yaml new file mode 100644 index 0000000000..8bcfff116e --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 1.16.0 +description: A Helm chart for Kubernetes +name: test-chart +type: application +version: 0.1.1 diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/chartHelmSecret.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/chartHelmSecret.yaml new file mode 100644 index 0000000000..05fa9cad4e --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/chartHelmSecret.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +data: + release: SDRzSUFBQUFBQUFDLyt4WjMzTGlQckorRlpmUExXU01DYW1CcXIzQURoZ1RJQUdDLzUxcy9VcVNoVzJRWkk4dEE4NVUzdjJVYkNDR2tOMmRzM3U1Y3pHMlcxS3IrK3YrV2kzeVcyYUFZcmtuYzV6eEpncEJ5dVdHSExGMUxQZCt5K3NvemZoZlBrNUlYR0JmN3NseVF5YmdpOGpIQlBQUGp3eWxVY0tqbU1rOStURXRwRFJuRW9wcElpYkpEVG5qZ09lWjNKUFBTajRhY3JWejc3ZE1NUWMrNEVDODN6SnRoOU9zVXEzY3RlNWFYemJzU3lOTXFGUk9sOVp4S2ozbEVLY01jNXpKRFJra2tYVldzRk5MU2ZJcGFkMjFIdTRVdVNIekloRTdneVFoRVFLbDZvK0dUR0swbFhzc0o2UWhjMHdUQW9UVzN2L1dMRDBLZndpYjd3cEFpVEN3ZEVkMkhTMnhxRlVnbGV6Z0pnNzh6ZUFKcUNUM0h1TmdwVm9iUkMxRnB5M2lHOE90Nnl6QzV5QU9UR09ZUTlwVlhHZVJRTFh6WHNyMGZnRGJmdTdaYys2eTdZTTVtaEczYlJYQVdYUW16b0s0dHZKazZscm0ybU1DUjlNSFBlb0hwcTd0ZkxWRDBDWU8zR1dMZVhhSElEcFVoSTVTbDJOeVNJZmNtNHM5T3lHMFYxZDZaeHZYN29oNVQ2aTlLSURkWVF0anFMaXZzZGdyOVp6dGcya01BdFMyOXA1akJ0Nm9lcUtqWDZiQkNaN0hmTEpVbnE1eGNCMXRqNHF1T3AwbktiQTcyK2RJRzNpT2xzRTI0WjdkdVlISkxmc1dCTFhuM0hQQ0VEcGE1aTFiRzJBTUM3K2Z2Q1BEMnBUclJtT0NqRVBpcXNQMzU2aC9FTGdnMWNvOGU2YkF0bm5DaWJ2T1lnTUdoOUNsVm9iZWhYLzlFbk5oNTRUeWxrdXRBbEpMOFp4cER1eWZPMkIzM24xam1MdnFUWnYrNmZvUzk5YzQrR3E3c0hsQmhNeDFGdVFjZTl0U1hIc1Irc2JnYUhNL01JMnY5cHE2RnFKUlB3ZHRLL0tjY2U0SmU0cE9Bb3R1QXRsTWNlM09SdXdyWXVRNzQ4UWZiYmx2V08vbHZpY2R4bkNQOUU3cTIyT0NhSWVJOFFrbHU0bDZqSUZoM2J0MmF3K05GWGZWTUVUczZPOW90dmZzYWMwK2tnTm44UWpWanVMYUpQZWM4VG1YVGIzUFRZTncxL2JKYzZRZGZIdllLZmRvbitPbGVQWmlBMVZsaCt3QkIycFhRWVZ5ZUtiRERCa2s5NWJLKzJTek92czlXV29KdEllczlNMnhRcndzZlM1RVRnRjdGdnFHdFhYVkxwKzBoK0hFNWp0L05PWFQ5eVNFSXkyQmRNV254YjM2YWZkc0I5a2lCSUl2ck9hUHJnU2UzVkZyUHBTeVV5eFhpdlZvV2VPeE5TVHJsVExUWHJlZDRZcDBKd3VMcktlUFZlN1Y0cVM2OXFIbHJid0Nxc3JENVZpSkpYSGJZK0lQT01IV21IaWJlb3pQT280Y0xIa1dmQm4vSjV5dTZUbGpCNm1mUUJZOFFHT29lTTVNcWR0MThoTTZXMTdQSDFmdDVyNHhUQ0MxaWpwV0FtOW9EMFd0cTl2T1RiMGJBZnQraDlRRDhaeisxWmpabVQ3MjkyWWQ0ODg4T2NYcllWcmMzN1ROVjRlSmJ3ZzdGRDZaSnlFeWlDM3lEdGpkL0RuU29wTG4ra1hkZVlLcStYVE5yNU0rWkhUZmZiMTE1TTRobTlqSnpnMXE5Y1VZaDY3S2R4NzFwc0J1SmY1akhFejNmOExoYit2YU41ejZQamUveFhzMGkrdFlUWlo5N3U0dmMvZ1lpMkQ2MnIrWkY2NTkySXM5NjNxQTNRbzkxWnI3OWlGYkdWM0JzODV6cEkyOWJXZm5EN1hDYzJZRXNubGRYKzdhTFJISEdLcmQ5THBXSW1xSm1scjRRMjBIRGJMQnIzSHdTaTFWNU9wa3FYQ2REdmZBOGdoaXN3U3E5dzhDZTkrWXhaTzJlOUFwVHlDZFA1aURNajdjY3hhaDkzbFduZmJkSTdyaXg5cWRRYjMxUzhRZXRUWGlsalZVaTF4N2xrTFZvNjhHNGNDWlA1aVBVeUZYdkxMZURSWHY5WWl0Y1hVK1hmcjM3dG16RnFKRXdjdFdqVWZhWjk1VTh6ZmYxOGJaRHRxdFVQaDBHVHZ0SGZRdll6ZXhwOWZ4emp6YjJwdVBnLzNYZUluNmZheWg4NjhjVzQyc0ROYndYOXJlTTJ3djVpSTI1Ymw4ZzNQQTZPNUEwYnFzRitMY2JTOUN4Qlp6cUI0U3Q3MTlNQWNkNHROdnVWbm41QnlxOCs4NWVYMTI2UzJDalNGSHhvRk03Rm5zT21QbDFCdUkyZ1NwdGZFTnNvTVh2UDNLbzhsU0N4SDF6M0VRV0YvSGNXSi9PZnNlbmgrUG5Qa2FNMjZPZk9ZNXh4ei9yR09SNzh3Nkx1M2VIL1BpbERkdFQ3VktEUDhSRitTUHZ6ZmtIU0M1NkVOL3kyQzlqbGpFQzduMys2TWhnNXpIR1FJa1lvRVl4QXhBSXJyME5TQVpic2dVSEJhNDdHOHp1ZGRTbElaTUkxYVROR1FPMGdCei9XVzE0aEdKM3NzKytBV25DRE1PQWl6M2Zpb2ZEWG1kRXlMYTMrY2RUdFBJeDlVdElLTGxqTjl5a2hQeUVwTUlGWEpQTnRlem1MK2tPTU5NOVBJcFR1SXM0bkVxeGxnUXNZTm92VUVnVkh3Y2RiemtoQ3d4U2pFWG5mYmZ4ZDBrU0hGV3VjdFl6RXVyc3NyamF4ZkRPT05WZ3k3ZTVGNTF6V2ppQXhDM2tUc1NJeUFhOUFUd3NOUXUwT1NrZW0zSVg3MWlzWStYbUdERTQ3VGFNWW45L3JVVlNld3ZNY3JUaUJkNnpEZys4RXFlVnRqcWNjNTRpVytLc3poUEVUNnV5MjR0eW5DNmkxQUZaU3l1U0QvVjgvVkVKM25HY1dxK3lKOFQrd2hWK20vQWcxSU1PSlo3UE0xeDQzUm5FV3Q1VEhCNm1sbjZucUVRVTNDNjdLd2pjbm5SdVFzeG9WSEE0aFIvWG5ETVFwdTd6a0lSelNZcU5BVVdXdUtwblIyaXE4QlhRd0pGc3RzazgwVEJLYlM5S0xDQ0JLaTRmeklMYlFVTThtNk9aaTAwMG5hSUxjUjc3Tm1IekRUOERLcG1BTzJoNHFwaEFpbktSRkVSUlJnNEhqRkhXdWdid2VXNE1jeTlmcnd4alE3eDFLRWlDb3VwaDN0RUxRcWNrSGk2MWdiT0lqYjFRVEtKdEJkSUR4M1Q2T2JlVXR1ZmZEQkhHa0dSYUJvN1pCTEUrV0k0VzYvYUMrR1BzUGNScWkwTzFmdkEyczVlVFdPUklEWjltbEEvOGZXZjFkTWdETkp1NGMzajNHVkpNZGxYVDJEN09XeVBpUjUxWXE4UWMwTldrNzM3OUg2blI5TmdYaDdpM2Z6WVdMU1FybEZnSHdqYXg3OG1iTlpHL2ZqWGhJNURVSDR2ZVBYZExZQ05ucDVZaWFudE91TUV0cTEzYzBBR0MyZjZOR0ZhQWRXRXVPMzUwNFNTcldjUGRub1U1NzdSMmlQYS9hVkhIUldwczUxbnJIWjY4TGUveVI4aUd5aGcwUnFYREdvMm0yL3NmNlJsbWJnOTZmTnUvdVBHNWZlTmZWNjRlOUt1OWNhMkVmTjdVa1hvTjNhNjdQZmVtQ1RWMHJYOGxxUjR6N0RmaEVWUE9sR2p5VEdnWXBBQWlFbDlYdHFUUURQQVRPUXg5cHVscUNteVZVd1J6NXFTREFIR2NQckdNcDVHTEhnOFdiREZSVThDVXBZbk9KWDg4ditzdEZTTXZMSC9pT3N2c1gvbDk1VnhwZHBqaGFyVVZ5SVVNNGFSZ09lTlpRbEc1Vm9VTXc0aWh0TUtpcVlFMHVDRVN2TWY2ZXo5VktwWktLWVVNUCs4WmgrSXdJajNzdnoySkpobkJZd1BsYXl5OVRRbnhSa0hLYS9LZTArYTRaMEE5ZCtBQ1NSSjl1TVRxOGZ5QnlLS0dmOVR5R29RSGF0dTFwTmE0ak03bHUrand4UndGRTdxeVNRSksrNjI1MStON3FMNFI4UXlEaGk2M3ZQN0JaV0JWeVpKMGdtQTArWjFuOFEvY21uSS84T1VQekJHa3M0WWxlRm1FZGN2MDZuS2lHTWUvTXBCSWJRZDhlVFlSekg5OFFzMHR6SFBtcTBlSUVuRWNMTjkxL25EcGUzUHBRK25wZWlXSVpqdGF0QTBqMW13SE9pcmhmbnEvclhVKzdQWllQSFgwOEQ5UzFGYW56TWxxZXlRaG1sTWUzV3BkR1QzRXk0V2VIMDFkS3dHSmZFdjVkOFZrOVA0MGVteW4rbVY2VjZMVHJXWUZzM3orck9ybjQ1ZWNyS1MvWUFSKzVFUmpKTzY5RTN1S29yeUpuL1p2WUswMTc2N3Y5NTdEeUwrYjlJVUN0TFVlRHFPNFUyQ0puSEdtMlhDRXRMY2lFbm5qSU1BYmVQMWVoTFJpUGVrOXI5Q2podWt2NUhHTnpQbkZxQlpXUDlxb29zeGdiUFVVcjZCOVVyOGNtNXhlMUs5dzcxR1Bvemo3UVZaLytQMTgxOE9USXIvRzVjL2pVdjlqdyt0cW4zT0VpQmFjMWwwd3l5VFAvNHZBQUQvL3lJbkFOVk9HUUFB +kind: Secret +metadata: + labels: + createdAt: "1" + name: test-chart + owner: helm + status: deployed + version: "1" + name: sh.helm.release.v1.test-chart.v1 + namespace: helmns +type: helm.sh/release.v1 diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/kustomization.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/kustomization.yaml new file mode 100644 index 0000000000..074775d621 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/kustomization.yaml @@ -0,0 +1,12 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + annotations: + kots.io/kustomization: base +resources: +- chartHelmSecret.yaml +- test-1.yaml +- test-2.yaml +- test-3.yaml +- test-4.yaml +- test-5.yaml diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-1.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-1.yaml new file mode 100644 index 0000000000..57a2d11a47 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-1.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + annotations: + owned-by: security-team + labels: + owner: a-generated-owner-name + name: security-scanner + namespace: helmns +stringData: + key: a super duper secret key diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-2.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-2.yaml new file mode 100644 index 0000000000..621ac98529 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-2.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-test-example-chart-test-connection + namespace: helmns +spec: + containers: + - args: + - security-test-example-chart:80 + command: + - wget + image: busybox + name: wget + restartPolicy: Never diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-3.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-3.yaml new file mode 100644 index 0000000000..127dc27076 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-3.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: security-test-example-chart + namespace: helmns +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: security-test + app.kubernetes.io/name: example-chart + template: + metadata: + labels: + app.kubernetes.io/instance: security-test + app.kubernetes.io/name: example-chart + spec: + containers: + - env: + - name: SECURITY_SCANNER_KEY_001 + valueFrom: + secretKeyRef: + key: key + name: security-scanner + image: nginx:latest + name: my-security-container + - command: + - /bin/sleep + - "9000" + image: alpine:3.4 + name: waiter + initContainers: + - image: quay.io/replicatedcom/qa-kots-1:alpine-3.5 + - image: quay.io/replicatedcom/qa-kots-3:alpine-3.6 diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-4.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-4.yaml new file mode 100644 index 0000000000..4a1d0ee0bf --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-4.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: post-install-job + namespace: helmns +spec: + backoffLimit: 3 + template: + metadata: + name: security-test + spec: + containers: + - command: + - sh + - -c + - sleep 10 + image: alpine + imagePullPolicy: IfNotPresent + name: hook-test + restartPolicy: Never diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-5.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-5.yaml new file mode 100644 index 0000000000..837bbfecc2 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/test-5.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: pre-install-job + namespace: helmns +spec: + backoffLimit: 3 + template: + metadata: + name: security-test + spec: + containers: + - command: + - sh + - -c + - sleep 10 + image: alpine + imagePullPolicy: IfNotPresent + name: hook-test + restartPolicy: Never diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/values.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/values.yaml new file mode 100644 index 0000000000..de2bccb1ac --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/charts/test-chart/values.yaml @@ -0,0 +1,34 @@ +affinity: {} +autoscaling: + enabled: false + maxReplicas: 100 + minReplicas: 1 + targetCPUUtilizationPercentage: 80 +fullnameOverride: "" +image: + pullPolicy: IfNotPresent + repository: nginx + tag: "" +imagePullSecrets: [] +ingress: + annotations: {} + enabled: false + hosts: + - host: chart-example.local + paths: [] + tls: [] +nameOverride: "" +nodeSelector: {} +podAnnotations: {} +podSecurityContext: {} +replicaCount: 1 +resources: {} +securityContext: {} +service: + port: 82 + type: ClusterIP +serviceAccount: + annotations: {} + create: true + name: "" +tolerations: [] diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/kustomization.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/kustomization.yaml new file mode 100644 index 0000000000..219698e8b1 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + annotations: + kots.io/kustomization: base +resources: +- charts/test-chart/chartHelmSecret.yaml +- charts/test-chart/test-1.yaml +- charts/test-chart/test-2.yaml +- charts/test-chart/test-3.yaml +- charts/test-chart/test-4.yaml +- charts/test-chart/test-5.yaml +- subdir/configmap.yaml diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/base/subdir/configmap.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/subdir/configmap.yaml new file mode 100644 index 0000000000..c0a01cdd1c --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/base/subdir/configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-config +data: + configOptionHostname: my-app.somebigbank.com diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/config.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/config.yaml new file mode 100644 index 0000000000..80a23ac410 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/config.yaml @@ -0,0 +1,24 @@ +apiVersion: kots.io/v1beta1 +kind: Config +metadata: + creationTimestamp: null + name: my-app +spec: + groups: + - items: + - default: "" + help_text: | + Use this field to provide a hostname for your Example Application installation. + name: hostname + required: true + title: Hostname + type: text + value: my-app.somebigbank.com + - default: "no" + name: helm + title: Include helm + type: text + value: "" + name: setup + title: Setup +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/test-chart.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/test-chart.yaml new file mode 100644 index 0000000000..5153d447c7 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/test-chart.yaml @@ -0,0 +1,20 @@ +apiVersion: kots.io/v1beta1 +kind: HelmChart +metadata: + name: test-chart +spec: + # exclude: 'true' + # chart identifies a matching chart from a .tgz + chart: + name: test-chart + chartVersion: 0.1.1 + useHelmInstall: false + namespace: helmns + + # values are used in the customer environment, as a pre-render step + # these values will be supplied to helm template + values: {} + + # builder values provide a way to render the chart with all images + # and manifests. this is used in replicated to create airgap packages + builder: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/config.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/config.yaml new file mode 100644 index 0000000000..d70bc110be --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/config.yaml @@ -0,0 +1,12 @@ +apiVersion: kots.io/v1beta1 +kind: ConfigValues +metadata: + creationTimestamp: null + name: replicated-kots-app +spec: + values: + helm: + default: "no" + hostname: + value: my-app.somebigbank.com +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/installation.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/installation.yaml new file mode 100644 index 0000000000..ffa201a902 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/installation.yaml @@ -0,0 +1,18 @@ +apiVersion: kots.io/v1beta1 +kind: Installation +metadata: + creationTimestamp: null + name: replicated-kots-app +spec: + channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 + channelName: My Channel + knownImages: + - image: quay.io/replicatedcom/qa-kots-3:alpine-3.6 + isPrivate: true + - image: quay.io/replicatedcom/qa-kots-1:alpine-3.5 + isPrivate: true + - image: alpine:3.4 + - image: alpine + - image: nginx:latest + - image: busybox +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/license.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/license.yaml new file mode 100644 index 0000000000..9fa3a14d7f --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/kotsKinds/userdata/license.yaml @@ -0,0 +1,49 @@ +apiVersion: kots.io/v1beta1 +kind: License +metadata: + creationTimestamp: null + name: testcustomer +spec: + appSlug: my-app + channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 + channelName: My Channel + customerName: Test Customer + endpoint: https://replicated.app + entitlements: + bool_field: + title: Bool Field + value: true + valueType: Boolean + expires_at: + description: License Expiration + title: Expiration + value: "2030-07-27T00:00:00Z" + valueType: String + hidden_field: + isHidden: true + title: Hidden Field + value: this is secret + valueType: String + int_field: + title: Int Field + value: 123 + valueType: Integer + string_field: + title: StringField + value: single line text + valueType: String + text_field: + title: Text Field + value: |- + multi + line + text + valueType: Text + isAirgapSupported: true + isGitOpsSupported: true + isSnapshotSupported: true + licenseID: 1vusOokxAVp1tkRGuyxnF23PJcq + licenseSequence: 7 + licenseType: prod + signature: eyJsaWNlbnNlRGF0YSI6ImV5SmhjR2xXWlhKemFXOXVJam9pYTI5MGN5NXBieTkyTVdKbGRHRXhJaXdpYTJsdVpDSTZJa3hwWTJWdWMyVWlMQ0p0WlhSaFpHRjBZU0k2ZXlKdVlXMWxJam9pZEdWemRHTjFjM1J2YldWeUluMHNJbk53WldNaU9uc2liR2xqWlc1elpVbEVJam9pTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54SWl3aWJHbGpaVzV6WlZSNWNHVWlPaUp3Y205a0lpd2lZM1Z6ZEc5dFpYSk9ZVzFsSWpvaVZHVnpkQ0JEZFhOMGIyMWxjaUlzSW1Gd2NGTnNkV2NpT2lKdGVTMWhjSEFpTENKamFHRnVibVZzU1VRaU9pSXhkblZ6U1ZsYVRFRldlRTFITm5FM05qQlBTbTFTUzJvMWFUVWlMQ0pqYUdGdWJtVnNUbUZ0WlNJNklrMTVJRU5vWVc1dVpXd2lMQ0pzYVdObGJuTmxVMlZ4ZFdWdVkyVWlPamNzSW1WdVpIQnZhVzUwSWpvaWFIUjBjSE02THk5eVpYQnNhV05oZEdWa0xtRndjQ0lzSW1WdWRHbDBiR1Z0Wlc1MGN5STZleUppYjI5c1gyWnBaV3hrSWpwN0luUnBkR3hsSWpvaVFtOXZiQ0JHYVdWc1pDSXNJblpoYkhWbElqcDBjblZsTENKMllXeDFaVlI1Y0dVaU9pSkNiMjlzWldGdUluMHNJbVY0Y0dseVpYTmZZWFFpT25zaWRHbDBiR1VpT2lKRmVIQnBjbUYwYVc5dUlpd2laR1Z6WTNKcGNIUnBiMjRpT2lKTWFXTmxibk5sSUVWNGNHbHlZWFJwYjI0aUxDSjJZV3gxWlNJNklqSXdNekF0TURjdE1qZFVNREE2TURBNk1EQmFJaXdpZG1Gc2RXVlVlWEJsSWpvaVUzUnlhVzVuSW4wc0ltaHBaR1JsYmw5bWFXVnNaQ0k2ZXlKMGFYUnNaU0k2SWtocFpHUmxiaUJHYVdWc1pDSXNJblpoYkhWbElqb2lkR2hwY3lCcGN5QnpaV055WlhRaUxDSjJZV3gxWlZSNWNHVWlPaUpUZEhKcGJtY2lMQ0pwYzBocFpHUmxiaUk2ZEhKMVpYMHNJbWx1ZEY5bWFXVnNaQ0k2ZXlKMGFYUnNaU0k2SWtsdWRDQkdhV1ZzWkNJc0luWmhiSFZsSWpveE1qTXNJblpoYkhWbFZIbHdaU0k2SWtsdWRHVm5aWElpZlN3aWMzUnlhVzVuWDJacFpXeGtJanA3SW5ScGRHeGxJam9pVTNSeWFXNW5SbWxsYkdRaUxDSjJZV3gxWlNJNkluTnBibWRzWlNCc2FXNWxJSFJsZUhRaUxDSjJZV3gxWlZSNWNHVWlPaUpUZEhKcGJtY2lmU3dpZEdWNGRGOW1hV1ZzWkNJNmV5SjBhWFJzWlNJNklsUmxlSFFnUm1sbGJHUWlMQ0oyWVd4MVpTSTZJbTExYkhScFhHNXNhVzVsWEc1MFpYaDBJaXdpZG1Gc2RXVlVlWEJsSWpvaVZHVjRkQ0o5ZlN3aWFYTkJhWEpuWVhCVGRYQndiM0owWldRaU9uUnlkV1VzSW1selIybDBUM0J6VTNWd2NHOXlkR1ZrSWpwMGNuVmxMQ0pwYzFOdVlYQnphRzkwVTNWd2NHOXlkR1ZrSWpwMGNuVmxmWDA9IiwiaW5uZXJTaWduYXR1cmUiOiJleUpzYVdObGJuTmxVMmxuYm1GMGRYSmxJam9pYUhneE1XTXZUR1ozUTNoVE5YRmtRWEJGU1hGdVRrMU9NMHBLYTJzNFZHZFhSVVpzVDFKVlJ6UjJjR1YzZEZoV1YzbG1lamRZY0hBd1ExazJZamRyUVRSS2N6TklhR3d3YkZJMFdUQTFMemN2UVVkQ2FEZFZNSGczUkhaTVozUXpVM00wYm5GTFZTdFhXRXBTVHpKWVFVRnZSME4xZFRWR1RGcHJRVWhYY1RSUVFtMXphSFY2Y1ZsdmNucHhlbGhGWVZWVlpFUlVkVXhDTW1nNWFIZ3dXRWhQUmxwUk16bHVkbTlPUjJaT2R5OTRTVmRaZEhSUGRYZHZhMncyTVZsb1JVeFZlRmQxU1ZSRmMwTlVhM2xtTVRNd09IazVSbFJzWlRKeVYyZEVlSEZNYTBSUFNXVXlPRWwzUzJSQkwySXdWVUl5VEZGbVRWcHdWemwyUTNCSkwybHlWek5uYmpaeU5WWjNWMjB2U1dweWJtNDNSelJrVmpadVYzcFRkMGhQUTJSdWEwMTRNRXQ1VVVOa0wxQjFaWEpUYjNSdVEwOXRTMDEzWlRSTGJqaERkMU5YVVRRNGRURkRNbTFpV1VzeGRYTlpOM1YzUFQwaUxDSndkV0pzYVdOTFpYa2lPaUl0TFMwdExVSkZSMGxPSUZCVlFreEpReUJMUlZrdExTMHRMVnh1VFVsSlFrbHFRVTVDWjJ0eGFHdHBSemwzTUVKQlVVVkdRVUZQUTBGUk9FRk5TVWxDUTJkTFEwRlJSVUZ6TkhKdlVIcDFhV1JNZVhOMmIxWTJkemxhTkZ4dVdHRmliME5tWTJNeGFHZFZhQ3N3V1VkS2NFNURSVXhyTjBaTFF5OTJhemR6ZERsR05tY3dUMjlrU0VSbGVYZFJXa2hLZFU1TVpsUnNRbEJHUTJOaU5seHVObTlzVEZOeWNGQTRjbFUzU0d4SGJsRkVSMFJNYVhkS1EyaGtSRGRVVUdSM2FXdHBkMHRGY201aldqaEdaalZsU25vd2RETmlUWFpyVDJaVVluSkJiRnh1WWtGQ1kwbzVNVmxVT1hKdVVXOXFkVWN4UldKUVRqaEZWblI2TWxZNE5IZHViR2Q0TUhCd2JEVjRPSFpOYlhwcE1ISnVibEZVV1VGamJ6WnFhMnBJTTF4dVRuTlVkWE4xUzFkdlJGUjVNWE5yZGtSUk9IbEJZV0ptWTNNME4zWnNRazAwU0RGT1JFNHZSSFJhWWxZdllubDJia0o2YkM4eFZrVnpURmRqWlZWcFRGeHVSWEYxT0VkeWF5dFFVRGQyUkdSd2JFUjNjWFpQV2t4RmRYazNkamhuUm01U09WUlVSV3ByTlVvNWRuWlVTR2RtU25VemVubEVPR2xLWTBSRE5YcHFPVnh1YjFGSlJFRlJRVUpjYmkwdExTMHRSVTVFSUZCVlFreEpReUJMUlZrdExTMHRMVnh1SWl3aWEyVjVVMmxuYm1GMGRYSmxJam9pWlhsS2VtRlhaSFZaV0ZJeFkyMVZhVTlwU2pCUldIQjJXVE5LVms1NmFGaFNSMlJzVVRKb2NtTklXa1ZVVlRsRldqQktXVTFGUmtaVFJFNUZVMGhLYkUxclRUTkxNSEJFVkROR2VGTnROVVJVVlRWVlltMDFiVnBGUm5sWldIQjZaRVJqTVZaSGFFeFBXRUpVVWtacmRrd3diek5aTUZaSlVteFdWRXd5T1VoV1JXeHNWa1ZPTUZSSE1WWlJNR04zVkd4R2JGa3pTblJUUm1zMFZVWk9hMVpWU2pCVU1WbDNZbXQwY0ZSclZuQmpia0poVFZjNWFtSldiSEZaYTNob1UyeHNWV0pGUmtWWGJVWnZWakZLVUZkcWJGSmhXRVp1V2xkb1EyRnVRak5TUjNNd1lWWkpOVTVXVmxkV1ZUVnlUMGhLYjFsVlRYbGhiVGcwVjBkYWVGbHFWbFppYlhoeFpFWkZkMDU1Y3pCaFZsSkpWRVpPTm1WRk1IcGxWWFJ2VFVaR1ZtRXdWVFJSVnpsSFVsaEtVRTFZUmxCU01WcFJVMVJDTmxsV2FIcFdWWEJ0WTBSU2JFMVVRazlPVjNSU1ZucFdUMU5XWTNaU1ZYUkZVMGhzYlU5VmJGaGtNMUl3WTFWc1lXTlhSakJTYTA1RVlVWmtjbUo2VmtSU00wSllUREkxUmsxWVl6SmxWM1JKVlZoQk1sVXhTbEppU0Zwd1VrVXdNRlpFVWt0VU1rWnNVVmQwYzFSV1VrMVVWV055V1RCYVRHSXpaRTlUVm05NVlraE9SR1JzVG5aUmFrWmFaVmRPVGxOVlNteGFiRXB1Wld0U2RVMHhSVGxRVTBselNXMWtjMkl5U21oaVJYUnNaVlZzYTBscWIybFpiVkpzV2xSVk1rNVVXWGRaTWxwcFRrUk9hazlYU1hsUFIwcHRUMVJvYkZsWFRtaGFiVVV5VGtSWmFXWlJQVDBpZlE9PSJ9 +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/downstreams/this-cluster/kustomization.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/downstreams/this-cluster/kustomization.yaml new file mode 100644 index 0000000000..73a609d8fa --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/downstreams/this-cluster/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +bases: +- ../../midstream +kind: Kustomization diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/backup-label-transformer.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/backup-label-transformer.yaml new file mode 100644 index 0000000000..c3acc6c5b9 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/backup-label-transformer.yaml @@ -0,0 +1,39 @@ +apiVersion: builtin +kind: LabelTransformer +metadata: + name: backup-label-transformer +labels: + kots.io/app-slug: my-app + kots.io/backup: velero +fieldSpecs: +- path: metadata/labels + create: true +- version: v1 + kind: ReplicationController + path: spec/template/metadata/labels + create: true +- kind: Deployment + path: spec/template/metadata/labels + create: true +- kind: ReplicaSet + path: spec/template/metadata/labels + create: true +- kind: DaemonSet + path: spec/template/metadata/labels + create: true +- group: apps + kind: StatefulSet + path: spec/template/metadata/labels + create: true +- group: batch + kind: Job + path: spec/template/metadata/labels + create: true +- group: batch + kind: CronJob + path: spec/jobTemplate/metadata/labels + create: true +- group: batch + kind: CronJob + path: spec/jobTemplate/spec/template/metadata/labels + create: true diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/kustomization.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/kustomization.yaml new file mode 100644 index 0000000000..c2fc38b110 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/kustomization.yaml @@ -0,0 +1,17 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +bases: +- ../../base +commonAnnotations: + kots.io/app-slug: my-app +images: +- name: quay.io/replicatedcom/qa-kots-1 + newName: proxy.replicated.com/proxy/my-app/quay.io/replicatedcom/qa-kots-1 +- name: quay.io/replicatedcom/qa-kots-3 + newName: proxy.replicated.com/proxy/my-app/quay.io/replicatedcom/qa-kots-3 +kind: Kustomization +patchesStrategicMerge: +- pullsecrets.yaml +resources: +- secret.yaml +transformers: +- backup-label-transformer.yaml diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/pullsecrets.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/pullsecrets.yaml new file mode 100644 index 0000000000..78b582aec2 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/pullsecrets.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: security-test-example-chart-test-connection + namespace: helmns +spec: + imagePullSecrets: + - name: my-app-registry +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: security-test-example-chart + namespace: helmns +spec: + template: + spec: + imagePullSecrets: + - name: my-app-registry +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: post-install-job + namespace: helmns +spec: + template: + spec: + imagePullSecrets: + - name: my-app-registry +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: pre-install-job + namespace: helmns +spec: + template: + spec: + imagePullSecrets: + - name: my-app-registry diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/secret.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/secret.yaml new file mode 100644 index 0000000000..4d81bc057f --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/overlays/midstream/secret.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +data: + .dockerconfigjson: eyJhdXRocyI6eyJwcm94eS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9LCJyZWdpc3RyeS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9fX0= +kind: Secret +metadata: + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-9999" + kots.io/creation-phase: "-9999" + creationTimestamp: null + name: my-app-registry + namespace: app-namespace +type: kubernetes.io/dockerconfigjson + +--- +apiVersion: v1 +data: + .dockerconfigjson: eyJhdXRocyI6eyJwcm94eS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9LCJyZWdpc3RyeS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9fX0= +kind: Secret +metadata: + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-9999" + kots.io/creation-phase: "-9999" + creationTimestamp: null + name: kotsadm-replicated-registry + namespace: app-namespace +type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/kotsadm-replicated-registry-secret.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/kotsadm-replicated-registry-secret.yaml new file mode 100644 index 0000000000..6f52289831 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/kotsadm-replicated-registry-secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +data: + .dockerconfigjson: eyJhdXRocyI6eyJwcm94eS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9LCJyZWdpc3RyeS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9fX0= +kind: Secret +metadata: + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-9999" + kots.io/app-slug: my-app + kots.io/creation-phase: "-9999" + creationTimestamp: null + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: kotsadm-replicated-registry + namespace: app-namespace +type: kubernetes.io/dockerconfigjson \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/my-app-registry-secret.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/my-app-registry-secret.yaml new file mode 100644 index 0000000000..6b04fe7f14 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/my-app-registry-secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +data: + .dockerconfigjson: eyJhdXRocyI6eyJwcm94eS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9LCJyZWdpc3RyeS5yZXBsaWNhdGVkLmNvbSI6eyJhdXRoIjoiTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54T2pGMmRYTlBiMnQ0UVZad01YUnJVa2QxZVhodVJqSXpVRXBqY1E9PSJ9fX0= +kind: Secret +metadata: + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-9999" + kots.io/app-slug: my-app + kots.io/creation-phase: "-9999" + creationTimestamp: null + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: my-app-registry + namespace: app-namespace +type: kubernetes.io/dockerconfigjson \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/post-install-job-job.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/post-install-job-job.yaml new file mode 100644 index 0000000000..8f99920839 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/post-install-job-job.yaml @@ -0,0 +1,32 @@ +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: post-install-job + namespace: helmns +spec: + backoffLimit: 3 + template: + metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: security-test + spec: + containers: + - command: + - sh + - -c + - sleep 10 + image: alpine + imagePullPolicy: IfNotPresent + name: hook-test + imagePullSecrets: + - name: my-app-registry + restartPolicy: Never \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/pre-install-job-job.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/pre-install-job-job.yaml new file mode 100644 index 0000000000..ef150db5a0 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/pre-install-job-job.yaml @@ -0,0 +1,32 @@ +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: pre-install-job + namespace: helmns +spec: + backoffLimit: 3 + template: + metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: security-test + spec: + containers: + - command: + - sh + - -c + - sleep 10 + image: alpine + imagePullPolicy: IfNotPresent + name: hook-test + imagePullSecrets: + - name: my-app-registry + restartPolicy: Never \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-scanner-secret.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-scanner-secret.yaml new file mode 100644 index 0000000000..90304a32a2 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-scanner-secret.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +metadata: + annotations: + kots.io/app-slug: my-app + owned-by: security-team + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + owner: a-generated-owner-name + name: security-scanner + namespace: helmns +stringData: + key: a super duper secret key \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-deployment.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-deployment.yaml new file mode 100644 index 0000000000..e9ac38dea3 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-deployment.yaml @@ -0,0 +1,44 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: security-test-example-chart + namespace: helmns +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: security-test + app.kubernetes.io/name: example-chart + template: + metadata: + annotations: + kots.io/app-slug: my-app + labels: + app.kubernetes.io/instance: security-test + app.kubernetes.io/name: example-chart + kots.io/app-slug: my-app + kots.io/backup: velero + spec: + containers: + - env: + - name: SECURITY_SCANNER_KEY_001 + valueFrom: + secretKeyRef: + key: key + name: security-scanner + image: nginx:latest + name: my-security-container + - command: + - /bin/sleep + - "9000" + image: alpine:3.4 + name: waiter + imagePullSecrets: + - name: my-app-registry + initContainers: + - image: proxy.replicated.com/proxy/my-app/quay.io/replicatedcom/qa-kots-3:alpine-3.6 \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-test-connection-pod.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-test-connection-pod.yaml new file mode 100644 index 0000000000..4bcc8a23cf --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/security-test-example-chart-test-connection-pod.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: security-test-example-chart-test-connection + namespace: helmns +spec: + containers: + - args: + - security-test-example-chart:80 + command: + - wget + image: busybox + name: wget + imagePullSecrets: + - name: my-app-registry + restartPolicy: Never diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/sh.helm.release.v1.test-chart.v1-secret.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/sh.helm.release.v1.test-chart.v1-secret.yaml new file mode 100644 index 0000000000..49583ee5fe --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/sh.helm.release.v1.test-chart.v1-secret.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +data: + release: SDRzSUFBQUFBQUFDLyt4WjMzTGlQckorRlpmUExXU01DYW1CcXIzQURoZ1RJQUdDLzUxcy9VcVNoVzJRWkk4dEE4NVUzdjJVYkNDR2tOMmRzM3U1Y3pHMlcxS3IrK3YrV2kzeVcyYUFZcmtuYzV6eEpncEJ5dVdHSExGMUxQZCt5K3NvemZoZlBrNUlYR0JmN3NseVF5YmdpOGpIQlBQUGp3eWxVY0tqbU1rOStURXRwRFJuRW9wcElpYkpEVG5qZ09lWjNKUFBTajRhY3JWejc3ZE1NUWMrNEVDODN6SnRoOU9zVXEzY3RlNWFYemJzU3lOTXFGUk9sOVp4S2ozbEVLY01jNXpKRFJra2tYVldzRk5MU2ZJcGFkMjFIdTRVdVNIekloRTdneVFoRVFLbDZvK0dUR0swbFhzc0o2UWhjMHdUQW9UVzN2L1dMRDBLZndpYjd3cEFpVEN3ZEVkMkhTMnhxRlVnbGV6Z0pnNzh6ZUFKcUNUM0h1TmdwVm9iUkMxRnB5M2lHOE90Nnl6QzV5QU9UR09ZUTlwVlhHZVJRTFh6WHNyMGZnRGJmdTdaYys2eTdZTTVtaEczYlJYQVdYUW16b0s0dHZKazZscm0ybU1DUjlNSFBlb0hwcTd0ZkxWRDBDWU8zR1dMZVhhSElEcFVoSTVTbDJOeVNJZmNtNHM5T3lHMFYxZDZaeHZYN29oNVQ2aTlLSURkWVF0anFMaXZzZGdyOVp6dGcya01BdFMyOXA1akJ0Nm9lcUtqWDZiQkNaN0hmTEpVbnE1eGNCMXRqNHF1T3AwbktiQTcyK2RJRzNpT2xzRTI0WjdkdVlISkxmc1dCTFhuM0hQQ0VEcGE1aTFiRzJBTUM3K2Z2Q1BEMnBUclJtT0NqRVBpcXNQMzU2aC9FTGdnMWNvOGU2YkF0bm5DaWJ2T1lnTUdoOUNsVm9iZWhYLzlFbk5oNTRUeWxrdXRBbEpMOFp4cER1eWZPMkIzM24xam1MdnFUWnYrNmZvUzk5YzQrR3E3c0hsQmhNeDFGdVFjZTl0U1hIc1Irc2JnYUhNL01JMnY5cHE2RnFKUlB3ZHRLL0tjY2U0SmU0cE9Bb3R1QXRsTWNlM09SdXdyWXVRNzQ4UWZiYmx2V08vbHZpY2R4bkNQOUU3cTIyT0NhSWVJOFFrbHU0bDZqSUZoM2J0MmF3K05GWGZWTUVUczZPOW90dmZzYWMwK2tnTm44UWpWanVMYUpQZWM4VG1YVGIzUFRZTncxL2JKYzZRZGZIdllLZmRvbitPbGVQWmlBMVZsaCt3QkIycFhRWVZ5ZUtiRERCa2s5NWJLKzJTek92czlXV29KdEllczlNMnhRcndzZlM1RVRnRjdGdnFHdFhYVkxwKzBoK0hFNWp0L05PWFQ5eVNFSXkyQmRNV254YjM2YWZkc0I5a2lCSUl2ck9hUHJnU2UzVkZyUHBTeVV5eFhpdlZvV2VPeE5TVHJsVExUWHJlZDRZcDBKd3VMcktlUFZlN1Y0cVM2OXFIbHJid0Nxc3JENVZpSkpYSGJZK0lQT01IV21IaWJlb3pQT280Y0xIa1dmQm4vSjV5dTZUbGpCNm1mUUJZOFFHT29lTTVNcWR0MThoTTZXMTdQSDFmdDVyNHhUQ0MxaWpwV0FtOW9EMFd0cTl2T1RiMGJBZnQraDlRRDhaeisxWmpabVQ3MjkyWWQ0ODg4T2NYcllWcmMzN1ROVjRlSmJ3ZzdGRDZaSnlFeWlDM3lEdGpkL0RuU29wTG4ra1hkZVlLcStYVE5yNU0rWkhUZmZiMTE1TTRobTlqSnpnMXE5Y1VZaDY3S2R4NzFwc0J1SmY1akhFejNmOExoYit2YU41ejZQamUveFhzMGkrdFlUWlo5N3U0dmMvZ1lpMkQ2MnIrWkY2NTkySXM5NjNxQTNRbzkxWnI3OWlGYkdWM0JzODV6cEkyOWJXZm5EN1hDYzJZRXNubGRYKzdhTFJISEdLcmQ5THBXSW1xSm1scjRRMjBIRGJMQnIzSHdTaTFWNU9wa3FYQ2REdmZBOGdoaXN3U3E5dzhDZTkrWXhaTzJlOUFwVHlDZFA1aURNajdjY3hhaDkzbFduZmJkSTdyaXg5cWRRYjMxUzhRZXRUWGlsalZVaTF4N2xrTFZvNjhHNGNDWlA1aVBVeUZYdkxMZURSWHY5WWl0Y1hVK1hmcjM3dG16RnFKRXdjdFdqVWZhWjk1VTh6ZmYxOGJaRHRxdFVQaDBHVHZ0SGZRdll6ZXhwOWZ4emp6YjJwdVBnLzNYZUluNmZheWg4NjhjVzQyc0ROYndYOXJlTTJ3djVpSTI1Ymw4ZzNQQTZPNUEwYnFzRitMY2JTOUN4Qlp6cUI0U3Q3MTlNQWNkNHROdnVWbm41QnlxOCs4NWVYMTI2UzJDalNGSHhvRk03Rm5zT21QbDFCdUkyZ1NwdGZFTnNvTVh2UDNLbzhsU0N4SDF6M0VRV0YvSGNXSi9PZnNlbmgrUG5Qa2FNMjZPZk9ZNXh4ei9yR09SNzh3Nkx1M2VIL1BpbERkdFQ3VktEUDhSRitTUHZ6ZmtIU0M1NkVOL3kyQzlqbGpFQzduMys2TWhnNXpIR1FJa1lvRVl4QXhBSXJyME5TQVpic2dVSEJhNDdHOHp1ZGRTbElaTUkxYVROR1FPMGdCei9XVzE0aEdKM3NzKytBV25DRE1PQWl6M2Zpb2ZEWG1kRXlMYTMrY2RUdFBJeDlVdElLTGxqTjl5a2hQeUVwTUlGWEpQTnRlem1MK2tPTU5NOVBJcFR1SXM0bkVxeGxnUXNZTm92VUVnVkh3Y2RiemtoQ3d4U2pFWG5mYmZ4ZDBrU0hGV3VjdFl6RXVyc3NyamF4ZkRPT05WZ3k3ZTVGNTF6V2ppQXhDM2tUc1NJeUFhOUFUd3NOUXUwT1NrZW0zSVg3MWlzWStYbUdERTQ3VGFNWW45L3JVVlNld3ZNY3JUaUJkNnpEZys4RXFlVnRqcWNjNTRpVytLc3poUEVUNnV5MjR0eW5DNmkxQUZaU3l1U0QvVjgvVkVKM25HY1dxK3lKOFQrd2hWK20vQWcxSU1PSlo3UE0xeDQzUm5FV3Q1VEhCNm1sbjZucUVRVTNDNjdLd2pjbm5SdVFzeG9WSEE0aFIvWG5ETVFwdTd6a0lSelNZcU5BVVdXdUtwblIyaXE4QlhRd0pGc3RzazgwVEJLYlM5S0xDQ0JLaTRmeklMYlFVTThtNk9aaTAwMG5hSUxjUjc3Tm1IekRUOERLcG1BTzJoNHFwaEFpbktSRkVSUlJnNEhqRkhXdWdid2VXNE1jeTlmcnd4alE3eDFLRWlDb3VwaDN0RUxRcWNrSGk2MWdiT0lqYjFRVEtKdEJkSUR4M1Q2T2JlVXR1ZmZEQkhHa0dSYUJvN1pCTEUrV0k0VzYvYUMrR1BzUGNScWkwTzFmdkEyczVlVFdPUklEWjltbEEvOGZXZjFkTWdETkp1NGMzajNHVkpNZGxYVDJEN09XeVBpUjUxWXE4UWMwTldrNzM3OUg2blI5TmdYaDdpM2Z6WVdMU1FybEZnSHdqYXg3OG1iTlpHL2ZqWGhJNURVSDR2ZVBYZExZQ05ucDVZaWFudE91TUV0cTEzYzBBR0MyZjZOR0ZhQWRXRXVPMzUwNFNTcldjUGRub1U1NzdSMmlQYS9hVkhIUldwczUxbnJIWjY4TGUveVI4aUd5aGcwUnFYREdvMm0yL3NmNlJsbWJnOTZmTnUvdVBHNWZlTmZWNjRlOUt1OWNhMkVmTjdVa1hvTjNhNjdQZmVtQ1RWMHJYOGxxUjR6N0RmaEVWUE9sR2p5VEdnWXBBQWlFbDlYdHFUUURQQVRPUXg5cHVscUNteVZVd1J6NXFTREFIR2NQckdNcDVHTEhnOFdiREZSVThDVXBZbk9KWDg4ditzdEZTTXZMSC9pT3N2c1gvbDk1VnhwZHBqaGFyVVZ5SVVNNGFSZ09lTlpRbEc1Vm9VTXc0aWh0TUtpcVlFMHVDRVN2TWY2ZXo5VktwWktLWVVNUCs4WmgrSXdJajNzdnoySkpobkJZd1BsYXl5OVRRbnhSa0hLYS9LZTArYTRaMEE5ZCtBQ1NSSjl1TVRxOGZ5QnlLS0dmOVR5R29RSGF0dTFwTmE0ak03bHUrand4UndGRTdxeVNRSksrNjI1MStON3FMNFI4UXlEaGk2M3ZQN0JaV0JWeVpKMGdtQTArWjFuOFEvY21uSS84T1VQekJHa3M0WWxlRm1FZGN2MDZuS2lHTWUvTXBCSWJRZDhlVFlSekg5OFFzMHR6SFBtcTBlSUVuRWNMTjkxL25EcGUzUHBRK25wZWlXSVpqdGF0QTBqMW13SE9pcmhmbnEvclhVKzdQWllQSFgwOEQ5UzFGYW56TWxxZXlRaG1sTWUzV3BkR1QzRXk0V2VIMDFkS3dHSmZFdjVkOFZrOVA0MGVteW4rbVY2VjZMVHJXWUZzM3orck9ybjQ1ZWNyS1MvWUFSKzVFUmpKTzY5RTN1S29yeUpuL1p2WUswMTc2N3Y5NTdEeUwrYjlJVUN0TFVlRHFPNFUyQ0puSEdtMlhDRXRMY2lFbm5qSU1BYmVQMWVoTFJpUGVrOXI5Q2podWt2NUhHTnpQbkZxQlpXUDlxb29zeGdiUFVVcjZCOVVyOGNtNXhlMUs5dzcxR1Bvemo3UVZaLytQMTgxOE9USXIvRzVjL2pVdjlqdyt0cW4zT0VpQmFjMWwwd3l5VFAvNHZBQUQvL3lJbkFOVk9HUUFB +kind: Secret +metadata: + annotations: + kots.io/app-slug: my-app + labels: + createdAt: "1" + kots.io/app-slug: my-app + kots.io/backup: velero + name: test-chart + owner: helm + status: deployed + version: "1" + name: sh.helm.release.v1.test-chart.v1 + namespace: helmns +type: helm.sh/release.v1 \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/test-config-configmap.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/test-config-configmap.yaml new file mode 100644 index 0000000000..5577babe0f --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/rendered/this-cluster/test-config-configmap.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +data: + configOptionHostname: my-app.somebigbank.com +kind: ConfigMap +metadata: + annotations: + kots.io/app-slug: my-app + labels: + kots.io/app-slug: my-app + kots.io/backup: velero + name: test-config \ No newline at end of file diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/config.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/config.yaml new file mode 100644 index 0000000000..f115c91567 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/config.yaml @@ -0,0 +1,19 @@ +apiVersion: kots.io/v1beta1 +kind: Config +metadata: + name: my-app +spec: + groups: + - name: setup + title: Setup + items: + - name: hostname + type: text + title: Hostname + help_text: | + Use this field to provide a hostname for your Example Application installation. + required: true + - name: helm + title: Include helm + type: text + default: "no" diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/subdir/configmap.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/subdir/configmap.yaml new file mode 100644 index 0000000000..fa4697178f --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/subdir/configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-config +data: + configOptionHostname: {{repl ConfigOption "hostname" }} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart-0.1.1.tgz b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart-0.1.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..50af594dde61c3d3c8fd961eef2e6a11ef45c1aa GIT binary patch literal 1893 zcmV-r2b%aFiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PI*>Z``;Q_A`IQsr|5R5NR~Nrg}5%Z0p8x3_D2?EEWNWIwLWr zNQH-*v9@S`dqGm8xp>lSx@m$%%?Dkm!*ls~Zj?iEiKw`BqceX^J6@}uuRF3V%Z?8Z z!#&Hg&3iUJIocT?9v$r;9cCv-_@Y%$>qtQPmI}2ByZsi*|xmqeEhv*OwWzPIs@V`nA)XI!;N|APeZnfO0A93O1P|IzsPG5){B*n@MN@>V&B z+aH2@=@cp3gV&WLkOUmwoxZ$GrpDIXIV@l*6?%em6pCAf8Ml&86cRWC6NH8nVF6M* z1D$C--?~xUA*GC23~AxawA$q`W=z(+#GC(kQBrg{TuiTw zyS7NE9Rt{dS2MI$7G7?J5cq)OCCn>B2t{w7jGtrbTIRWwfhW#kcemH!x>f2Hg+)g> z{Pc6kYYP#9Y}zXIV3HBqnG|>`L@+66cH5wkQ;7ug3SEU3IP`SDBOy>_T2*+wghlSK zV9-D1;B1S5(W%zPg&Z2d#;LblWP=tR+kX?Zp(d zaX{#R>!Q~sz-L>03Oq8B1SM*;USnuU>M}51U^DDB1BiveW7L@9bVEBocZ;I6(sgG> zJG^&;)>Hb6HEol_ewJk(;q7FCH+&+MbP_4z4p3OrES?iMy}S(17J2bXtM0}a_oGxu z9XYI5aJH>Jr7NR7!RGWELYu?5S0&)*CB!Osrdo1nFRs0_8tZa+w$GTr`a257&jX~lR^$0J8?L~gcR$0s`(bEkPJgg3W=?p03GX&@J6ZiQ^7)?T&HmW5m<6S%?w91P?o5p0u z6&aA)dp03?RketB>&S057!9ar(i&Z(b_8?jDp1ln)jPyOm8U?hsJ!@>QcJ%nsSlve zv``qBbG>HC%Cc5RYh4T*qm-FTT?Xz-YEQz84=si7wHKgKAQ89S(_p{F+63znL~B(C z6UzfOQ->CQSVH|n+B2=?a*ssQ24AlG_ZsVvaL4=4UdrCYk1f)#UBP(k3<<8JF1NaS zE%i-I`Q+0*K+W%0CbBH#VOyd*yMFV=NhN;?!EudNpmx4Cz_TpKj$|)`{7+LdZ3?_a zg~AydQ;jpqC#)E9KmE)YpH8Kgt_z>PcPaiZW2OHas`JQCe#JiUbN%1($;n3lceFpw z9{ayO3&W79&1&gv453fFD_uc49(xOE^3D(uziRyC2T=3G<%^FV5*Ov`(pQMkftt$gV zJJkzbF~twHro)$O@$2;fSODXPPoBOT<5Hs?XV{(ulec8%`<;vrJrP!hc>e&*Kq~G(~=VxzjE?&QTe|vU%b@lw_{fp=C-e=i( zAcS}l`q7#?Uzvp7=U!lUgVXgdy^DHpT%Z1gdoMos#)h^o52<&#A#rKlCBy2$#KAz{ zL2zBH8abLsJtBqJtW56yIm@!$O|cQf{2)Et5IX15p?wfo6YuTI$oiX^Yze8xkV}HI zDV2OMlOc{KT-=%I^wM`BIUIb}rME=r1NYmu>02 z#+5O5tD$Al7Z|r#d4;q88d{5w$bKoZ1E$xe__7KRr-acOMfiESz-Jws1h_4SbJl<0 zmp_YOtihPTyu@fw574BgZerpouMfvavDMt)T>n@4zqCSC%TgPQU!}De#^?V3A00gS z|9^OV^4R}Z_>x@OV2WO_PjfS^pw@^q+EG?xQg=4e|0C#kFbv$3*dPyWUB;4Qb(v;-ID&xxgtH6KtomdXP8D3V+Afu%DN frohqv=ZW%hJdVfldl~-@00960RrxUP03ZMWc=fEQ literal 0 HcmV?d00001 diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart.yaml new file mode 100644 index 0000000000..8dc7b76547 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/test-chart.yaml @@ -0,0 +1,20 @@ +apiVersion: kots.io/v1beta1 +kind: HelmChart +metadata: + name: test-chart +spec: + # exclude: 'repl{{ ConfigOptionEquals "helm" "no" }}' + # chart identifies a matching chart from a .tgz + chart: + name: test-chart + chartVersion: 0.1.1 + useHelmInstall: false + namespace: helmns + + # values are used in the customer environment, as a pre-render step + # these values will be supplied to helm template + values: {} + + # builder values provide a way to render the chart with all images + # and manifests. this is used in replicated to create airgap packages + builder: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/config.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/config.yaml new file mode 100644 index 0000000000..d70bc110be --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/config.yaml @@ -0,0 +1,12 @@ +apiVersion: kots.io/v1beta1 +kind: ConfigValues +metadata: + creationTimestamp: null + name: replicated-kots-app +spec: + values: + helm: + default: "no" + hostname: + value: my-app.somebigbank.com +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/installation.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/installation.yaml new file mode 100644 index 0000000000..ffa201a902 --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/installation.yaml @@ -0,0 +1,18 @@ +apiVersion: kots.io/v1beta1 +kind: Installation +metadata: + creationTimestamp: null + name: replicated-kots-app +spec: + channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 + channelName: My Channel + knownImages: + - image: quay.io/replicatedcom/qa-kots-3:alpine-3.6 + isPrivate: true + - image: quay.io/replicatedcom/qa-kots-1:alpine-3.5 + isPrivate: true + - image: alpine:3.4 + - image: alpine + - image: nginx:latest + - image: busybox +status: {} diff --git a/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/license.yaml b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/license.yaml new file mode 100644 index 0000000000..9fa3a14d7f --- /dev/null +++ b/pkg/tests/pull/cases/replicatedhelm/wantResults/upstream/userdata/license.yaml @@ -0,0 +1,49 @@ +apiVersion: kots.io/v1beta1 +kind: License +metadata: + creationTimestamp: null + name: testcustomer +spec: + appSlug: my-app + channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 + channelName: My Channel + customerName: Test Customer + endpoint: https://replicated.app + entitlements: + bool_field: + title: Bool Field + value: true + valueType: Boolean + expires_at: + description: License Expiration + title: Expiration + value: "2030-07-27T00:00:00Z" + valueType: String + hidden_field: + isHidden: true + title: Hidden Field + value: this is secret + valueType: String + int_field: + title: Int Field + value: 123 + valueType: Integer + string_field: + title: StringField + value: single line text + valueType: String + text_field: + title: Text Field + value: |- + multi + line + text + valueType: Text + isAirgapSupported: true + isGitOpsSupported: true + isSnapshotSupported: true + licenseID: 1vusOokxAVp1tkRGuyxnF23PJcq + licenseSequence: 7 + licenseType: prod + signature: eyJsaWNlbnNlRGF0YSI6ImV5SmhjR2xXWlhKemFXOXVJam9pYTI5MGN5NXBieTkyTVdKbGRHRXhJaXdpYTJsdVpDSTZJa3hwWTJWdWMyVWlMQ0p0WlhSaFpHRjBZU0k2ZXlKdVlXMWxJam9pZEdWemRHTjFjM1J2YldWeUluMHNJbk53WldNaU9uc2liR2xqWlc1elpVbEVJam9pTVhaMWMwOXZhM2hCVm5BeGRHdFNSM1Y1ZUc1R01qTlFTbU54SWl3aWJHbGpaVzV6WlZSNWNHVWlPaUp3Y205a0lpd2lZM1Z6ZEc5dFpYSk9ZVzFsSWpvaVZHVnpkQ0JEZFhOMGIyMWxjaUlzSW1Gd2NGTnNkV2NpT2lKdGVTMWhjSEFpTENKamFHRnVibVZzU1VRaU9pSXhkblZ6U1ZsYVRFRldlRTFITm5FM05qQlBTbTFTUzJvMWFUVWlMQ0pqYUdGdWJtVnNUbUZ0WlNJNklrMTVJRU5vWVc1dVpXd2lMQ0pzYVdObGJuTmxVMlZ4ZFdWdVkyVWlPamNzSW1WdVpIQnZhVzUwSWpvaWFIUjBjSE02THk5eVpYQnNhV05oZEdWa0xtRndjQ0lzSW1WdWRHbDBiR1Z0Wlc1MGN5STZleUppYjI5c1gyWnBaV3hrSWpwN0luUnBkR3hsSWpvaVFtOXZiQ0JHYVdWc1pDSXNJblpoYkhWbElqcDBjblZsTENKMllXeDFaVlI1Y0dVaU9pSkNiMjlzWldGdUluMHNJbVY0Y0dseVpYTmZZWFFpT25zaWRHbDBiR1VpT2lKRmVIQnBjbUYwYVc5dUlpd2laR1Z6WTNKcGNIUnBiMjRpT2lKTWFXTmxibk5sSUVWNGNHbHlZWFJwYjI0aUxDSjJZV3gxWlNJNklqSXdNekF0TURjdE1qZFVNREE2TURBNk1EQmFJaXdpZG1Gc2RXVlVlWEJsSWpvaVUzUnlhVzVuSW4wc0ltaHBaR1JsYmw5bWFXVnNaQ0k2ZXlKMGFYUnNaU0k2SWtocFpHUmxiaUJHYVdWc1pDSXNJblpoYkhWbElqb2lkR2hwY3lCcGN5QnpaV055WlhRaUxDSjJZV3gxWlZSNWNHVWlPaUpUZEhKcGJtY2lMQ0pwYzBocFpHUmxiaUk2ZEhKMVpYMHNJbWx1ZEY5bWFXVnNaQ0k2ZXlKMGFYUnNaU0k2SWtsdWRDQkdhV1ZzWkNJc0luWmhiSFZsSWpveE1qTXNJblpoYkhWbFZIbHdaU0k2SWtsdWRHVm5aWElpZlN3aWMzUnlhVzVuWDJacFpXeGtJanA3SW5ScGRHeGxJam9pVTNSeWFXNW5SbWxsYkdRaUxDSjJZV3gxWlNJNkluTnBibWRzWlNCc2FXNWxJSFJsZUhRaUxDSjJZV3gxWlZSNWNHVWlPaUpUZEhKcGJtY2lmU3dpZEdWNGRGOW1hV1ZzWkNJNmV5SjBhWFJzWlNJNklsUmxlSFFnUm1sbGJHUWlMQ0oyWVd4MVpTSTZJbTExYkhScFhHNXNhVzVsWEc1MFpYaDBJaXdpZG1Gc2RXVlVlWEJsSWpvaVZHVjRkQ0o5ZlN3aWFYTkJhWEpuWVhCVGRYQndiM0owWldRaU9uUnlkV1VzSW1selIybDBUM0J6VTNWd2NHOXlkR1ZrSWpwMGNuVmxMQ0pwYzFOdVlYQnphRzkwVTNWd2NHOXlkR1ZrSWpwMGNuVmxmWDA9IiwiaW5uZXJTaWduYXR1cmUiOiJleUpzYVdObGJuTmxVMmxuYm1GMGRYSmxJam9pYUhneE1XTXZUR1ozUTNoVE5YRmtRWEJGU1hGdVRrMU9NMHBLYTJzNFZHZFhSVVpzVDFKVlJ6UjJjR1YzZEZoV1YzbG1lamRZY0hBd1ExazJZamRyUVRSS2N6TklhR3d3YkZJMFdUQTFMemN2UVVkQ2FEZFZNSGczUkhaTVozUXpVM00wYm5GTFZTdFhXRXBTVHpKWVFVRnZSME4xZFRWR1RGcHJRVWhYY1RSUVFtMXphSFY2Y1ZsdmNucHhlbGhGWVZWVlpFUlVkVXhDTW1nNWFIZ3dXRWhQUmxwUk16bHVkbTlPUjJaT2R5OTRTVmRaZEhSUGRYZHZhMncyTVZsb1JVeFZlRmQxU1ZSRmMwTlVhM2xtTVRNd09IazVSbFJzWlRKeVYyZEVlSEZNYTBSUFNXVXlPRWwzUzJSQkwySXdWVUl5VEZGbVRWcHdWemwyUTNCSkwybHlWek5uYmpaeU5WWjNWMjB2U1dweWJtNDNSelJrVmpadVYzcFRkMGhQUTJSdWEwMTRNRXQ1VVVOa0wxQjFaWEpUYjNSdVEwOXRTMDEzWlRSTGJqaERkMU5YVVRRNGRURkRNbTFpV1VzeGRYTlpOM1YzUFQwaUxDSndkV0pzYVdOTFpYa2lPaUl0TFMwdExVSkZSMGxPSUZCVlFreEpReUJMUlZrdExTMHRMVnh1VFVsSlFrbHFRVTVDWjJ0eGFHdHBSemwzTUVKQlVVVkdRVUZQUTBGUk9FRk5TVWxDUTJkTFEwRlJSVUZ6TkhKdlVIcDFhV1JNZVhOMmIxWTJkemxhTkZ4dVdHRmliME5tWTJNeGFHZFZhQ3N3V1VkS2NFNURSVXhyTjBaTFF5OTJhemR6ZERsR05tY3dUMjlrU0VSbGVYZFJXa2hLZFU1TVpsUnNRbEJHUTJOaU5seHVObTlzVEZOeWNGQTRjbFUzU0d4SGJsRkVSMFJNYVhkS1EyaGtSRGRVVUdSM2FXdHBkMHRGY201aldqaEdaalZsU25vd2RETmlUWFpyVDJaVVluSkJiRnh1WWtGQ1kwbzVNVmxVT1hKdVVXOXFkVWN4UldKUVRqaEZWblI2TWxZNE5IZHViR2Q0TUhCd2JEVjRPSFpOYlhwcE1ISnVibEZVV1VGamJ6WnFhMnBJTTF4dVRuTlVkWE4xUzFkdlJGUjVNWE5yZGtSUk9IbEJZV0ptWTNNME4zWnNRazAwU0RGT1JFNHZSSFJhWWxZdllubDJia0o2YkM4eFZrVnpURmRqWlZWcFRGeHVSWEYxT0VkeWF5dFFVRGQyUkdSd2JFUjNjWFpQV2t4RmRYazNkamhuUm01U09WUlVSV3ByTlVvNWRuWlVTR2RtU25VemVubEVPR2xLWTBSRE5YcHFPVnh1YjFGSlJFRlJRVUpjYmkwdExTMHRSVTVFSUZCVlFreEpReUJMUlZrdExTMHRMVnh1SWl3aWEyVjVVMmxuYm1GMGRYSmxJam9pWlhsS2VtRlhaSFZaV0ZJeFkyMVZhVTlwU2pCUldIQjJXVE5LVms1NmFGaFNSMlJzVVRKb2NtTklXa1ZVVlRsRldqQktXVTFGUmtaVFJFNUZVMGhLYkUxclRUTkxNSEJFVkROR2VGTnROVVJVVlRWVlltMDFiVnBGUm5sWldIQjZaRVJqTVZaSGFFeFBXRUpVVWtacmRrd3diek5aTUZaSlVteFdWRXd5T1VoV1JXeHNWa1ZPTUZSSE1WWlJNR04zVkd4R2JGa3pTblJUUm1zMFZVWk9hMVpWU2pCVU1WbDNZbXQwY0ZSclZuQmpia0poVFZjNWFtSldiSEZaYTNob1UyeHNWV0pGUmtWWGJVWnZWakZLVUZkcWJGSmhXRVp1V2xkb1EyRnVRak5TUjNNd1lWWkpOVTVXVmxkV1ZUVnlUMGhLYjFsVlRYbGhiVGcwVjBkYWVGbHFWbFppYlhoeFpFWkZkMDU1Y3pCaFZsSkpWRVpPTm1WRk1IcGxWWFJ2VFVaR1ZtRXdWVFJSVnpsSFVsaEtVRTFZUmxCU01WcFJVMVJDTmxsV2FIcFdWWEJ0WTBSU2JFMVVRazlPVjNSU1ZucFdUMU5XWTNaU1ZYUkZVMGhzYlU5VmJGaGtNMUl3WTFWc1lXTlhSakJTYTA1RVlVWmtjbUo2VmtSU00wSllUREkxUmsxWVl6SmxWM1JKVlZoQk1sVXhTbEppU0Zwd1VrVXdNRlpFVWt0VU1rWnNVVmQwYzFSV1VrMVVWV055V1RCYVRHSXpaRTlUVm05NVlraE9SR1JzVG5aUmFrWmFaVmRPVGxOVlNteGFiRXB1Wld0U2RVMHhSVGxRVTBselNXMWtjMkl5U21oaVJYUnNaVlZzYTBscWIybFpiVkpzV2xSVk1rNVVXWGRaTWxwcFRrUk9hazlYU1hsUFIwcHRUMVJvYkZsWFRtaGFiVVV5VGtSWmFXWlJQVDBpZlE9PSJ9 +status: {} diff --git a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-1/kustomization.yaml b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-1/kustomization.yaml index e8289ac0c9..9de2f19995 100644 --- a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-1/kustomization.yaml +++ b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-1/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: alpine newName: fake-docker-proxy/alpine - name: docker.io/library/alpine @@ -28,6 +20,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-2/kustomization.yaml b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-2/kustomization.yaml index 3637f18303..4c450255c8 100644 --- a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-2/kustomization.yaml +++ b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-release-2/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: alpine newName: fake-docker-proxy/alpine - name: docker.io/library/alpine @@ -28,6 +20,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-variation-0/kustomization.yaml b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-variation-0/kustomization.yaml index f39acdc692..5c48438146 100644 --- a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-variation-0/kustomization.yaml +++ b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/charts/test-chart-variation-0/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: alpine newName: fake-docker-proxy/alpine - name: docker.io/library/alpine @@ -28,6 +20,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/kustomization.yaml b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/kustomization.yaml index f6386398b7..bb6f5b2615 100644 --- a/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/kustomization.yaml +++ b/pkg/tests/pull/cases/samechartvariations/wantResults/overlays/midstream/kustomization.yaml @@ -3,31 +3,6 @@ bases: - ../../base commonAnnotations: kots.io/app-slug: my-app -images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx -- name: alpine - newName: fake-docker-proxy/alpine -- name: docker.io/library/alpine - newName: fake-docker-proxy/alpine -- name: library/alpine - newName: fake-docker-proxy/alpine -- name: docker.io/alpine - newName: fake-docker-proxy/alpine -- name: busybox - newName: fake-docker-proxy/busybox -- name: docker.io/library/busybox - newName: fake-docker-proxy/busybox -- name: library/busybox - newName: fake-docker-proxy/busybox -- name: docker.io/busybox - newName: fake-docker-proxy/busybox kind: Kustomization resources: - secret.yaml diff --git a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml index fb0c49569f..449480618e 100644 --- a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml +++ b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml index 6cd227ebc8..ccc25e724f 100644 --- a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml +++ b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml index b9a23fe71a..a9a357d4d8 100644 --- a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml +++ b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-3/kustomization.yaml b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-3/kustomization.yaml index 68fa4326b3..fafe2e9bb4 100644 --- a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-3/kustomization.yaml +++ b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/charts/subchart-3/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/kustomization.yaml b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/kustomization.yaml index 815db3cba1..e72f9990a3 100644 --- a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/kustomization.yaml +++ b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/charts/chart/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/kustomization.yaml b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/kustomization.yaml index 1a484d0439..bb6f5b2615 100644 --- a/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/kustomization.yaml +++ b/pkg/tests/pull/cases/subchart-alias/wantResults/overlays/midstream/kustomization.yaml @@ -3,23 +3,6 @@ bases: - ../../base commonAnnotations: kots.io/app-slug: my-app -images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx -- name: busybox - newName: fake-docker-proxy/busybox -- name: docker.io/library/busybox - newName: fake-docker-proxy/busybox -- name: library/busybox - newName: fake-docker-proxy/busybox -- name: docker.io/busybox - newName: fake-docker-proxy/busybox kind: Kustomization resources: - secret.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml index fb0c49569f..449480618e 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml index 6cd227ebc8..ccc25e724f 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml index b9a23fe71a..a9a357d4d8 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/kustomization.yaml index 815db3cba1..e72f9990a3 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/kustomization.yaml @@ -4,14 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -20,6 +12,14 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: nginx + newName: fake-docker-proxy/nginx +- name: docker.io/library/nginx + newName: fake-docker-proxy/nginx +- name: library/nginx + newName: fake-docker-proxy/nginx +- name: docker.io/nginx + newName: fake-docker-proxy/nginx kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/charts/fluent-bit/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/charts/fluent-bit/kustomization.yaml index d1cc30c6a5..5ed1074eeb 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/charts/fluent-bit/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/charts/fluent-bit/kustomization.yaml @@ -4,8 +4,6 @@ bases: commonAnnotations: kots.io/app-slug: my-app images: -- name: cr.fluentbit.io/fluent/fluent-bit - newName: fake-docker-proxy/fluent-bit - name: busybox newName: fake-docker-proxy/busybox - name: docker.io/library/busybox @@ -14,6 +12,8 @@ images: newName: fake-docker-proxy/busybox - name: docker.io/busybox newName: fake-docker-proxy/busybox +- name: cr.fluentbit.io/fluent/fluent-bit + newName: fake-docker-proxy/fluent-bit kind: Kustomization patchesStrategicMerge: - pullsecrets.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/kustomization.yaml index 80a7e2d5cc..b9de558891 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/fluent-bit/kustomization.yaml @@ -3,17 +3,6 @@ bases: - ../../../../base/charts/fluent-bit commonAnnotations: kots.io/app-slug: my-app -images: -- name: cr.fluentbit.io/fluent/fluent-bit - newName: fake-docker-proxy/fluent-bit -- name: busybox - newName: fake-docker-proxy/busybox -- name: docker.io/library/busybox - newName: fake-docker-proxy/busybox -- name: library/busybox - newName: fake-docker-proxy/busybox -- name: docker.io/busybox - newName: fake-docker-proxy/busybox kind: Kustomization resources: - secret.yaml diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/kustomization.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/kustomization.yaml index 138599e690..bb6f5b2615 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/kustomization.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/kustomization.yaml @@ -3,25 +3,6 @@ bases: - ../../base commonAnnotations: kots.io/app-slug: my-app -images: -- name: nginx - newName: fake-docker-proxy/nginx -- name: docker.io/library/nginx - newName: fake-docker-proxy/nginx -- name: library/nginx - newName: fake-docker-proxy/nginx -- name: docker.io/nginx - newName: fake-docker-proxy/nginx -- name: busybox - newName: fake-docker-proxy/busybox -- name: docker.io/library/busybox - newName: fake-docker-proxy/busybox -- name: library/busybox - newName: fake-docker-proxy/busybox -- name: docker.io/busybox - newName: fake-docker-proxy/busybox -- name: cr.fluentbit.io/fluent/fluent-bit - newName: fake-docker-proxy/fluent-bit kind: Kustomization resources: - secret.yaml diff --git a/pkg/upstream/push_images.go b/pkg/upstream/push_images.go deleted file mode 100644 index 6f1902c587..0000000000 --- a/pkg/upstream/push_images.go +++ /dev/null @@ -1,129 +0,0 @@ -package upstream - -import ( - "io" - "time" - - "github.com/pkg/errors" - registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" - "github.com/replicatedhq/kots/pkg/imageutil" - "github.com/replicatedhq/kots/pkg/kotsadm" - kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types" - "github.com/replicatedhq/kots/pkg/logger" - kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" - kustomizetypes "sigs.k8s.io/kustomize/api/types" -) - -type ProcessAirgapImagesOptions struct { - RootDir string - AirgapRoot string - AirgapBundle string - CreateAppDir bool - PushImages bool - UseKnownImages bool - KnownImages []kustomizetypes.Image - Log *logger.CLILogger - ReplicatedRegistry registrytypes.RegistryOptions - ReportWriter io.Writer - DestinationRegistry registrytypes.RegistryOptions -} - -type ProcessAirgapImagesResult struct { - KustomizeImages []kustomizetypes.Image - KnownImages []kotsv1beta1.InstallationImage -} - -func ProcessAirgapImages(options ProcessAirgapImagesOptions) (*ProcessAirgapImagesResult, error) { - pushOpts := kotsadmtypes.PushImagesOptions{ - Registry: options.DestinationRegistry, - Log: options.Log, - ProgressWriter: options.ReportWriter, - LogForUI: true, - } - - var foundImages []kustomizetypes.Image - if options.UseKnownImages { - foundImages = options.KnownImages - } else { - if !options.PushImages { - if options.AirgapBundle != "" { - images, err := kotsadm.GetImagesFromBundle(options.AirgapBundle, pushOpts) - if err != nil { - return nil, errors.Wrap(err, "failed to push images") - } - foundImages = images - } else { - // TODO: Implement GetImagesFromPath - return nil, errors.New("GetImagesFromPath is not implemented") - } - } else { - if options.AirgapBundle != "" { - images, err := kotsadm.TagAndPushAppImagesFromBundle(options.AirgapBundle, pushOpts) - if err != nil { - return nil, errors.Wrap(err, "failed to push images from bundle") - } - foundImages = images - } else { - images, err := kotsadm.TagAndPushAppImagesFromPath(options.AirgapRoot, pushOpts) - if err != nil { - return nil, errors.Wrap(err, "failed to push images from dir") - } - foundImages = images - } - } - } - - withAltNames := make([]kustomizetypes.Image, 0) - for _, i := range foundImages { - altNames, err := imageutil.BuildImageAltNames(i) - if err != nil { - return nil, errors.Wrap(err, "failed to build image alt names") - } - withAltNames = append(withAltNames, altNames...) - } - - result := &ProcessAirgapImagesResult{ - KustomizeImages: withAltNames, - // This list is slightly different from the list we get from app specs because of alternative names, - // but it still works because after rewriting image names with private registry, the lists become the same. - KnownImages: makeInstallationImages(withAltNames), - } - return result, nil -} - -type ProgressReport struct { - // set to "progressReport" - Type string `json:"type"` - // the same progress text that used to be sent in unstructured message - CompatibilityMessage string `json:"compatibilityMessage"` - // all images found in archive - Images []ProgressImage `json:"images"` -} - -type ProgressImage struct { - // image name and tag, "nginx:latest" - DisplayName string `json:"displayName"` - // image upload status: queued, uploading, uploaded, failed - Status string `json:"status"` - // error string set when status is failed - Error string `json:"error"` - // amount currently uploaded (currently number of layers) - Current int64 `json:"current"` - // total amount that needs to be uploaded (currently number of layers) - Total int64 `json:"total"` - // time when image started uploading - StartTime time.Time `json:"startTime"` - // time when image finished uploading - EndTime time.Time `json:"endTime"` -} - -func makeInstallationImages(images []kustomizetypes.Image) []kotsv1beta1.InstallationImage { - result := make([]kotsv1beta1.InstallationImage, 0) - for _, i := range images { - result = append(result, kotsv1beta1.InstallationImage{ - Image: imageutil.SrcImageFromKustomizeImage(i), - IsPrivate: true, - }) - } - return result -} diff --git a/pkg/upstream/upgrade.go b/pkg/upstream/upgrade.go index b620df3a8d..1f8ea0b08b 100644 --- a/pkg/upstream/upgrade.go +++ b/pkg/upstream/upgrade.go @@ -15,12 +15,12 @@ import ( "github.com/pkg/errors" "github.com/replicatedhq/kots/pkg/auth" registrytypes "github.com/replicatedhq/kots/pkg/docker/registry/types" + "github.com/replicatedhq/kots/pkg/image" + imagetypes "github.com/replicatedhq/kots/pkg/image/types" "github.com/replicatedhq/kots/pkg/k8sutil" - "github.com/replicatedhq/kots/pkg/kotsadm" kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types" "github.com/replicatedhq/kots/pkg/logger" "github.com/replicatedhq/kots/pkg/util" - kustomizetypes "sigs.k8s.io/kustomize/api/types" ) type UpgradeResponse struct { @@ -58,7 +58,6 @@ func Upgrade(appSlug string, options UpgradeOptions) (*UpgradeResponse, error) { } airgapPath := "" - var images []kustomizetypes.Image if options.AirgapBundle != "" { airgapRootDir, err := ioutil.TempDir("", "kotsadm-airgap") if err != nil { @@ -68,12 +67,12 @@ func Upgrade(appSlug string, options UpgradeOptions) (*UpgradeResponse, error) { airgapPath = airgapRootDir - err = kotsadm.ExtractAppAirgapArchive(options.AirgapBundle, airgapRootDir, options.DisableImagePush, os.Stdout) + err = image.ExtractAppAirgapArchive(options.AirgapBundle, airgapRootDir, options.DisableImagePush, os.Stdout) if err != nil { return nil, errors.Wrap(err, "failed to extract images") } - pushOptions := kotsadmtypes.PushImagesOptions{ + pushOptions := imagetypes.PushImagesOptions{ Registry: registrytypes.RegistryOptions{ Endpoint: options.RegistryConfig.OverrideRegistry, Namespace: options.RegistryConfig.OverrideNamespace, @@ -84,12 +83,7 @@ func Upgrade(appSlug string, options UpgradeOptions) (*UpgradeResponse, error) { } if options.DisableImagePush { - images, err = kotsadm.GetImagesFromBundle(options.AirgapBundle, pushOptions) - if err != nil { - return nil, errors.Wrap(err, "failed to get images from bundle") - } - } else { - images, err = kotsadm.TagAndPushAppImagesFromPath(airgapRootDir, pushOptions) + err := image.TagAndPushAppImagesFromPath(airgapRootDir, pushOptions) if err != nil { return nil, errors.Wrap(err, "failed to tag and push app images from path") } @@ -118,20 +112,7 @@ func Upgrade(appSlug string, options UpgradeOptions) (*UpgradeResponse, error) { return nil, errors.Wrap(err, "failed to create part from app.tar.gz") } - b, err := json.Marshal(images) - if err != nil { - return nil, errors.Wrap(err, "failed to marshal images data") - } - err = ioutil.WriteFile(filepath.Join(airgapPath, "images.json"), b, 0644) - if err != nil { - return nil, errors.Wrap(err, "failed to write images data") - } - - if err := createPartFromFile(writer, airgapPath, "images.json"); err != nil { - return nil, errors.Wrap(err, "failed to create part from images.json") - } - - err = writer.Close() + err := writer.Close() if err != nil { return nil, errors.Wrap(err, "failed to close multi-part writer") } From c11210a96b660643d45b4464f429a3eadeecf89a Mon Sep 17 00:00:00 2001 From: Salah Al Saleh Date: Fri, 19 Jan 2024 19:06:55 +0000 Subject: [PATCH 2/4] dest registry always exists --- pkg/apparchive/helm-v1beta2.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pkg/apparchive/helm-v1beta2.go b/pkg/apparchive/helm-v1beta2.go index 046231c1b2..2ed514929d 100644 --- a/pkg/apparchive/helm-v1beta2.go +++ b/pkg/apparchive/helm-v1beta2.go @@ -317,14 +317,11 @@ func processV1Beta2HelmChartImages(opts WriteV1Beta2HelmChartsOptions, helmChart dockerHubRegistryCreds, _ = registry.GetCredentialsForRegistryFromConfigJSON(dockerhubSecret.Data[".dockerconfigjson"], registry.DockerHubRegistryName) } - var destRegistry *dockerregistrytypes.RegistryOptions - if opts.ProcessImageOptions.RewriteImages { - destRegistry = &dockerregistrytypes.RegistryOptions{ - Endpoint: opts.ProcessImageOptions.RegistrySettings.Hostname, - Namespace: opts.ProcessImageOptions.RegistrySettings.Namespace, - Username: opts.ProcessImageOptions.RegistrySettings.Username, - Password: opts.ProcessImageOptions.RegistrySettings.Password, - } + destRegistry := &dockerregistrytypes.RegistryOptions{ + Endpoint: opts.ProcessImageOptions.RegistrySettings.Hostname, + Namespace: opts.ProcessImageOptions.RegistrySettings.Namespace, + Username: opts.ProcessImageOptions.RegistrySettings.Username, + Password: opts.ProcessImageOptions.RegistrySettings.Password, } baseImages, err := image.FindImagesInDir(templatedOutputDir) From 53a673b5d25db697282ccd36afe85b7ab3c59c0a Mon Sep 17 00:00:00 2001 From: Salah Al Saleh Date: Fri, 19 Jan 2024 19:16:04 +0000 Subject: [PATCH 3/4] remove todo --- pkg/midstream/write.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/midstream/write.go b/pkg/midstream/write.go index 2839d7ce50..89d82be208 100644 --- a/pkg/midstream/write.go +++ b/pkg/midstream/write.go @@ -256,7 +256,6 @@ func ProcessAirgapImages(options image.ProcessImageOptions, baseImages []string, processAirgapImageOptions.ReplicatedRegistry.Password = license.Spec.LicenseID } - // TODO NOW: move this to base package result, err := base.ProcessAirgapImages(processAirgapImageOptions) if err != nil { return nil, errors.Wrap(err, "failed to process airgap images") From e2efa8914820a5393909b0992bbc13311bed6b33 Mon Sep 17 00:00:00 2001 From: Salah Al Saleh Date: Fri, 19 Jan 2024 19:18:43 +0000 Subject: [PATCH 4/4] fix condition --- pkg/upstream/upgrade.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/upstream/upgrade.go b/pkg/upstream/upgrade.go index 1f8ea0b08b..3ffd35c713 100644 --- a/pkg/upstream/upgrade.go +++ b/pkg/upstream/upgrade.go @@ -82,7 +82,7 @@ func Upgrade(appSlug string, options UpgradeOptions) (*UpgradeResponse, error) { ProgressWriter: os.Stdout, } - if options.DisableImagePush { + if !options.DisableImagePush { err := image.TagAndPushAppImagesFromPath(airgapRootDir, pushOptions) if err != nil { return nil, errors.Wrap(err, "failed to tag and push app images from path")