Some OCI Improvements
tldr; Zarf's latest release (v0.28.0) contains a few cool improvements to its OCI (Open Container Initiative) library code and CLI options.
Inline Publishing
There is now a new option for the destination of a Zarf package create!
zarf package create . -o oci://ghcr.io/defenseunicorns/packages
I call this guy inline publishing because it is essentially the same thing as doing a create
followed by a publish
. This is useful for when you want to create a package and publish it to a registry in one step. In a future release, I plan to combine this with differential
packages, so that you can publish a package and only pull images that have changed (saving massive amounts of time and bandwidth).
Slimmer Deployments
Previously, when you did a zarf package deploy oci://
with the --components
flag, each and every layer from that package was pulled down before the package could be deployed. This was a bit of a pain, especially when you only wanted to deploy a single component.
Now, that same command will only pull down the layers that are needed for the component(s) you are deploying (this functionality only occurs when you use --confirm
, as you might specify other components interactively after the fact).
# only pulls down the layers needed for dubbd-aws (this is just an example)
zarf package deploy oci://ghcr.io/defenseunicorns/packages/dubbd-aws:0.3.0-amd64 --components dubbd-aws --confirm
Removing an OCI package
Previously, in order to remove a package deployed via zarf package deploy oci://
, you had to do a zarf package pull && zarf package remove <tarball>
.
Now you can do:
# to remove all components
zarf package remove oci://ghcr.io/defenseunicorns/packages/dubbd-aws:0.3.0-amd64
# or to remove a specific component
zarf package remove oci://ghcr.io/defenseunicorns/packages/dubbd-aws:0.3.0-amd64 --components dubbd-aws
The
--oci-concurrency
flag is now available on allzarf package
commands that interact with OCI packages. This allows you to specify the number of concurrent pulls/pushes that can occur at once. It is also accessible via thepackage.oci_concurrency
config value.
Consuming Zarf as a Library
In !1764, I re-wrote how our OCI library code (which uses the ORAS (OCI Registry As Storage) library under the hood) is accessed. Now you can easily do stuff like:
import (
"fmt"
"path/filepath"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/oci"
)
func main() {
ver := "0.3.0"
arch := "amd64"
url := fmt.Sprintf("ghcr.io/defenseunicorns/packages/dubbd-aws:%s-%s", ver, arch)
// create a new client
// auth checking is handled immediately
client, err := oci.NewOrasRemote(url)
if err != nil {
message.Fatal(err, "Failed to create OCI client")
}
dst := filepath.Join("unpacked-dubbd-aws")
err = utils.CreateDirectory(dst, 0755)
if err != nil {
message.Fatal(err, "Failed to create directory")
}
// pull the package into dst with a concurrency of 10
err = client.PullPackage(dst, 10)
if err != nil {
message.Fatalf(err, "Failed to pull package %s", client.Reference)
}
// contents of the package are now in dst
//
// $ ls -R unpacked-dubbd-aws
//
// zarf.yaml
// checksums.txt
// components/...
// blobs/sha256/...
}
There are also a ton of other useful helper functions (like PullPackageMetadata
, FetchZarfYaml
, LayersFromRequestedComponents
etc...) that you can use to build more advanced workflows.
Much of this work was a necessary precursor to the upcoming zarf bundle
command and bundler
library. I'm excited to share more about that soon!