diff --git a/cmd/kk/pkg/images/module.go b/cmd/kk/pkg/images/module.go index 0a28bf362..d1e2b88f8 100644 --- a/cmd/kk/pkg/images/module.go +++ b/cmd/kk/pkg/images/module.go @@ -85,8 +85,13 @@ func (c *CopyImagesToRegistryModule) Init() { Desc: "Copy images to a private registry from an artifact OCI Path", Action: &CopyImagesToRegistry{ImagesPath: c.ImagePath}, } - + pushManifest := &task.LocalTask{ + Name: "PushManifest", + Desc: "Push multi-arch manifest to private registry", + Action: new(PushManifest), + } c.Tasks = []task.Interface{ copyImage, + pushManifest, } } diff --git a/cmd/kk/pkg/images/tasks.go b/cmd/kk/pkg/images/tasks.go index b3c03efe9..b1d47b8b6 100644 --- a/cmd/kk/pkg/images/tasks.go +++ b/cmd/kk/pkg/images/tasks.go @@ -19,8 +19,10 @@ package images import ( "encoding/json" "fmt" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" "os" "path/filepath" + "reflect" "strings" manifestregistry "github.com/estesp/manifest-tool/v2/pkg/registry" @@ -176,7 +178,10 @@ func (s *SaveImages) Execute(runtime connector.Runtime) error { for _, platform := range s.Manifest.Spec.Arches { arch, variant := ParseArchVariant(platform) - destName := fmt.Sprintf("%s-%s-%s%s", imageFullName[1], suffixImageName(imageFullName[2:]), arch, variant) + destName := fmt.Sprintf("%s-%s-%s", imageFullName[1], suffixImageName(imageFullName[2:]), arch) + if variant != "" { + destName = fmt.Sprintf("%s:%s", destName, variant) + } logger.Log.Infof("Source: %s", image) logger.Log.Infof("Destination: %s/%s", dirName, destName) @@ -194,7 +199,7 @@ func (s *SaveImages) Execute(runtime connector.Runtime) error { }, }, destImage: &destImageOptions{ - imageName: image, + imageName: destName, outputPath: dirName, dockerImage: dockerImageOptions{ arch: arch, @@ -236,24 +241,24 @@ func (c *CopyImagesToRegistry) Execute(runtime connector.Runtime) error { } auths := registry.DockerRegistryAuthEntries(c.KubeConf.Cluster.Registry.Auths) - + var manifestList = make(map[string][]manifesttypes.ManifestEntry) for _, m := range index.Manifests { ref := m.Annotations.RefName // Ex: - // calico:cni:v3.20.0-amd64 - nameArr := strings.Split(ref, "/") + // library-bash:5.1.16-amd64:v1 + nameArr := strings.Split(ref, "-") if len(nameArr) < 3 { return errors.Errorf("invalid ref name: %s", ref) } - regTag := strings.Split(nameArr[len(nameArr)-1], ":") + regTag := strings.Split(nameArr[len(nameArr)-2], ":") if len(regTag) != 2 { return errors.Errorf("invalid tag name: %s", ref) } image := Image{ RepoAddr: c.KubeConf.Cluster.Registry.PrivateRegistry, - Namespace: nameArr[1], + Namespace: nameArr[0], NamespaceOverride: c.KubeConf.Cluster.Registry.NamespaceOverride, Repo: regTag[0], Tag: regTag[1], @@ -264,11 +269,46 @@ func (c *CopyImagesToRegistry) Execute(runtime connector.Runtime) error { auth = config } + arch, v := ParseArchVariant(strings.ReplaceAll(nameArr[len(nameArr)-1], ":", "/")) + srcName := fmt.Sprintf("oci:%s/%s", imagesPath, ref) - destName := fmt.Sprintf("%s", image.ImageName()) + destName := fmt.Sprintf("%s-%s", image.ImageName(), arch) + if v != "" { + destName = fmt.Sprintf("%s-%s", destName, v) + } logger.Log.Infof("Source: %s", srcName) logger.Log.Infof("Destination: %s", destName) + entry := manifesttypes.ManifestEntry{ + Image: destName, + Platform: ocispec.Platform{ + Architecture: arch, + OS: "linux", + Variant: v, + }, + } + + skip := false + if entries, ok := manifestList[image.ImageName()]; ok { + + for _, old := range v { + if reflect.DeepEqual(old, entry) { + skip = true + break + } + } + if !skip { + entries = append(entries, entry) + manifestList[image.ImageName()] = entries + } + + } else { + + entryArr := make([]manifesttypes.ManifestEntry, 0) + manifestList[image.ImageName()] = append(entryArr, entry) + + } + o := &CopyImageOptions{ srcImage: &srcImageOptions{ imageName: ref, @@ -305,7 +345,7 @@ func (c *CopyImagesToRegistry) Execute(runtime connector.Runtime) error { return errors.Wrap(errors.WithStack(err), fmt.Sprintf("copy image %s to %s failed, retry %d", srcName, destName, maxRetry)) } } - + c.ModuleCache.Set("manifestList", manifestList) return nil } @@ -325,8 +365,8 @@ func (p *PushManifest) Execute(_ connector.Runtime) error { auths := registry.DockerRegistryAuthEntries(p.KubeConf.Cluster.Registry.Auths) auth := new(registry.DockerRegistryEntry) - if _, ok := auths[p.KubeConf.Cluster.Registry.PrivateRegistry]; ok { - auth = auths[p.KubeConf.Cluster.Registry.PrivateRegistry] + if _, ok := auths[p.KubeConf.Cluster.Registry.GetHost()]; ok { + auth = auths[p.KubeConf.Cluster.Registry.GetHost()] } for imageName, platforms := range list {