Skip to content

Commit

Permalink
Allow shasums to be present in images (#2028)
Browse files Browse the repository at this point in the history
## Description

This allows shasum references to work with Zarf by swapping the crane
tag parsing code with the docker library.

## Related Issue

Fixes #1221 

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Other (security config, docs update, etc)

## Checklist before merging

- [ ] Test, docs, adr added or updated as needed
- [x] [Contributor Guide
Steps](https://github.com/defenseunicorns/zarf/blob/main/CONTRIBUTING.md#developer-workflow)
followed
  • Loading branch information
Racer159 authored Sep 30, 2023
1 parent 8f4d55f commit b3cb69e
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 161 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/test-e2e-shim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ on:
- "docs/**"
- "CODEOWNERS"

permissions:
contents: read

# This is here to act as a shim for branch protection rules to work correctly.
# This is ugly but this seems to be the best way to do this since:
# - Job names in a workflow must be unique
Expand Down
22 changes: 11 additions & 11 deletions src/cmd/tools/crane.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func pruneImages(_ *cobra.Command, _ []string) error {
if err != nil {
return err
}
imageRefToDigest := map[string]string{}
referenceToDigest := map[string]string{}
for _, image := range imageCatalog {
imageRef := fmt.Sprintf("%s/%s", registryAddress, image)
tags, err := crane.ListTags(imageRef, authOption)
Expand All @@ -280,28 +280,28 @@ func pruneImages(_ *cobra.Command, _ []string) error {
if err != nil {
return err
}
imageRefToDigest[taggedImageRef] = digest
referenceToDigest[taggedImageRef] = digest
}
}

// Figure out which images are in the registry but not needed by packages
imageDigestsToPrune := map[string]bool{}
for imageRef, digest := range imageRefToDigest {
for digestRef, digest := range referenceToDigest {
if _, ok := pkgImages[digest]; !ok {
ref, err := transform.ParseImageRef(imageRef)
refInfo, err := transform.ParseImageRef(digestRef)
if err != nil {
return err
}
imageRef = fmt.Sprintf("%s@%s", ref.Name, digest)
imageDigestsToPrune[imageRef] = true
digestRef = fmt.Sprintf("%s@%s", refInfo.Name, digest)
imageDigestsToPrune[digestRef] = true
}
}

if len(imageDigestsToPrune) > 0 {
message.Note(lang.CmdToolsRegistryPruneImageList)

for imageRef := range imageDigestsToPrune {
message.Info(imageRef)
for digestRef := range imageDigestsToPrune {
message.Info(digestRef)
}

confirm := config.CommonOptions.Confirm
Expand All @@ -317,9 +317,9 @@ func pruneImages(_ *cobra.Command, _ []string) error {
}
}
if confirm {
// Delete the image references that are to be pruned
for imageRef := range imageDigestsToPrune {
err = crane.Delete(imageRef, authOption)
// Delete the digest references that are to be pruned
for digestRef := range imageDigestsToPrune {
err = crane.Delete(digestRef, authOption)
if err != nil {
return err
}
Expand Down
27 changes: 13 additions & 14 deletions src/internal/cluster/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
var payloadChunkSize = 1024 * 768

// StartInjectionMadness initializes a Zarf injection into the cluster.
func (c *Cluster) StartInjectionMadness(tempPath types.TempPaths, injectorSeedTags []string) {
func (c *Cluster) StartInjectionMadness(tempPath types.TempPaths, injectorSeedSrcs []string) {
spinner := message.NewProgressSpinner("Attempting to bootstrap the seed image into the cluster")
defer spinner.Stop()

Expand Down Expand Up @@ -59,7 +59,7 @@ func (c *Cluster) StartInjectionMadness(tempPath types.TempPaths, injectorSeedTa
}

spinner.Updatef("Loading the seed image from the package")
if seedImages, err = c.loadSeedImages(tempPath, injectorSeedTags, spinner); err != nil {
if seedImages, err = c.loadSeedImages(tempPath, injectorSeedSrcs, spinner); err != nil {
spinner.Fatalf(err, "Unable to load the injector seed image from the package")
}

Expand Down Expand Up @@ -129,37 +129,36 @@ func (c *Cluster) StopInjectionMadness() error {
return c.DeleteService(ZarfNamespaceName, "zarf-injector")
}

func (c *Cluster) loadSeedImages(tempPath types.TempPaths, injectorSeedTags []string, spinner *message.Spinner) ([]transform.Image, error) {
func (c *Cluster) loadSeedImages(tempPath types.TempPaths, injectorSeedSrcs []string, spinner *message.Spinner) ([]transform.Image, error) {
seedImages := []transform.Image{}
tagToDigest := make(map[string]string)
localReferenceToDigest := make(map[string]string)

// Load the injector-specific images and save them as seed-images
for _, src := range injectorSeedTags {
for _, src := range injectorSeedSrcs {
spinner.Updatef("Loading the seed image '%s' from the package", src)

img, err := utils.LoadOCIImage(tempPath.Images, src)
ref, err := transform.ParseImageRef(src)
if err != nil {
return seedImages, fmt.Errorf("failed to create ref for image %s: %w", src, err)
}
img, err := utils.LoadOCIImage(tempPath.Images, ref)
if err != nil {
return seedImages, err
}

crane.SaveOCI(img, tempPath.SeedImages)

imgRef, err := transform.ParseImageRef(src)
if err != nil {
return seedImages, err
}
seedImages = append(seedImages, imgRef)
seedImages = append(seedImages, ref)

// Get the image digest so we can set an annotation in the image.json later
imgDigest, err := img.Digest()
if err != nil {
return seedImages, err
}
// This is done _without_ the domain (different from pull.go) since the injector only handles local images
tagToDigest[imgRef.Path+imgRef.TagOrDigest] = imgDigest.String()
localReferenceToDigest[ref.Path+ref.TagOrDigest] = imgDigest.String()
}

if err := utils.AddImageNameAnnotation(tempPath.SeedImages, tagToDigest); err != nil {
if err := utils.AddImageNameAnnotation(tempPath.SeedImages, localReferenceToDigest); err != nil {
return seedImages, fmt.Errorf("unable to format OCI layout: %w", err)
}

Expand Down
19 changes: 10 additions & 9 deletions src/internal/packager/images/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import (
"os"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/types"
"github.com/google/go-containerregistry/pkg/crane"
v1 "github.com/google/go-containerregistry/pkg/v1"
)

// ImgConfig is the main struct for managing container images.
type ImgConfig struct {
// ImageConfig is the main struct for managing container images.
type ImageConfig struct {
ImagesPath string

ImgList []string
ImageList []transform.Image

RegInfo types.RegistryInfo

Expand All @@ -33,17 +34,17 @@ type ImgConfig struct {
}

// GetLegacyImgTarballPath returns the ImagesPath as if it were a path to a tarball instead of a directory.
func (i *ImgConfig) GetLegacyImgTarballPath() string {
func (i *ImageConfig) GetLegacyImgTarballPath() string {
return fmt.Sprintf("%s.tar", i.ImagesPath)
}

// LoadImageFromPackage returns a v1.Image from the image tag specified, or an error if the image cannot be found.
func (i ImgConfig) LoadImageFromPackage(imgTag string) (v1.Image, error) {
// If the package still has a images.tar that contains all of the images, use crane to load the specific tag we want
// LoadImageFromPackage returns a v1.Image from the specified image, or an error if the image cannot be found.
func (i ImageConfig) LoadImageFromPackage(refInfo transform.Image) (v1.Image, error) {
// If the package still has a images.tar that contains all of the images, use crane to load the specific reference (crane tag) we want
if _, statErr := os.Stat(i.GetLegacyImgTarballPath()); statErr == nil {
return crane.LoadTag(i.GetLegacyImgTarballPath(), imgTag, config.GetCraneOptions(i.Insecure, i.Architectures...)...)
return crane.LoadTag(i.GetLegacyImgTarballPath(), refInfo.Reference, config.GetCraneOptions(i.Insecure, i.Architectures...)...)
}

// Load the image from the OCI formatted images directory
return utils.LoadOCIImage(i.ImagesPath, imgTag)
return utils.LoadOCIImage(i.ImagesPath, refInfo)
}
Loading

0 comments on commit b3cb69e

Please sign in to comment.