From c4efeb3955ccff6c2b0eeceb618ddaa45345031f Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Mon, 15 Apr 2024 14:50:30 +0000 Subject: [PATCH 1/9] pass embedded cluster artifacts in upstream upgrade --- go.mod | 2 +- go.sum | 2 ++ pkg/embeddedcluster/util.go | 20 ++++++++++++++++++++ pkg/pull/pull.go | 1 + pkg/rewrite/rewrite.go | 1 + pkg/upstream/fetch.go | 21 +++++++++++++++++++++ pkg/upstream/replicated.go | 8 ++++++-- pkg/upstream/types/types.go | 2 ++ pkg/upstream/write.go | 1 + 9 files changed, 55 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e612722fda..28e59c3bd2 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 github.com/replicatedhq/embedded-cluster-kinds v1.1.2 - github.com/replicatedhq/kotskinds v0.0.0-20240326213823-6a0ed11e7397 + github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70 github.com/replicatedhq/kurlkinds v1.5.0 github.com/replicatedhq/troubleshoot v0.87.0 github.com/replicatedhq/yaml/v3 v3.0.0-beta5-replicatedhq diff --git a/go.sum b/go.sum index 90a0ec97fb..7de3e6e0e1 100644 --- a/go.sum +++ b/go.sum @@ -1310,6 +1310,8 @@ github.com/replicatedhq/embedded-cluster-kinds v1.1.2 h1:2ITzcUzh5uh0fsnfZsVHvkw github.com/replicatedhq/embedded-cluster-kinds v1.1.2/go.mod h1:LheSDOgMngMRAbwAj0sVZUVv2ciKIVR2bYTMeOBGwlg= github.com/replicatedhq/kotskinds v0.0.0-20240326213823-6a0ed11e7397 h1:JNuBcFH9D3Osyi+1QUwdvaAklEd6HXznqZDfpWlr73M= github.com/replicatedhq/kotskinds v0.0.0-20240326213823-6a0ed11e7397/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= +github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70 h1:55fMr60YysSf+ac5zeW+xTIIJ8edUpAjorQyFn0iP2c= +github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= github.com/replicatedhq/kurlkinds v1.5.0 h1:zZ0PKNeh4kXvSzVGkn62DKTo314GxhXg1TSB3azURMc= github.com/replicatedhq/kurlkinds v1.5.0/go.mod h1:rUpBMdC81IhmJNCWMU/uRsMETv9P0xFoMvdSP/TAr5A= github.com/replicatedhq/termui/v3 v3.1.1-0.20200811145416-f40076d26851 h1:eRlNDHxGfVkPCRXbA4BfQJvt5DHjFiTtWy3R/t4djyY= diff --git a/pkg/embeddedcluster/util.go b/pkg/embeddedcluster/util.go index 240581da92..f249fd6c03 100644 --- a/pkg/embeddedcluster/util.go +++ b/pkg/embeddedcluster/util.go @@ -5,11 +5,13 @@ import ( "context" "encoding/json" "fmt" + "path/filepath" "regexp" "sort" "time" embeddedclusterv1beta1 "github.com/replicatedhq/embedded-cluster-kinds/apis/v1beta1" + "github.com/replicatedhq/kots/pkg/imageutil" "github.com/replicatedhq/kots/pkg/k8sutil" "github.com/replicatedhq/kots/pkg/logger" kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" @@ -171,3 +173,21 @@ func startClusterUpgrade(ctx context.Context, newcfg embeddedclusterv1beta1.Conf } return nil } + +type EmbeddedClusterArtifactOCIPathOptions struct { + RegistryHost string + RegistryNamespace string + ChannelID string + UpdateCursor string + VersionLabel string +} + +// EmbeddedClusterArtifactOCIPath returns the OCI path for an embedded cluster artifact given +// the artifact filename and details about the configured registry and channel release. +func EmbeddedClusterArtifactOCIPath(filename string, opts EmbeddedClusterArtifactOCIPathOptions) string { + name := filepath.Base(filename) + repository := filepath.Join("embedded-cluster", imageutil.SanitizeRepo(name)) + tag := imageutil.SanitizeTag(fmt.Sprintf("%s-%s-%s", opts.ChannelID, opts.UpdateCursor, opts.VersionLabel)) + artifact := fmt.Sprintf("%s:%s", filepath.Join(opts.RegistryHost, opts.RegistryNamespace, repository), tag) + return artifact +} diff --git a/pkg/pull/pull.go b/pkg/pull/pull.go index 7ccb73fd20..7660405119 100644 --- a/pkg/pull/pull.go +++ b/pkg/pull/pull.go @@ -216,6 +216,7 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { fetchOptions.CurrentVersionIsRequired = installation.Spec.IsRequired fetchOptions.CurrentReplicatedRegistryDomain = installation.Spec.ReplicatedRegistryDomain fetchOptions.CurrentReplicatedProxyDomain = installation.Spec.ReplicatedProxyDomain + fetchOptions.CurrentEmbeddedClusterArtifacts = installation.Spec.EmbeddedClusterArtifacts } if pullOptions.AirgapRoot != "" { diff --git a/pkg/rewrite/rewrite.go b/pkg/rewrite/rewrite.go index b49aefc535..95dde7e9cd 100644 --- a/pkg/rewrite/rewrite.go +++ b/pkg/rewrite/rewrite.go @@ -77,6 +77,7 @@ func Rewrite(rewriteOptions RewriteOptions) error { CurrentReplicatedRegistryDomain: rewriteOptions.Installation.Spec.ReplicatedRegistryDomain, CurrentReplicatedProxyDomain: rewriteOptions.Installation.Spec.ReplicatedProxyDomain, CurrentReplicatedChartNames: rewriteOptions.Installation.Spec.ReplicatedChartNames, + CurrentEmbeddedClusterArtifacts: rewriteOptions.Installation.Spec.EmbeddedClusterArtifacts, EncryptionKey: rewriteOptions.Installation.Spec.EncryptionKey, License: rewriteOptions.License, AppSequence: rewriteOptions.AppSequence, diff --git a/pkg/upstream/fetch.go b/pkg/upstream/fetch.go index b7663280f8..92a51dc5f0 100644 --- a/pkg/upstream/fetch.go +++ b/pkg/upstream/fetch.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" "github.com/replicatedhq/kots/pkg/crypto" + "github.com/replicatedhq/kots/pkg/embeddedcluster" "github.com/replicatedhq/kots/pkg/replicatedapp" "github.com/replicatedhq/kots/pkg/upstream/types" "github.com/replicatedhq/kots/pkg/util" @@ -50,6 +51,7 @@ func downloadUpstream(upstreamURI string, fetchOptions *types.FetchOptions) (*ty pickReplicatedRegistryDomain(fetchOptions), pickReplicatedProxyDomain(fetchOptions), pickReplicatedChartNames(fetchOptions), + pickEmbeddedClusterArtifacts(fetchOptions), fetchOptions.AppSlug, fetchOptions.AppSequence, fetchOptions.Airgap != nil, @@ -118,3 +120,22 @@ func pickReplicatedChartNames(fetchOptions *types.FetchOptions) []string { } return fetchOptions.CurrentReplicatedChartNames } + +func pickEmbeddedClusterArtifacts(fetchOptions *types.FetchOptions) []string { + if fetchOptions.Airgap != nil { + opts := embeddedcluster.EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: fetchOptions.LocalRegistry.Hostname, + RegistryNamespace: fetchOptions.LocalRegistry.Namespace, + ChannelID: fetchOptions.Airgap.Spec.ChannelID, + UpdateCursor: fetchOptions.Airgap.Spec.UpdateCursor, + VersionLabel: fetchOptions.Airgap.Spec.VersionLabel, + } + return []string{ + embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Binary, opts), + embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Charts, opts), + embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Images, opts), + embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Metadata, opts), + } + } + return fetchOptions.CurrentEmbeddedClusterArtifacts +} diff --git a/pkg/upstream/replicated.go b/pkg/upstream/replicated.go index 4be64998eb..ec0199701d 100644 --- a/pkg/upstream/replicated.go +++ b/pkg/upstream/replicated.go @@ -56,6 +56,7 @@ type Release struct { ReplicatedRegistryDomain string ReplicatedProxyDomain string ReplicatedChartNames []string + EmbeddedClusterArtifacts []string Manifests map[string][]byte } @@ -127,6 +128,7 @@ func downloadReplicated( replicatedRegistryDomain string, replicatedProxyDomain string, replicatedChartNames []string, + embeddedClusterArtifacts []string, appSlug string, appSequence int64, isAirgap bool, @@ -138,7 +140,7 @@ func downloadReplicated( var release *Release if localPath != "" { - parsedLocalRelease, err := readReplicatedAppFromLocalPath(localPath, updateCursor, versionLabel, isRequired, replicatedRegistryDomain, replicatedProxyDomain, replicatedChartNames) + parsedLocalRelease, err := readReplicatedAppFromLocalPath(localPath, updateCursor, versionLabel, isRequired, replicatedRegistryDomain, replicatedProxyDomain, replicatedChartNames, embeddedClusterArtifacts) if err != nil { return nil, errors.Wrap(err, "failed to read replicated app from local path") } @@ -299,12 +301,13 @@ func downloadReplicated( ReplicatedRegistryDomain: release.ReplicatedRegistryDomain, ReplicatedProxyDomain: release.ReplicatedProxyDomain, ReplicatedChartNames: release.ReplicatedChartNames, + EmbeddedClusterArtifacts: embeddedClusterArtifacts, } return upstream, nil } -func readReplicatedAppFromLocalPath(localPath string, localCursor replicatedapp.ReplicatedCursor, versionLabel string, isRequired bool, replicatedRegistryDomain string, replicatedProxyDomain string, replicatedChartNames []string) (*Release, error) { +func readReplicatedAppFromLocalPath(localPath string, localCursor replicatedapp.ReplicatedCursor, versionLabel string, isRequired bool, replicatedRegistryDomain string, replicatedProxyDomain string, replicatedChartNames []string, embeddedClusterArtifacts []string) (*Release, error) { release := Release{ Manifests: make(map[string][]byte), UpdateCursor: localCursor, @@ -313,6 +316,7 @@ func readReplicatedAppFromLocalPath(localPath string, localCursor replicatedapp. ReplicatedRegistryDomain: replicatedRegistryDomain, ReplicatedProxyDomain: replicatedProxyDomain, ReplicatedChartNames: replicatedChartNames, + EmbeddedClusterArtifacts: embeddedClusterArtifacts, } err := filepath.Walk(localPath, diff --git a/pkg/upstream/types/types.go b/pkg/upstream/types/types.go index 6f24527b6f..aab06a6b00 100644 --- a/pkg/upstream/types/types.go +++ b/pkg/upstream/types/types.go @@ -37,6 +37,7 @@ type Upstream struct { ReplicatedRegistryDomain string ReplicatedProxyDomain string ReplicatedChartNames []string + EmbeddedClusterArtifacts []string EncryptionKey string } @@ -104,6 +105,7 @@ type FetchOptions struct { CurrentReplicatedRegistryDomain string CurrentReplicatedProxyDomain string CurrentReplicatedChartNames []string + CurrentEmbeddedClusterArtifacts []string ChannelChanged bool AppSlug string AppSequence int64 diff --git a/pkg/upstream/write.go b/pkg/upstream/write.go index 8481ad946d..f60ad3b9b5 100644 --- a/pkg/upstream/write.go +++ b/pkg/upstream/write.go @@ -141,6 +141,7 @@ func WriteUpstream(u *types.Upstream, options types.WriteOptions) error { ReplicatedRegistryDomain: u.ReplicatedRegistryDomain, ReplicatedProxyDomain: u.ReplicatedProxyDomain, ReplicatedChartNames: u.ReplicatedChartNames, + EmbeddedClusterArtifacts: u.EmbeddedClusterArtifacts, EncryptionKey: encryptionKey, }, } From 64a5b9cb6e51f8357e42f89b5204e2ccad7d955f Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Mon, 15 Apr 2024 15:00:24 +0000 Subject: [PATCH 2/9] nil check on embeddedClusterArtifacts in metadata --- pkg/upstream/fetch.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/upstream/fetch.go b/pkg/upstream/fetch.go index 92a51dc5f0..b19b32cc94 100644 --- a/pkg/upstream/fetch.go +++ b/pkg/upstream/fetch.go @@ -123,6 +123,10 @@ func pickReplicatedChartNames(fetchOptions *types.FetchOptions) []string { func pickEmbeddedClusterArtifacts(fetchOptions *types.FetchOptions) []string { if fetchOptions.Airgap != nil { + if fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts == nil { + return nil + } + opts := embeddedcluster.EmbeddedClusterArtifactOCIPathOptions{ RegistryHost: fetchOptions.LocalRegistry.Hostname, RegistryNamespace: fetchOptions.LocalRegistry.Namespace, From f9cc4b567ae1c8aba05e7ca4825799b67594ae65 Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Mon, 15 Apr 2024 15:41:50 +0000 Subject: [PATCH 3/9] update kotskinds for new embedded artifact field names --- go.mod | 2 +- go.sum | 2 ++ pkg/upstream/fetch.go | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 28e59c3bd2..17221bc78d 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 github.com/replicatedhq/embedded-cluster-kinds v1.1.2 - github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70 + github.com/replicatedhq/kotskinds v0.0.0-20240415152931-2837245679f5 github.com/replicatedhq/kurlkinds v1.5.0 github.com/replicatedhq/troubleshoot v0.87.0 github.com/replicatedhq/yaml/v3 v3.0.0-beta5-replicatedhq diff --git a/go.sum b/go.sum index 7de3e6e0e1..31810c0fba 100644 --- a/go.sum +++ b/go.sum @@ -1312,6 +1312,8 @@ github.com/replicatedhq/kotskinds v0.0.0-20240326213823-6a0ed11e7397 h1:JNuBcFH9 github.com/replicatedhq/kotskinds v0.0.0-20240326213823-6a0ed11e7397/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70 h1:55fMr60YysSf+ac5zeW+xTIIJ8edUpAjorQyFn0iP2c= github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= +github.com/replicatedhq/kotskinds v0.0.0-20240415152931-2837245679f5 h1:SI1Ar5c6QWTm1IpPOO/CVv8dktdqd8KaQUEOeHEbhgM= +github.com/replicatedhq/kotskinds v0.0.0-20240415152931-2837245679f5/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= github.com/replicatedhq/kurlkinds v1.5.0 h1:zZ0PKNeh4kXvSzVGkn62DKTo314GxhXg1TSB3azURMc= github.com/replicatedhq/kurlkinds v1.5.0/go.mod h1:rUpBMdC81IhmJNCWMU/uRsMETv9P0xFoMvdSP/TAr5A= github.com/replicatedhq/termui/v3 v3.1.1-0.20200811145416-f40076d26851 h1:eRlNDHxGfVkPCRXbA4BfQJvt5DHjFiTtWy3R/t4djyY= diff --git a/pkg/upstream/fetch.go b/pkg/upstream/fetch.go index b19b32cc94..9eae89b617 100644 --- a/pkg/upstream/fetch.go +++ b/pkg/upstream/fetch.go @@ -135,9 +135,9 @@ func pickEmbeddedClusterArtifacts(fetchOptions *types.FetchOptions) []string { VersionLabel: fetchOptions.Airgap.Spec.VersionLabel, } return []string{ - embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Binary, opts), + embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.BinaryAmd64, opts), embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Charts, opts), - embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Images, opts), + embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.ImagesAmd64, opts), embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Metadata, opts), } } From 0c9cefb6cf2b3bd4172adb3c2336abdd90cdda33 Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Mon, 15 Apr 2024 15:51:14 -0400 Subject: [PATCH 4/9] don't overwrite installation after copying images --- cmd/kots/cli/admin-console-push-images.go | 2 +- pkg/image/airgap.go | 36 ++++++++++------------- pkg/kotsadm/main.go | 2 +- pkg/midstream/write.go | 10 +------ pkg/pull/pull.go | 2 +- pkg/upstream/replicated.go | 2 +- pkg/upstream/upgrade.go | 2 +- 7 files changed, 21 insertions(+), 35 deletions(-) diff --git a/cmd/kots/cli/admin-console-push-images.go b/cmd/kots/cli/admin-console-push-images.go index a4e2809d3f..90e8f31d9d 100644 --- a/cmd/kots/cli/admin-console-push-images.go +++ b/cmd/kots/cli/admin-console-push-images.go @@ -54,7 +54,7 @@ func AdminPushImagesCmd() *cobra.Command { } if _, err := os.Stat(imageSource); err == nil { - _, err = image.TagAndPushImagesFromBundle(imageSource, *options) + err = image.TagAndPushImagesFromBundle(imageSource, *options) if err != nil { return errors.Wrap(err, "failed to push images") } diff --git a/pkg/image/airgap.go b/pkg/image/airgap.go index 0dea825898..6f3677d900 100644 --- a/pkg/image/airgap.go +++ b/pkg/image/airgap.go @@ -108,9 +108,9 @@ func WriteProgressLine(progressWriter io.Writer, line string) { } // CopyAirgapImages pushes images found in the airgap bundle/airgap root to the configured registry. -func CopyAirgapImages(opts imagetypes.ProcessImageOptions, log *logger.CLILogger) (*imagetypes.CopyAirgapImagesResult, error) { +func CopyAirgapImages(opts imagetypes.ProcessImageOptions, log *logger.CLILogger) error { if opts.AirgapBundle == "" { - return &imagetypes.CopyAirgapImagesResult{}, nil + return nil } pushOpts := imagetypes.PushImagesOptions{ @@ -125,27 +125,25 @@ func CopyAirgapImages(opts imagetypes.ProcessImageOptions, log *logger.CLILogger LogForUI: true, } - copyResult, err := TagAndPushImagesFromBundle(opts.AirgapBundle, pushOpts) + err := TagAndPushImagesFromBundle(opts.AirgapBundle, pushOpts) if err != nil { - return nil, errors.Wrap(err, "failed to push images from bundle") + return errors.Wrap(err, "failed to push images from bundle") } - return &imagetypes.CopyAirgapImagesResult{ - EmbeddedClusterArtifacts: copyResult.EmbeddedClusterArtifacts, - }, nil + return nil } -func TagAndPushImagesFromBundle(airgapBundle string, options imagetypes.PushImagesOptions) (*imagetypes.CopyAirgapImagesResult, error) { +func TagAndPushImagesFromBundle(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 := os.MkdirTemp("", "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) @@ -155,17 +153,17 @@ func TagAndPushImagesFromBundle(airgapBundle string, options imagetypes.PushImag }, } 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") } if err := PushImagesFromTempRegistry(extractedBundle, airgap.Spec.SavedImages, options); err != nil { - return nil, errors.Wrap(err, "failed to push images from docker registry bundle") + return errors.Wrap(err, "failed to push images from docker registry bundle") } case dockertypes.FormatDockerArchive, "": if err := PushImagesFromDockerArchiveBundle(airgapBundle, options); err != nil { - return nil, errors.Wrap(err, "failed to push images from docker archive bundle") + return errors.Wrap(err, "failed to push images from docker archive bundle") } 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) } pushEmbeddedArtifactsOpts := imagetypes.PushEmbeddedClusterArtifactsOptions{ @@ -173,16 +171,12 @@ func TagAndPushImagesFromBundle(airgapBundle string, options imagetypes.PushImag Tag: imageutil.SanitizeTag(fmt.Sprintf("%s-%s-%s", airgap.Spec.ChannelID, airgap.Spec.UpdateCursor, airgap.Spec.VersionLabel)), HTTPClient: orasretry.DefaultClient, } - pushedArtifacts, err := PushEmbeddedClusterArtifacts(airgapBundle, pushEmbeddedArtifactsOpts) + _, err = PushEmbeddedClusterArtifacts(airgapBundle, pushEmbeddedArtifactsOpts) if err != nil { - return nil, errors.Wrap(err, "failed to push embedded cluster artifacts") + return errors.Wrap(err, "failed to push embedded cluster artifacts") } - result := &imagetypes.CopyAirgapImagesResult{ - EmbeddedClusterArtifacts: pushedArtifacts, - } - - return result, nil + return nil } func PushImagesFromTempRegistry(airgapRootDir string, imageList []string, options imagetypes.PushImagesOptions) error { diff --git a/pkg/kotsadm/main.go b/pkg/kotsadm/main.go index 337c8374e9..cf87267135 100644 --- a/pkg/kotsadm/main.go +++ b/pkg/kotsadm/main.go @@ -164,7 +164,7 @@ func Deploy(deployOptions types.DeployOptions, log *logger.CLILogger) error { } if !deployOptions.DisableImagePush { - _, err := image.TagAndPushImagesFromBundle(deployOptions.AirgapBundle, pushOptions) + err := image.TagAndPushImagesFromBundle(deployOptions.AirgapBundle, pushOptions) if err != nil { return errors.Wrap(err, "failed to tag and push app images from path") } diff --git a/pkg/midstream/write.go b/pkg/midstream/write.go index 795d702d1e..173539e53f 100644 --- a/pkg/midstream/write.go +++ b/pkg/midstream/write.go @@ -112,18 +112,10 @@ func WriteMidstream(opts WriteOptions) (*Midstream, error) { io.WriteString(opts.ProcessImageOptions.ReportWriter, "Copying images\n") if opts.ProcessImageOptions.IsAirgap { - copyResult, err := image.CopyAirgapImages(opts.ProcessImageOptions, opts.Log) + err := image.CopyAirgapImages(opts.ProcessImageOptions, opts.Log) if err != nil { return nil, errors.Wrap(err, "failed to copy airgap images") } - - if err := image.UpdateInstallationEmbeddedClusterArtifacts(image.UpdateInstallationEmbeddedClusterArtifactsOptions{ - Artifacts: copyResult.EmbeddedClusterArtifacts, - KotsKinds: opts.KotsKinds, - UpstreamDir: opts.UpstreamDir, - }); err != nil { - return nil, errors.Wrap(err, "failed to update installation airgap artifacts") - } } else { err := image.CopyOnlineImages(opts.ProcessImageOptions, allImages, opts.KotsKinds, opts.License, dockerHubRegistryCreds, opts.Log) if err != nil { diff --git a/pkg/pull/pull.go b/pkg/pull/pull.go index 7660405119..830f1b33ca 100644 --- a/pkg/pull/pull.go +++ b/pkg/pull/pull.go @@ -365,7 +365,7 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { } if processImageOptions.RewriteImages && processImageOptions.IsAirgap { // if this is an airgap install, we still need to process the images - if _, err := image.CopyAirgapImages(processImageOptions, log); err != nil { + if err := image.CopyAirgapImages(processImageOptions, log); err != nil { return "", errors.Wrap(err, "failed to copy airgap images") } } diff --git a/pkg/upstream/replicated.go b/pkg/upstream/replicated.go index ec0199701d..1a88663d3d 100644 --- a/pkg/upstream/replicated.go +++ b/pkg/upstream/replicated.go @@ -301,7 +301,7 @@ func downloadReplicated( ReplicatedRegistryDomain: release.ReplicatedRegistryDomain, ReplicatedProxyDomain: release.ReplicatedProxyDomain, ReplicatedChartNames: release.ReplicatedChartNames, - EmbeddedClusterArtifacts: embeddedClusterArtifacts, + EmbeddedClusterArtifacts: release.EmbeddedClusterArtifacts, } return upstream, nil diff --git a/pkg/upstream/upgrade.go b/pkg/upstream/upgrade.go index 2d8709221b..45c660930b 100644 --- a/pkg/upstream/upgrade.go +++ b/pkg/upstream/upgrade.go @@ -69,7 +69,7 @@ func Upgrade(appSlug string, options UpgradeOptions) (*UpgradeResponse, error) { } if !options.DisableImagePush { - _, err := image.TagAndPushImagesFromBundle(options.AirgapBundle, pushOptions) + err := image.TagAndPushImagesFromBundle(options.AirgapBundle, pushOptions) if err != nil { return nil, errors.Wrap(err, "failed to tag and push app images from path") } From 5c5c4022907e9329b14a1c75a63be09a3c009d3a Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Mon, 15 Apr 2024 16:16:11 -0400 Subject: [PATCH 5/9] pull test for installation embedded cluster artifacts --- .../cases/airgap/upstream/userdata/installation.yaml | 11 +++++++++++ .../wantResults/kotsKinds/userdata/installation.yaml | 2 ++ .../wantResults/upstream/userdata/installation.yaml | 2 ++ pkg/tests/pull/pull_test.go | 3 +++ 4 files changed, 18 insertions(+) create mode 100644 pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml diff --git a/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml b/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml new file mode 100644 index 0000000000..5753d13f1f --- /dev/null +++ b/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml @@ -0,0 +1,11 @@ +apiVersion: kots.io/v1beta1 +kind: Installation +metadata: + creationTimestamp: null + name: my-app +spec: + channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 + channelName: My Channel + embeddedClusterArtifacts: + - ttl.sh/replicated/charts.tar.gz:v1 +status: {} diff --git a/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml b/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml index 825d8239f2..30c83e87f8 100644 --- a/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml +++ b/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml @@ -6,6 +6,8 @@ metadata: spec: channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 channelName: My Channel + embeddedClusterArtifacts: + - ttl.sh/replicated/charts.tar.gz:v1 knownImages: - image: alpine isPrivate: true diff --git a/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml b/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml index 825d8239f2..30c83e87f8 100644 --- a/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml +++ b/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml @@ -6,6 +6,8 @@ metadata: spec: channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 channelName: My Channel + embeddedClusterArtifacts: + - ttl.sh/replicated/charts.tar.gz:v1 knownImages: - image: alpine isPrivate: true diff --git a/pkg/tests/pull/pull_test.go b/pkg/tests/pull/pull_test.go index 567e9e3ca0..6a329cda59 100644 --- a/pkg/tests/pull/pull_test.go +++ b/pkg/tests/pull/pull_test.go @@ -263,6 +263,9 @@ func TestKotsPull(t *testing.T) { require.ElementsMatch(t, wantInstallation.Spec.KnownImages, installation.Spec.KnownImages) wantInstallation.Spec.KnownImages = nil installation.Spec.KnownImages = nil + require.ElementsMatch(t, wantInstallation.Spec.EmbeddedClusterArtifacts, installation.Spec.EmbeddedClusterArtifacts) + wantInstallation.Spec.EmbeddedClusterArtifacts = nil + installation.Spec.EmbeddedClusterArtifacts = nil require.Equal(t, wantInstallation, installation) }) } From bfd0bddb5386b4491c7d684b0abf4dd2aa8db1b1 Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Mon, 15 Apr 2024 16:30:56 -0400 Subject: [PATCH 6/9] unit tests for EmbeddedClusterArtifactOCIPath --- pkg/embeddedcluster/util_test.go | 104 +++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/pkg/embeddedcluster/util_test.go b/pkg/embeddedcluster/util_test.go index deb293d396..0064e1f811 100644 --- a/pkg/embeddedcluster/util_test.go +++ b/pkg/embeddedcluster/util_test.go @@ -58,3 +58,107 @@ func Test_getArtifactsFromInstallation(t *testing.T) { }) } } + +func TestEmbeddedClusterArtifactOCIPath(t *testing.T) { + type args struct { + filename string + opts EmbeddedClusterArtifactOCIPathOptions + } + tests := []struct { + name string + args args + want string + }{ + { + name: "happy path for binary", + args: args{ + filename: "embedded-cluster/embedded-cluster-amd64", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/embedded-cluster-amd64:test-channel-id-1-1.0.0", + }, + { + name: "happy path for charts bundle", + args: args{ + filename: "embedded-cluster/charts.tar.gz", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/charts.tar.gz:test-channel-id-1-1.0.0", + }, + { + name: "happy path for image bundle", + args: args{ + filename: "embedded-cluster/images-amd64.tar", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/images-amd64.tar:test-channel-id-1-1.0.0", + }, + { + name: "happy path for version metadata", + args: args{ + filename: "embedded-cluster/version-metadata.json", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/version-metadata.json:test-channel-id-1-1.0.0", + }, + { + name: "file with name that needs to be sanitized", + args: args{ + filename: "A file with spaces.tar.gz", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/afilewithspaces.tar.gz:test-channel-id-1-1.0.0", + }, + { + name: "version label name that needs to be sanitized", + args: args{ + filename: "test.txt", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "A version with spaces", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/test.txt:test-channel-id-1-Aversionwithspaces", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := EmbeddedClusterArtifactOCIPath(tt.args.filename, tt.args.opts); got != tt.want { + t.Errorf("EmbeddedClusterArtifactOCIPath() = %v, want %v", got, tt.want) + } + }) + } +} From a911e95122c7ea1226d7991c5e8356e19e40e225 Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Tue, 16 Apr 2024 09:54:40 -0400 Subject: [PATCH 7/9] use embeddedClusterArtifacts type --- pkg/embeddedcluster/util.go | 52 ++------------ pkg/embeddedcluster/util_test.go | 114 ++----------------------------- pkg/image/airgap.go | 65 +++++++++++------- pkg/image/airgap_test.go | 40 +++++------ pkg/image/online.go | 14 ---- pkg/image/types/types.go | 8 ++- pkg/imageutil/image.go | 39 +++++++++++ pkg/imageutil/image_test.go | 104 ++++++++++++++++++++++++++++ pkg/upstream/fetch.go | 17 ++--- pkg/upstream/replicated.go | 6 +- pkg/upstream/types/types.go | 4 +- 11 files changed, 236 insertions(+), 227 deletions(-) diff --git a/pkg/embeddedcluster/util.go b/pkg/embeddedcluster/util.go index f249fd6c03..667398a2a8 100644 --- a/pkg/embeddedcluster/util.go +++ b/pkg/embeddedcluster/util.go @@ -5,15 +5,11 @@ import ( "context" "encoding/json" "fmt" - "path/filepath" - "regexp" "sort" "time" embeddedclusterv1beta1 "github.com/replicatedhq/embedded-cluster-kinds/apis/v1beta1" - "github.com/replicatedhq/kots/pkg/imageutil" "github.com/replicatedhq/kots/pkg/k8sutil" - "github.com/replicatedhq/kots/pkg/logger" kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,13 +24,6 @@ const configMapNamespace = "embedded-cluster" // ErrNoInstallations is returned when no installation object is found in the cluster. var ErrNoInstallations = fmt.Errorf("no installations found") -var ( - chartsArtifactRegex = regexp.MustCompile(`\/embedded-cluster\/(charts\.tar\.gz):`) - imagesArtifactRegex = regexp.MustCompile(`\/embedded-cluster\/(images-.+\.tar):`) - binaryArtifactRegex = regexp.MustCompile(`\/embedded-cluster\/(embedded-cluster-.+):`) - metadataArtifactRegex = regexp.MustCompile(`\/embedded-cluster\/(version-metadata\.json):`) -) - // ReadConfigMap will read the Kurl config from a configmap func ReadConfigMap(client kubernetes.Interface) (*corev1.ConfigMap, error) { return client.CoreV1().ConfigMaps(configMapNamespace).Get(context.TODO(), configMapName, metav1.GetOptions{}) @@ -115,27 +104,16 @@ func ClusterConfig(ctx context.Context) (*embeddedclusterv1beta1.ConfigSpec, err } func getArtifactsFromInstallation(installation kotsv1beta1.Installation, appSlug string) *embeddedclusterv1beta1.ArtifactsLocation { - if len(installation.Spec.EmbeddedClusterArtifacts) == 0 { + if installation.Spec.EmbeddedClusterArtifacts == nil { return nil } - artifacts := &embeddedclusterv1beta1.ArtifactsLocation{} - for _, artifact := range installation.Spec.EmbeddedClusterArtifacts { - switch { - case chartsArtifactRegex.MatchString(artifact): - artifacts.HelmCharts = artifact - case imagesArtifactRegex.MatchString(artifact): - artifacts.Images = artifact - case binaryArtifactRegex.MatchString(artifact): - artifacts.EmbeddedClusterBinary = artifact - case metadataArtifactRegex.MatchString(artifact): - artifacts.EmbeddedClusterMetadata = artifact - default: - logger.Warnf("unknown artifact in installation: %s", artifact) - } + return &embeddedclusterv1beta1.ArtifactsLocation{ + EmbeddedClusterBinary: installation.Spec.EmbeddedClusterArtifacts.BinaryAmd64, + Images: installation.Spec.EmbeddedClusterArtifacts.ImagesAmd64, + HelmCharts: installation.Spec.EmbeddedClusterArtifacts.Charts, + EmbeddedClusterMetadata: installation.Spec.EmbeddedClusterArtifacts.Metadata, } - - return artifacts } // startClusterUpgrade will create a new installation with the provided config. @@ -173,21 +151,3 @@ func startClusterUpgrade(ctx context.Context, newcfg embeddedclusterv1beta1.Conf } return nil } - -type EmbeddedClusterArtifactOCIPathOptions struct { - RegistryHost string - RegistryNamespace string - ChannelID string - UpdateCursor string - VersionLabel string -} - -// EmbeddedClusterArtifactOCIPath returns the OCI path for an embedded cluster artifact given -// the artifact filename and details about the configured registry and channel release. -func EmbeddedClusterArtifactOCIPath(filename string, opts EmbeddedClusterArtifactOCIPathOptions) string { - name := filepath.Base(filename) - repository := filepath.Join("embedded-cluster", imageutil.SanitizeRepo(name)) - tag := imageutil.SanitizeTag(fmt.Sprintf("%s-%s-%s", opts.ChannelID, opts.UpdateCursor, opts.VersionLabel)) - artifact := fmt.Sprintf("%s:%s", filepath.Join(opts.RegistryHost, opts.RegistryNamespace, repository), tag) - return artifact -} diff --git a/pkg/embeddedcluster/util_test.go b/pkg/embeddedcluster/util_test.go index 0064e1f811..7305476721 100644 --- a/pkg/embeddedcluster/util_test.go +++ b/pkg/embeddedcluster/util_test.go @@ -31,11 +31,11 @@ func Test_getArtifactsFromInstallation(t *testing.T) { args: args{ installation: kotsv1beta1.Installation{ Spec: kotsv1beta1.InstallationSpec{ - EmbeddedClusterArtifacts: []string{ - "onprem.registry.com/my-app/embedded-cluster/charts.tar.gz:v1", - "onprem.registry.com/my-app/embedded-cluster/images-amd64.tar:v1", - "onprem.registry.com/my-app/embedded-cluster/embedded-cluster-amd64:v1", - "onprem.registry.com/my-app/embedded-cluster/version-metadata.json:v1", + EmbeddedClusterArtifacts: &kotsv1beta1.EmbeddedClusterArtifacts{ + Charts: "onprem.registry.com/my-app/embedded-cluster/charts.tar.gz:v1", + ImagesAmd64: "onprem.registry.com/my-app/embedded-cluster/images-amd64.tar:v1", + BinaryAmd64: "onprem.registry.com/my-app/embedded-cluster/embedded-cluster-amd64:v1", + Metadata: "onprem.registry.com/my-app/embedded-cluster/version-metadata.json:v1", }, }, }, @@ -58,107 +58,3 @@ func Test_getArtifactsFromInstallation(t *testing.T) { }) } } - -func TestEmbeddedClusterArtifactOCIPath(t *testing.T) { - type args struct { - filename string - opts EmbeddedClusterArtifactOCIPathOptions - } - tests := []struct { - name string - args args - want string - }{ - { - name: "happy path for binary", - args: args{ - filename: "embedded-cluster/embedded-cluster-amd64", - opts: EmbeddedClusterArtifactOCIPathOptions{ - RegistryHost: "registry.example.com", - RegistryNamespace: "my-app", - ChannelID: "test-channel-id", - UpdateCursor: "1", - VersionLabel: "1.0.0", - }, - }, - want: "registry.example.com/my-app/embedded-cluster/embedded-cluster-amd64:test-channel-id-1-1.0.0", - }, - { - name: "happy path for charts bundle", - args: args{ - filename: "embedded-cluster/charts.tar.gz", - opts: EmbeddedClusterArtifactOCIPathOptions{ - RegistryHost: "registry.example.com", - RegistryNamespace: "my-app", - ChannelID: "test-channel-id", - UpdateCursor: "1", - VersionLabel: "1.0.0", - }, - }, - want: "registry.example.com/my-app/embedded-cluster/charts.tar.gz:test-channel-id-1-1.0.0", - }, - { - name: "happy path for image bundle", - args: args{ - filename: "embedded-cluster/images-amd64.tar", - opts: EmbeddedClusterArtifactOCIPathOptions{ - RegistryHost: "registry.example.com", - RegistryNamespace: "my-app", - ChannelID: "test-channel-id", - UpdateCursor: "1", - VersionLabel: "1.0.0", - }, - }, - want: "registry.example.com/my-app/embedded-cluster/images-amd64.tar:test-channel-id-1-1.0.0", - }, - { - name: "happy path for version metadata", - args: args{ - filename: "embedded-cluster/version-metadata.json", - opts: EmbeddedClusterArtifactOCIPathOptions{ - RegistryHost: "registry.example.com", - RegistryNamespace: "my-app", - ChannelID: "test-channel-id", - UpdateCursor: "1", - VersionLabel: "1.0.0", - }, - }, - want: "registry.example.com/my-app/embedded-cluster/version-metadata.json:test-channel-id-1-1.0.0", - }, - { - name: "file with name that needs to be sanitized", - args: args{ - filename: "A file with spaces.tar.gz", - opts: EmbeddedClusterArtifactOCIPathOptions{ - RegistryHost: "registry.example.com", - RegistryNamespace: "my-app", - ChannelID: "test-channel-id", - UpdateCursor: "1", - VersionLabel: "1.0.0", - }, - }, - want: "registry.example.com/my-app/embedded-cluster/afilewithspaces.tar.gz:test-channel-id-1-1.0.0", - }, - { - name: "version label name that needs to be sanitized", - args: args{ - filename: "test.txt", - opts: EmbeddedClusterArtifactOCIPathOptions{ - RegistryHost: "registry.example.com", - RegistryNamespace: "my-app", - ChannelID: "test-channel-id", - UpdateCursor: "1", - VersionLabel: "A version with spaces", - }, - }, - want: "registry.example.com/my-app/embedded-cluster/test.txt:test-channel-id-1-Aversionwithspaces", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := EmbeddedClusterArtifactOCIPath(tt.args.filename, tt.args.opts); got != tt.want { - t.Errorf("EmbeddedClusterArtifactOCIPath() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/image/airgap.go b/pkg/image/airgap.go index 6f3677d900..d6fb2f8f52 100644 --- a/pkg/image/airgap.go +++ b/pkg/image/airgap.go @@ -27,6 +27,7 @@ import ( "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" oras "oras.land/oras-go/v2" orasfile "oras.land/oras-go/v2/content/file" orasremote "oras.land/oras-go/v2/registry/remote" @@ -167,11 +168,13 @@ func TagAndPushImagesFromBundle(airgapBundle string, options imagetypes.PushImag } pushEmbeddedArtifactsOpts := imagetypes.PushEmbeddedClusterArtifactsOptions{ - Registry: options.Registry, - Tag: imageutil.SanitizeTag(fmt.Sprintf("%s-%s-%s", airgap.Spec.ChannelID, airgap.Spec.UpdateCursor, airgap.Spec.VersionLabel)), - HTTPClient: orasretry.DefaultClient, + Registry: options.Registry, + ChannelID: airgap.Spec.ChannelID, + UpdateCursor: airgap.Spec.UpdateCursor, + VersionLabel: airgap.Spec.VersionLabel, + HTTPClient: orasretry.DefaultClient, } - _, err = PushEmbeddedClusterArtifacts(airgapBundle, pushEmbeddedArtifactsOpts) + err = PushEmbeddedClusterArtifacts(airgapBundle, airgap.Spec.EmbeddedClusterArtifacts, pushEmbeddedArtifactsOpts) if err != nil { return errors.Wrap(err, "failed to push embedded cluster artifacts") } @@ -678,59 +681,58 @@ func reportWriterWithProgress(imageInfos map[string]*imagetypes.ImageInfo, repor return pipeWriter } -func PushEmbeddedClusterArtifacts(airgapBundle string, opts imagetypes.PushEmbeddedClusterArtifactsOptions) ([]string, error) { +func PushEmbeddedClusterArtifacts(airgapBundle string, artifactsToPush *kotsv1beta1.EmbeddedClusterArtifacts, opts imagetypes.PushEmbeddedClusterArtifactsOptions) error { tmpDir, err := os.MkdirTemp("", "embedded-cluster-artifacts") if err != nil { - return nil, errors.Wrap(err, "failed to create temp directory") + return errors.Wrap(err, "failed to create temp directory") } defer os.RemoveAll(tmpDir) 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() var artifacts []string tarReader := tar.NewReader(gzipReader) - pushedArtifacts := make([]string, 0) for { header, err := tarReader.Next() if err == io.EOF { 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 { continue } - if filepath.Dir(header.Name) != "embedded-cluster" { + if !shouldPushArtifact(header.Name, artifactsToPush) { continue } dstFilePath := filepath.Join(tmpDir, header.Name) if err := os.MkdirAll(filepath.Dir(dstFilePath), 0755); err != nil { - return nil, errors.Wrap(err, "failed to create path") + return errors.Wrap(err, "failed to create path") } dstFile, err := os.Create(dstFilePath) if err != nil { - return nil, errors.Wrap(err, "failed to create file") + return errors.Wrap(err, "failed to create file") } if _, err := io.Copy(dstFile, tarReader); err != nil { dstFile.Close() - return nil, errors.Wrap(err, "failed to copy file data") + return errors.Wrap(err, "failed to copy file data") } dstFile.Close() @@ -738,10 +740,16 @@ func PushEmbeddedClusterArtifacts(airgapBundle string, opts imagetypes.PushEmbed } for i, dstFilePath := range artifacts { - name := filepath.Base(dstFilePath) - repository := filepath.Join("embedded-cluster", imageutil.SanitizeRepo(name)) + ociArtifactPath := imageutil.NewEmbeddedClusterOCIArtifactPath(dstFilePath, imageutil.EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: opts.Registry.Endpoint, + RegistryNamespace: opts.Registry.Namespace, + ChannelID: opts.ChannelID, + UpdateCursor: opts.UpdateCursor, + VersionLabel: opts.VersionLabel, + }) + artifactFile := imagetypes.OCIArtifactFile{ - Name: name, + Name: ociArtifactPath.Name, Path: dstFilePath, MediaType: EmbeddedClusterMediaType, } @@ -750,20 +758,31 @@ func PushEmbeddedClusterArtifacts(airgapBundle string, opts imagetypes.PushEmbed Files: []imagetypes.OCIArtifactFile{artifactFile}, ArtifactType: EmbeddedClusterArtifactType, Registry: opts.Registry, - Repository: repository, - Tag: opts.Tag, + Repository: ociArtifactPath.Repository, + Tag: ociArtifactPath.Tag, HTTPClient: opts.HTTPClient, } fmt.Printf("Pushing embedded cluster artifacts (%d/%d)\n", i+1, len(artifacts)) - artifact := fmt.Sprintf("%s:%s", filepath.Join(opts.Registry.Endpoint, opts.Registry.Namespace, repository), opts.Tag) if err := pushOCIArtifact(pushOCIArtifactOpts); err != nil { - return nil, errors.Wrapf(err, "failed to push oci artifact %s", name) + return errors.Wrapf(err, "failed to push oci artifact %s", ociArtifactPath.Name) } - pushedArtifacts = append(pushedArtifacts, artifact) } - return pushedArtifacts, nil + return nil +} + +func shouldPushArtifact(artifactPath string, artifactsToPush *kotsv1beta1.EmbeddedClusterArtifacts) bool { + if artifactsToPush == nil { + return false + } + + switch artifactPath { + case artifactsToPush.BinaryAmd64, artifactsToPush.Charts, artifactsToPush.ImagesAmd64, artifactsToPush.Metadata: + return true + default: + return false + } } func pushOCIArtifact(opts imagetypes.PushOCIArtifactOptions) error { diff --git a/pkg/image/airgap_test.go b/pkg/image/airgap_test.go index c10a913038..a015eca92a 100644 --- a/pkg/image/airgap_test.go +++ b/pkg/image/airgap_test.go @@ -16,16 +16,20 @@ import ( dockertypes "github.com/replicatedhq/kots/pkg/docker/types" "github.com/replicatedhq/kots/pkg/image/types" imagetypes "github.com/replicatedhq/kots/pkg/image/types" + kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" "github.com/stretchr/testify/require" ) func TestPushEmbeddedClusterArtifacts(t *testing.T) { testAppSlug := "test-app" - testTag := "test-tag" + testChannelID := "test-tag" + testUpdateCursor := "test-cursor" + testVersionLabel := "test-version" tests := []struct { name string airgapFiles map[string][]byte + artifactsToPush *kotsv1beta1.EmbeddedClusterArtifacts wantRegistryArtifacts map[string]string wantErr bool }{ @@ -36,6 +40,7 @@ func TestPushEmbeddedClusterArtifacts(t *testing.T) { "app.tar.gz": []byte("this-is-the-app-archive"), "images/something": []byte("this-is-an-image"), }, + artifactsToPush: nil, wantRegistryArtifacts: map[string]string{}, wantErr: false, }, @@ -51,12 +56,17 @@ func TestPushEmbeddedClusterArtifacts(t *testing.T) { "embedded-cluster/version-metadata.json": []byte("this-is-the-metadata"), "embedded-cluster/some-file-TBD": []byte("this-is-an-arbitrary-file"), }, + artifactsToPush: &kotsv1beta1.EmbeddedClusterArtifacts{ + BinaryAmd64: "embedded-cluster/test-app", + ImagesAmd64: "embedded-cluster/images-amd64.tar", + Charts: "embedded-cluster/charts.tar.gz", + Metadata: "embedded-cluster/version-metadata.json", + }, wantRegistryArtifacts: map[string]string{ - fmt.Sprintf("%s/embedded-cluster/test-app", testAppSlug): testTag, - fmt.Sprintf("%s/embedded-cluster/charts.tar.gz", testAppSlug): testTag, - fmt.Sprintf("%s/embedded-cluster/images-amd64.tar", testAppSlug): testTag, - fmt.Sprintf("%s/embedded-cluster/version-metadata.json", testAppSlug): testTag, - fmt.Sprintf("%s/embedded-cluster/some-file-tbd", testAppSlug): testTag, + fmt.Sprintf("%s/embedded-cluster/test-app", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel), + fmt.Sprintf("%s/embedded-cluster/charts.tar.gz", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel), + fmt.Sprintf("%s/embedded-cluster/images-amd64.tar", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel), + fmt.Sprintf("%s/embedded-cluster/version-metadata.json", testAppSlug): fmt.Sprintf("%s-%s-%s", testChannelID, testUpdateCursor, testVersionLabel), }, wantErr: false, }, @@ -83,26 +93,18 @@ func TestPushEmbeddedClusterArtifacts(t *testing.T) { Endpoint: u.Host, Namespace: testAppSlug, }, - Tag: testTag, - HTTPClient: mockRegistryServer.Client(), - } - gotArtifacts, err := PushEmbeddedClusterArtifacts(airgapBundle, opts) - if (err != nil) != tt.wantErr { - t.Errorf("PushEmbeddedClusterArtifacts() error = %v, wantErr %v", err, tt.wantErr) + ChannelID: testChannelID, + UpdateCursor: testUpdateCursor, + VersionLabel: testVersionLabel, + HTTPClient: mockRegistryServer.Client(), } - + err = PushEmbeddedClusterArtifacts(airgapBundle, tt.artifactsToPush, opts) if tt.wantErr { req.Error(err) } else { req.NoError(err) } - wantArtifacts := make([]string, 0) - for repo, tag := range tt.wantRegistryArtifacts { - wantArtifacts = append(wantArtifacts, fmt.Sprintf("%s/%s:%s", u.Host, repo, tag)) - } - req.ElementsMatch(wantArtifacts, gotArtifacts) - // validate that each of the expected artifacts were pushed to the registry req.Equal(tt.wantRegistryArtifacts, pushedRegistryArtifacts) }) diff --git a/pkg/image/online.go b/pkg/image/online.go index 146857cb3d..93bcb4afa4 100644 --- a/pkg/image/online.go +++ b/pkg/image/online.go @@ -138,20 +138,6 @@ func UpdateInstallationImages(opts UpdateInstallationImagesOptions) error { return nil } -func UpdateInstallationEmbeddedClusterArtifacts(opts UpdateInstallationEmbeddedClusterArtifactsOptions) error { - if opts.KotsKinds == nil { - return nil - } - - opts.KotsKinds.Installation.Spec.EmbeddedClusterArtifacts = opts.Artifacts - - if err := kotsutil.SaveInstallation(&opts.KotsKinds.Installation, opts.UpstreamDir); err != nil { - return errors.Wrap(err, "failed to save installation") - } - - return nil -} - func CopyOnlineImages(opts imagetypes.ProcessImageOptions, images []string, kotsKinds *kotsutil.KotsKinds, license *kotsv1beta1.License, dockerHubRegistryCreds registry.Credentials, log *logger.CLILogger) error { installationImages := make(map[string]imagetypes.InstallationImageInfo) for _, i := range kotsKinds.Installation.Spec.KnownImages { diff --git a/pkg/image/types/types.go b/pkg/image/types/types.go index 64e5b59638..720fe43d7c 100644 --- a/pkg/image/types/types.go +++ b/pkg/image/types/types.go @@ -84,9 +84,11 @@ type LayerInfo struct { } type PushEmbeddedClusterArtifactsOptions struct { - Registry dockerregistrytypes.RegistryOptions - Tag string - HTTPClient *http.Client + Registry dockerregistrytypes.RegistryOptions + ChannelID string + UpdateCursor string + VersionLabel string + HTTPClient *http.Client } type PushOCIArtifactOptions struct { diff --git a/pkg/imageutil/image.go b/pkg/imageutil/image.go index df1d7099e5..7f10a1ad4d 100644 --- a/pkg/imageutil/image.go +++ b/pkg/imageutil/image.go @@ -3,6 +3,7 @@ package imageutil import ( "fmt" "path" + "path/filepath" "strings" "github.com/containers/image/v5/docker/reference" @@ -334,3 +335,41 @@ func SanitizeRepo(repo string) string { repo = strings.Join(dockerref.NameRegexp.FindAllString(repo, -1), "") return repo } + +type OCIArtifactPath struct { + Name string + RegistryHost string + RegistryNamespace string + Repository string + Tag string +} + +func (p *OCIArtifactPath) String() string { + if p.RegistryNamespace == "" { + return fmt.Sprintf("%s:%s", filepath.Join(p.RegistryHost, p.Repository), p.Tag) + } + return fmt.Sprintf("%s:%s", filepath.Join(p.RegistryHost, p.RegistryNamespace, p.Repository), p.Tag) +} + +type EmbeddedClusterArtifactOCIPathOptions struct { + RegistryHost string + RegistryNamespace string + ChannelID string + UpdateCursor string + VersionLabel string +} + +// NewEmbeddedClusterOCIArtifactPath returns the OCI path for an embedded cluster artifact given +// the artifact filename and details about the configured registry and channel release. +func NewEmbeddedClusterOCIArtifactPath(filename string, opts EmbeddedClusterArtifactOCIPathOptions) *OCIArtifactPath { + name := filepath.Base(filename) + repository := filepath.Join("embedded-cluster", SanitizeRepo(name)) + tag := SanitizeTag(fmt.Sprintf("%s-%s-%s", opts.ChannelID, opts.UpdateCursor, opts.VersionLabel)) + return &OCIArtifactPath{ + Name: name, + RegistryHost: opts.RegistryHost, + RegistryNamespace: opts.RegistryNamespace, + Repository: repository, + Tag: tag, + } +} diff --git a/pkg/imageutil/image_test.go b/pkg/imageutil/image_test.go index bb8436d011..3e4a584371 100644 --- a/pkg/imageutil/image_test.go +++ b/pkg/imageutil/image_test.go @@ -1198,3 +1198,107 @@ func TestSanitizeRepo(t *testing.T) { }) } } + +func TestEmbeddedClusterArtifactOCIPath(t *testing.T) { + type args struct { + filename string + opts EmbeddedClusterArtifactOCIPathOptions + } + tests := []struct { + name string + args args + want string + }{ + { + name: "happy path for binary", + args: args{ + filename: "embedded-cluster/embedded-cluster-amd64", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/embedded-cluster-amd64:test-channel-id-1-1.0.0", + }, + { + name: "happy path for charts bundle", + args: args{ + filename: "embedded-cluster/charts.tar.gz", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/charts.tar.gz:test-channel-id-1-1.0.0", + }, + { + name: "happy path for image bundle", + args: args{ + filename: "embedded-cluster/images-amd64.tar", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/images-amd64.tar:test-channel-id-1-1.0.0", + }, + { + name: "happy path for version metadata", + args: args{ + filename: "embedded-cluster/version-metadata.json", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/version-metadata.json:test-channel-id-1-1.0.0", + }, + { + name: "file with name that needs to be sanitized", + args: args{ + filename: "A file with spaces.tar.gz", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "1.0.0", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/afilewithspaces.tar.gz:test-channel-id-1-1.0.0", + }, + { + name: "version label name that needs to be sanitized", + args: args{ + filename: "test.txt", + opts: EmbeddedClusterArtifactOCIPathOptions{ + RegistryHost: "registry.example.com", + RegistryNamespace: "my-app", + ChannelID: "test-channel-id", + UpdateCursor: "1", + VersionLabel: "A version with spaces", + }, + }, + want: "registry.example.com/my-app/embedded-cluster/test.txt:test-channel-id-1-Aversionwithspaces", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewEmbeddedClusterOCIArtifactPath(tt.args.filename, tt.args.opts); got.String() != tt.want { + t.Errorf("EmbeddedClusterArtifactOCIPath() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/upstream/fetch.go b/pkg/upstream/fetch.go index 9eae89b617..9563623b85 100644 --- a/pkg/upstream/fetch.go +++ b/pkg/upstream/fetch.go @@ -5,10 +5,11 @@ import ( "github.com/pkg/errors" "github.com/replicatedhq/kots/pkg/crypto" - "github.com/replicatedhq/kots/pkg/embeddedcluster" + "github.com/replicatedhq/kots/pkg/imageutil" "github.com/replicatedhq/kots/pkg/replicatedapp" "github.com/replicatedhq/kots/pkg/upstream/types" "github.com/replicatedhq/kots/pkg/util" + kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" ) func FetchUpstream(upstreamURI string, fetchOptions *types.FetchOptions) (*types.Upstream, error) { @@ -121,24 +122,24 @@ func pickReplicatedChartNames(fetchOptions *types.FetchOptions) []string { return fetchOptions.CurrentReplicatedChartNames } -func pickEmbeddedClusterArtifacts(fetchOptions *types.FetchOptions) []string { +func pickEmbeddedClusterArtifacts(fetchOptions *types.FetchOptions) *kotsv1beta1.EmbeddedClusterArtifacts { if fetchOptions.Airgap != nil { if fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts == nil { return nil } - opts := embeddedcluster.EmbeddedClusterArtifactOCIPathOptions{ + opts := imageutil.EmbeddedClusterArtifactOCIPathOptions{ RegistryHost: fetchOptions.LocalRegistry.Hostname, RegistryNamespace: fetchOptions.LocalRegistry.Namespace, ChannelID: fetchOptions.Airgap.Spec.ChannelID, UpdateCursor: fetchOptions.Airgap.Spec.UpdateCursor, VersionLabel: fetchOptions.Airgap.Spec.VersionLabel, } - return []string{ - embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.BinaryAmd64, opts), - embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Charts, opts), - embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.ImagesAmd64, opts), - embeddedcluster.EmbeddedClusterArtifactOCIPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Metadata, opts), + return &kotsv1beta1.EmbeddedClusterArtifacts{ + BinaryAmd64: imageutil.NewEmbeddedClusterOCIArtifactPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.BinaryAmd64, opts).String(), + Charts: imageutil.NewEmbeddedClusterOCIArtifactPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Charts, opts).String(), + ImagesAmd64: imageutil.NewEmbeddedClusterOCIArtifactPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.ImagesAmd64, opts).String(), + Metadata: imageutil.NewEmbeddedClusterOCIArtifactPath(fetchOptions.Airgap.Spec.EmbeddedClusterArtifacts.Metadata, opts).String(), } } return fetchOptions.CurrentEmbeddedClusterArtifacts diff --git a/pkg/upstream/replicated.go b/pkg/upstream/replicated.go index 1a88663d3d..f083699374 100644 --- a/pkg/upstream/replicated.go +++ b/pkg/upstream/replicated.go @@ -56,7 +56,7 @@ type Release struct { ReplicatedRegistryDomain string ReplicatedProxyDomain string ReplicatedChartNames []string - EmbeddedClusterArtifacts []string + EmbeddedClusterArtifacts *kotsv1beta1.EmbeddedClusterArtifacts Manifests map[string][]byte } @@ -128,7 +128,7 @@ func downloadReplicated( replicatedRegistryDomain string, replicatedProxyDomain string, replicatedChartNames []string, - embeddedClusterArtifacts []string, + embeddedClusterArtifacts *kotsv1beta1.EmbeddedClusterArtifacts, appSlug string, appSequence int64, isAirgap bool, @@ -307,7 +307,7 @@ func downloadReplicated( return upstream, nil } -func readReplicatedAppFromLocalPath(localPath string, localCursor replicatedapp.ReplicatedCursor, versionLabel string, isRequired bool, replicatedRegistryDomain string, replicatedProxyDomain string, replicatedChartNames []string, embeddedClusterArtifacts []string) (*Release, error) { +func readReplicatedAppFromLocalPath(localPath string, localCursor replicatedapp.ReplicatedCursor, versionLabel string, isRequired bool, replicatedRegistryDomain string, replicatedProxyDomain string, replicatedChartNames []string, embeddedClusterArtifacts *kotsv1beta1.EmbeddedClusterArtifacts) (*Release, error) { release := Release{ Manifests: make(map[string][]byte), UpdateCursor: localCursor, diff --git a/pkg/upstream/types/types.go b/pkg/upstream/types/types.go index aab06a6b00..e7548cb19f 100644 --- a/pkg/upstream/types/types.go +++ b/pkg/upstream/types/types.go @@ -37,7 +37,7 @@ type Upstream struct { ReplicatedRegistryDomain string ReplicatedProxyDomain string ReplicatedChartNames []string - EmbeddedClusterArtifacts []string + EmbeddedClusterArtifacts *kotsv1beta1.EmbeddedClusterArtifacts EncryptionKey string } @@ -105,7 +105,7 @@ type FetchOptions struct { CurrentReplicatedRegistryDomain string CurrentReplicatedProxyDomain string CurrentReplicatedChartNames []string - CurrentEmbeddedClusterArtifacts []string + CurrentEmbeddedClusterArtifacts *kotsv1beta1.EmbeddedClusterArtifacts ChannelChanged bool AppSlug string AppSequence int64 From 80496fef7bd33d10d13c6ea3bccee4fbe44db9f6 Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Tue, 16 Apr 2024 09:59:45 -0400 Subject: [PATCH 8/9] changes to go.mod --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 17221bc78d..9175bb9cf4 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 github.com/replicatedhq/embedded-cluster-kinds v1.1.2 - github.com/replicatedhq/kotskinds v0.0.0-20240415152931-2837245679f5 + github.com/replicatedhq/kotskinds v0.0.0-20240416132840-4e646b87f7a1 github.com/replicatedhq/kurlkinds v1.5.0 github.com/replicatedhq/troubleshoot v0.87.0 github.com/replicatedhq/yaml/v3 v3.0.0-beta5-replicatedhq diff --git a/go.sum b/go.sum index 31810c0fba..bd685dda54 100644 --- a/go.sum +++ b/go.sum @@ -1314,6 +1314,8 @@ github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70 h1:55fMr60Y github.com/replicatedhq/kotskinds v0.0.0-20240402213802-a6d75e97be70/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= github.com/replicatedhq/kotskinds v0.0.0-20240415152931-2837245679f5 h1:SI1Ar5c6QWTm1IpPOO/CVv8dktdqd8KaQUEOeHEbhgM= github.com/replicatedhq/kotskinds v0.0.0-20240415152931-2837245679f5/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= +github.com/replicatedhq/kotskinds v0.0.0-20240416132840-4e646b87f7a1 h1:+RvMZ646tQTRzWFZTy6mnmgWJZOLFu6B9PXv8tcIcFY= +github.com/replicatedhq/kotskinds v0.0.0-20240416132840-4e646b87f7a1/go.mod h1:QjhIUu3+OmHZ09u09j3FCoTt8F3BYtQglS+OLmftu9I= github.com/replicatedhq/kurlkinds v1.5.0 h1:zZ0PKNeh4kXvSzVGkn62DKTo314GxhXg1TSB3azURMc= github.com/replicatedhq/kurlkinds v1.5.0/go.mod h1:rUpBMdC81IhmJNCWMU/uRsMETv9P0xFoMvdSP/TAr5A= github.com/replicatedhq/termui/v3 v3.1.1-0.20200811145416-f40076d26851 h1:eRlNDHxGfVkPCRXbA4BfQJvt5DHjFiTtWy3R/t4djyY= From 135882c9d86b7675032416138936a1634922285b Mon Sep 17 00:00:00 2001 From: Craig O'Donnell Date: Tue, 16 Apr 2024 14:10:27 +0000 Subject: [PATCH 9/9] update pull test --- .../pull/cases/airgap/upstream/userdata/installation.yaml | 5 ++++- .../airgap/wantResults/kotsKinds/userdata/installation.yaml | 5 ++++- .../airgap/wantResults/upstream/userdata/installation.yaml | 5 ++++- pkg/tests/pull/pull_test.go | 3 --- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml b/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml index 5753d13f1f..af57ecf3e8 100644 --- a/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml +++ b/pkg/tests/pull/cases/airgap/upstream/userdata/installation.yaml @@ -7,5 +7,8 @@ spec: channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 channelName: My Channel embeddedClusterArtifacts: - - ttl.sh/replicated/charts.tar.gz:v1 + binaryAmd64: ttl.sh/replicated/binary-amd64:v1 + imagesAmd64: ttl.sh/replicated/images-amd64:v1 + charts: ttl.sh/replicated/charts.tar.gz:v1 + metadata: ttl.sh/replicated/metadata.json:v1 status: {} diff --git a/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml b/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml index 30c83e87f8..d147c12f23 100644 --- a/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml +++ b/pkg/tests/pull/cases/airgap/wantResults/kotsKinds/userdata/installation.yaml @@ -7,7 +7,10 @@ spec: channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 channelName: My Channel embeddedClusterArtifacts: - - ttl.sh/replicated/charts.tar.gz:v1 + binaryAmd64: ttl.sh/replicated/binary-amd64:v1 + imagesAmd64: ttl.sh/replicated/images-amd64:v1 + charts: ttl.sh/replicated/charts.tar.gz:v1 + metadata: ttl.sh/replicated/metadata.json:v1 knownImages: - image: alpine isPrivate: true diff --git a/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml b/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml index 30c83e87f8..d147c12f23 100644 --- a/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml +++ b/pkg/tests/pull/cases/airgap/wantResults/upstream/userdata/installation.yaml @@ -7,7 +7,10 @@ spec: channelID: 1vusIYZLAVxMG6q760OJmRKj5i5 channelName: My Channel embeddedClusterArtifacts: - - ttl.sh/replicated/charts.tar.gz:v1 + binaryAmd64: ttl.sh/replicated/binary-amd64:v1 + imagesAmd64: ttl.sh/replicated/images-amd64:v1 + charts: ttl.sh/replicated/charts.tar.gz:v1 + metadata: ttl.sh/replicated/metadata.json:v1 knownImages: - image: alpine isPrivate: true diff --git a/pkg/tests/pull/pull_test.go b/pkg/tests/pull/pull_test.go index 6a329cda59..567e9e3ca0 100644 --- a/pkg/tests/pull/pull_test.go +++ b/pkg/tests/pull/pull_test.go @@ -263,9 +263,6 @@ func TestKotsPull(t *testing.T) { require.ElementsMatch(t, wantInstallation.Spec.KnownImages, installation.Spec.KnownImages) wantInstallation.Spec.KnownImages = nil installation.Spec.KnownImages = nil - require.ElementsMatch(t, wantInstallation.Spec.EmbeddedClusterArtifacts, installation.Spec.EmbeddedClusterArtifacts) - wantInstallation.Spec.EmbeddedClusterArtifacts = nil - installation.Spec.EmbeddedClusterArtifacts = nil require.Equal(t, wantInstallation, installation) }) }