Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some OCI Optimizations #1764

Merged
merged 83 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
6bf8449
wip
Noxsios Jun 1, 2023
2e47273
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 1, 2023
b070c48
deploying a single component via OCI is working
Noxsios Jun 1, 2023
9866b10
handle required components needing to be always pulled
Noxsios Jun 1, 2023
7c63e10
lint
Noxsios Jun 1, 2023
87b129f
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 1, 2023
7db7554
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 2, 2023
6da2fab
merge main
Noxsios Jun 3, 2023
b4d20e4
committing in case i lose power in a sec
Noxsios Jun 3, 2023
5e826a7
should be working now
Noxsios Jun 3, 2023
c81f1a7
naming
Noxsios Jun 3, 2023
1742243
simpler calculate size
Noxsios Jun 3, 2023
48c642f
fix deploy w/ components after refactor
Noxsios Jun 3, 2023
875b9a9
comments
Noxsios Jun 3, 2023
d55ac15
cleanup
Noxsios Jun 3, 2023
3e6826d
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 3, 2023
2290d4f
cleanup
Noxsios Jun 5, 2023
ef940f9
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 5, 2023
466ba62
feedback from review
Noxsios Jun 6, 2023
b182ab8
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 6, 2023
b32a74f
fetch if you specify an optional component
Noxsios Jun 6, 2023
8ded3dc
update ui to match
Noxsios Jun 6, 2023
b347e8e
update ui to match
Noxsios Jun 6, 2023
2f1d2b4
fix nonsense
Noxsios Jun 6, 2023
7aff506
fix ui api
Noxsios Jun 7, 2023
356054d
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 7, 2023
c2513bf
move publish code into oras.go
Noxsios Jun 7, 2023
44754b9
create inline publish functionality
Noxsios Jun 7, 2023
4539814
docs and schema
Noxsios Jun 7, 2023
ab7f207
remove leaking debug statement
Noxsios Jun 7, 2023
0e41e98
fix references
Noxsios Jun 7, 2023
6d5bb78
docs and schema
Noxsios Jun 7, 2023
9b50987
fix tests
Noxsios Jun 7, 2023
7dd5cce
break out oras.go into separate files
Noxsios Jun 7, 2023
9fcb0c3
fix compiler error
Noxsios Jun 7, 2023
1e5fae9
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 7, 2023
16bd86e
some minor tweaks
Noxsios Jun 7, 2023
de0711e
big improvements
Noxsios Jun 8, 2023
3ee8309
fix
Noxsios Jun 8, 2023
adca46b
fix inspect
Noxsios Jun 8, 2023
b9b220d
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 8, 2023
0ae675e
common remote
Noxsios Jun 8, 2023
dc3563d
Update src/pkg/packager/create.go
Noxsios Jun 8, 2023
47a47d1
common oci concurrency
Noxsios Jun 8, 2023
88b5bd7
common oci concurrency
Noxsios Jun 8, 2023
6f335d2
docs and schema
Noxsios Jun 8, 2023
d72337a
feedback from review
Noxsios Jun 8, 2023
1056387
feedback from review
Noxsios Jun 8, 2023
cdd3751
fix
Noxsios Jun 8, 2023
7213bd1
fix remove oci://
Noxsios Jun 8, 2023
cd03e7a
add remove oci:// to a test
Noxsios Jun 8, 2023
c109b5c
fix inspect
Noxsios Jun 8, 2023
1d21c3d
hide output-directory flag and alias
Noxsios Jun 8, 2023
bacfb7e
messaging
Noxsios Jun 8, 2023
5ec371f
add spinner to writing tarball
Noxsios Jun 8, 2023
2591ad3
docs and schema
Noxsios Jun 8, 2023
80103a5
lint
Noxsios Jun 8, 2023
ef9351d
fix tests
Noxsios Jun 10, 2023
85fa6ce
cleanup
Noxsios Jun 10, 2023
092fb1b
fix inspect test
Noxsios Jun 12, 2023
8421293
printing tweaks
Noxsios Jun 12, 2023
b18de26
fix test 50
Noxsios Jun 12, 2023
8b48fd5
message tweak
Noxsios Jun 12, 2023
ef5eb56
message tweak
Noxsios Jun 12, 2023
82b259b
message tweak
Noxsios Jun 12, 2023
d743f78
message tweak
Noxsios Jun 12, 2023
f6a4ae0
testing github group
Noxsios Jun 12, 2023
aadcfd5
feedback from review
Noxsios Jun 12, 2023
63ea4a5
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 12, 2023
9137417
Merge branch 'main' into 1763-oci-layer-optimizations
Racer159 Jun 12, 2023
7357b3e
Update src/pkg/oci/pull.go
Noxsios Jun 13, 2023
5740e81
Update src/internal/api/components/list.go
Noxsios Jun 13, 2023
1f357d5
Update src/pkg/oci/pull.go
Noxsios Jun 13, 2023
6e04b29
Update src/pkg/packager/common.go
Noxsios Jun 13, 2023
4a398da
Update src/pkg/utils/checksum.go
Noxsios Jun 13, 2023
a6a7a1b
feedback from review
Noxsios Jun 13, 2023
1e176f1
feedback from review
Noxsios Jun 13, 2023
d2588b1
Merge branch 'main' into 1763-oci-layer-optimizations
Noxsios Jun 13, 2023
2dbac28
feedback from review
Noxsios Jun 13, 2023
44611f0
verify agg checksums exist before validating
Noxsios Jun 13, 2023
d4e1bec
check agg checksum within validate
Noxsios Jun 13, 2023
4e76a6f
dont validate checksums on packages that do not have agg checksums
Noxsios Jun 13, 2023
06c5d04
lint
Noxsios Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ const (
ZarfSBOMTar = "sboms.tar"
ZarfPackagePrefix = "zarf-package-"

ZarfComponentsDir = "components"

ZarfInClusterContainerRegistryNodePort = 31999

ZarfInClusterGitServiceURL = "http://zarf-gitea-http.zarf.svc.cluster.local:3000"
Expand Down
14 changes: 10 additions & 4 deletions src/pkg/packager/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func createPaths() (paths types.TempPaths, err error) {
InjectBinary: filepath.Join(basePath, "zarf-injector"),
SeedImages: filepath.Join(basePath, "seed-images"),
Images: filepath.Join(basePath, "images"),
Components: filepath.Join(basePath, "components"),
Components: filepath.Join(basePath, config.ZarfComponentsDir),
SbomTar: filepath.Join(basePath, config.ZarfSBOMTar),
Sboms: filepath.Join(basePath, "sboms"),
Checksums: filepath.Join(basePath, config.ZarfChecksumsTxt),
Expand Down Expand Up @@ -272,7 +272,7 @@ func (p *Packager) loadZarfPkg() error {
}

// Load the config from the extracted archive zarf.yaml
spinner.Updatef("Loading the zarf package config")
spinner.Updatef("Loading the Zarf package config")
configPath := p.tmp.ZarfYaml
if err := p.readYaml(configPath); err != nil {
return fmt.Errorf("unable to read the zarf.yaml in %s: %w", p.tmp.Base, err)
Expand Down Expand Up @@ -474,7 +474,13 @@ func (p *Packager) validatePackageChecksums() error {
itemPath := strs[1]
expectedShasum := strs[0]

actualShasum, err := utils.GetSHA256OfFile(filepath.Join(p.tmp.Base, itemPath))
path := filepath.Join(p.tmp.Base, itemPath)
if utils.InvalidPath(path) {
Noxsios marked this conversation as resolved.
Show resolved Hide resolved
message.Debugf("skipping checksum of %s as it does not exist", path)
continue
}
Racer159 marked this conversation as resolved.
Show resolved Hide resolved

actualShasum, err := utils.GetSHA256OfFile(path)
if err != nil {
return err
}
Expand All @@ -483,7 +489,7 @@ func (p *Packager) validatePackageChecksums() error {
return fmt.Errorf("mismatch on the checksum of the %s file (expected: %s, actual: %s)", itemPath, expectedShasum, actualShasum)
}

filepathMap[filepath.Join(p.tmp.Base, itemPath)] = true
filepathMap[path] = true
}

for path, processed := range filepathMap {
Expand Down
8 changes: 4 additions & 4 deletions src/pkg/packager/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (p *Packager) getChildComponent(parent types.ZarfComponent, pathAncestry st
return child, fmt.Errorf("unable to create cache path %s: %w", cachePath, err)
}

componentLayer := filepath.Join("components", fmt.Sprintf("%s.tar", childComponentName))
componentLayer := filepath.Join(config.ZarfComponentsDir, fmt.Sprintf("%s.tar", childComponentName))
err = p.handleOciPackage(skelURL, cachePath, 3, componentLayer)
if err != nil {
return child, fmt.Errorf("unable to pull skeleton from %s: %w", skelURL, err)
Expand Down Expand Up @@ -145,15 +145,15 @@ func (p *Packager) getChildComponent(parent types.ZarfComponent, pathAncestry st

// If it's OCI, we need to unpack the component tarball
if parent.Import.URL != "" {
dir := filepath.Join(cachePath, "components", child.Name)
parent.Import.Path = filepath.Join(parent.Import.Path, "components", child.Name)
dir := filepath.Join(cachePath, config.ZarfComponentsDir, child.Name)
parent.Import.Path = filepath.Join(parent.Import.Path, config.ZarfComponentsDir, child.Name)
if !utils.InvalidPath(dir) {
err = os.RemoveAll(dir)
if err != nil {
return child, fmt.Errorf("unable to remove composed component cache path %s: %w", cachePath, err)
}
}
err = archiver.Unarchive(fmt.Sprintf("%s.tar", dir), filepath.Join(cachePath, "components"))
err = archiver.Unarchive(fmt.Sprintf("%s.tar", dir), filepath.Join(cachePath, config.ZarfComponentsDir))
if err != nil {
return child, fmt.Errorf("unable to unpack composed component tarball: %w", err)
}
Expand Down
123 changes: 110 additions & 13 deletions src/pkg/packager/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,21 @@ import (
"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/types"
goyaml "github.com/goccy/go-yaml"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content"
"oras.land/oras-go/v2/content/file"
"oras.land/oras-go/v2/registry"
)

var (
indexPath = filepath.Join("images", "index.json")
ociLayoutPat = filepath.Join("images", "oci-layout")
blobsDir = filepath.Join("images", "blobs", "sha256")
)

// handlePackagePath If provided package is a URL download it to a temp directory.
func (p *Packager) handlePackagePath() error {
message.Debug("packager.handlePackagePath()")
Expand All @@ -41,7 +49,22 @@ func (p *Packager) handlePackagePath() error {
if utils.IsOCIURL(opts.PackagePath) {
ociURL := opts.PackagePath
p.cfg.DeployOpts.PackagePath = p.tmp.Base
return p.handleOciPackage(ociURL, p.tmp.Base, p.cfg.PublishOpts.CopyOptions.Concurrency)
requestedComponents := getRequestedComponentList(p.cfg.DeployOpts.Components)
layersToPull := []string{}
for _, c := range requestedComponents {
layersToPull = append(layersToPull, filepath.Join(config.ZarfComponentsDir, fmt.Sprintf("%s.tar", c)))
}
if len(requestedComponents) > 0 {
layersToPull = append(layersToPull, config.ZarfSBOMTar)
layersToPull = append(layersToPull, ociLayoutPat)
layersToPull = append(layersToPull, indexPath)
layers, err := getLayersToPullFromRequestedComponents(ociURL, requestedComponents)
if err != nil {
return fmt.Errorf("unable to get published component image layers: %s", err.Error())
}
layersToPull = append(layersToPull, layers...)
}
return p.handleOciPackage(ociURL, p.tmp.Base, p.cfg.PublishOpts.CopyOptions.Concurrency, layersToPull...)
}

// Handle case where deploying remote package validated via sget
Expand Down Expand Up @@ -159,18 +182,8 @@ func (p *Packager) handleOciPackage(url string, out string, concurrency int, lay

copyOpts := oras.DefaultCopyOptions
copyOpts.Concurrency = concurrency
copyOpts.OnCopySkipped = func(ctx context.Context, desc ocispec.Descriptor) error {
title := desc.Annotations[ocispec.AnnotationTitle]
var format string
if title != "" {
format = fmt.Sprintf("%s %s", desc.Digest.Encoded()[:12], utils.First30last30(title))
} else {
format = fmt.Sprintf("%s [%s]", desc.Digest.Encoded()[:12], desc.MediaType)
}
message.Successf(format)
return nil
}
copyOpts.PostCopy = copyOpts.OnCopySkipped
copyOpts.OnCopySkipped = utils.PrintLayerExists
copyOpts.PostCopy = utils.PrintLayerExists
isPartialPull := len(layers) > 0
if isPartialPull {
alwaysPull := []string{config.ZarfYAML, config.ZarfChecksumsTxt, config.ZarfYAMLSignature}
Expand Down Expand Up @@ -272,3 +285,87 @@ func pullLayer(dst *utils.OrasRemote, desc ocispec.Descriptor, out string) error
err = utils.WriteFile(out, bytes)
return err
}

// getLayersToPullFromRequestedComponents returns a list of layers to pull from a Zarf OCI package given a list of components
func getLayersToPullFromRequestedComponents(url string, requestedComponents []string) (layers []string, err error) {
ref, err := registry.ParseReference(strings.TrimPrefix(url, utils.OCIURLPrefix))
if err != nil {
return nil, fmt.Errorf("failed to parse OCI reference: %w", err)
}
src, err := utils.NewOrasRemote(ref)
if err != nil {
return nil, err
}
manifest, err := getManifest(src)
if err != nil {
return nil, err
}
zarfYamlDescriptor := utils.Find(manifest.Layers, func(layer ocispec.Descriptor) bool {
return layer.Annotations[ocispec.AnnotationTitle] == config.ZarfYAML
})
zarfYamlBytes, err := content.FetchAll(src.Context, src, zarfYamlDescriptor)
if err != nil {
return nil, err
}
pkg := types.ZarfPackage{}
err = goyaml.Unmarshal(zarfYamlBytes, &pkg)
if err != nil {
return nil, err
}
images := []string{}
for _, name := range requestedComponents {
component := utils.Find(pkg.Components, func(component types.ZarfComponent) bool {
return component.Name == name
})
if component.Name == "" {
return nil, fmt.Errorf("component %s does not exist in this package", name)
}
}
for _, component := range pkg.Components {
// If we requested this component, or it is required, we need to pull its images
if utils.SliceContains(requestedComponents, component.Name) || component.Required {
images = append(images, component.Images...)
}
// If we did not request this component, but it is required, we need to pull it
if !utils.SliceContains(requestedComponents, component.Name) && component.Required {
layers = append(layers, filepath.Join(config.ZarfComponentsDir, component.Name))
}
}

if len(images) > 0 {
indexDescriptor := utils.Find(manifest.Layers, func(layer ocispec.Descriptor) bool {
return layer.Annotations[ocispec.AnnotationTitle] == indexPath
})
indexBytes, err := content.FetchAll(src.Context, src, indexDescriptor)
if err != nil {
return nil, err
}
index := ocispec.Index{}
err = json.Unmarshal(indexBytes, &index)
if err != nil {
return nil, err
}
for _, image := range images {
manifestDescriptor := utils.Find(index.Manifests, func(layer ocispec.Descriptor) bool {
return layer.Annotations[ocispec.AnnotationBaseImageName] == image
})
manifestBytes, err := content.FetchAll(src.Context, src, manifestDescriptor)
if err != nil {
return nil, err
}
manifest := ocispec.Manifest{}
err = json.Unmarshal(manifestBytes, &manifest)
if err != nil {
return nil, err
}
layers = append(layers, filepath.Join(blobsDir, strings.TrimPrefix(manifestDescriptor.Digest.String(), "sha256:")))
layers = append(layers, filepath.Join(blobsDir, strings.TrimPrefix(manifest.Config.Digest.String(), "sha256:")))
for _, layer := range manifest.Layers {
pathInPkg := filepath.Join(blobsDir, strings.TrimPrefix(layer.Digest.String(), "sha256:"))
layers = append(layers, pathInPkg)
}
}
}

return layers, nil
}
Noxsios marked this conversation as resolved.
Show resolved Hide resolved