From b3e21806feaad915c0cfa0b665abc71aeb3d17ba Mon Sep 17 00:00:00 2001 From: Zack Brady Date: Tue, 7 Apr 2026 07:51:25 -0400 Subject: [PATCH] allow multiple prefix references (#532) * allow multiple prefix references * fixed some duplications --- cmd/hauler/cli/store.go | 101 ++++++++++++++++--------------- cmd/hauler/cli/store/add_test.go | 10 +-- cmd/hauler/cli/store/copy.go | 8 +-- cmd/hauler/cli/store/serve.go | 2 +- 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/cmd/hauler/cli/store.go b/cmd/hauler/cli/store.go index 1010a28..ccc03f0 100644 --- a/cmd/hauler/cli/store.go +++ b/cmd/hauler/cli/store.go @@ -250,7 +250,10 @@ func addStoreCopy(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Comman cmd := &cobra.Command{ Use: "copy", Short: "Copy all store content to another location", - Args: cobra.ExactArgs(1), + Example: ` # supported copy target prefixes + registry:// | reg:// | oci:// - Pushes the store to an OCI registry + directory:// | dir:// - Extracts the store to a directory`, + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -291,14 +294,14 @@ func addStoreAddFile(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Com cmd := &cobra.Command{ Use: "file", Short: "Add a file to the store", - Example: `# fetch local file -hauler store add file file.txt + Example: ` # fetch local file + hauler store add file file.txt -# fetch remote file -hauler store add file https://get.rke2.io/install.sh + # fetch remote file + hauler store add file https://get.rke2.io/install.sh -# fetch remote file and assign new name -hauler store add file https://get.hauler.dev --name hauler-install.sh`, + # fetch remote file and assign new name + hauler store add file https://get.hauler.dev --name hauler-install.sh`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -322,24 +325,24 @@ func addStoreAddImage(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Co cmd := &cobra.Command{ Use: "image", Short: "Add a image to the store", - Example: `# fetch image -hauler store add image busybox + Example: ` # fetch image + hauler store add image busybox -# fetch image with repository and tag -hauler store add image library/busybox:stable + # fetch image with repository and tag + hauler store add image library/busybox:stable -# fetch image with full image reference and specific platform -hauler store add image ghcr.io/hauler-dev/hauler-debug:v1.2.0 --platform linux/amd64 + # fetch image with full image reference and specific platform + hauler store add image ghcr.io/hauler-dev/hauler-debug:v1.2.0 --platform linux/amd64 -# fetch image with full image reference via digest -hauler store add image gcr.io/distroless/base@sha256:7fa7445dfbebae4f4b7ab0e6ef99276e96075ae42584af6286ba080750d6dfe5 + # fetch image with full image reference via digest + hauler store add image gcr.io/distroless/base@sha256:7fa7445dfbebae4f4b7ab0e6ef99276e96075ae42584af6286ba080750d6dfe5 -# fetch image with full image reference, specific platform, and signature verification -curl -sfOL https://raw.githubusercontent.com/rancherfederal/carbide-releases/main/carbide-key.pub -hauler store add image rgcrprod.azurecr.us/rancher/rke2-runtime:v1.31.5-rke2r1 --platform linux/amd64 --key carbide-key.pub + # fetch image with full image reference, specific platform, and signature verification + curl -sfOL https://raw.githubusercontent.com/rancherfederal/carbide-releases/main/carbide-key.pub + hauler store add image rgcrprod.azurecr.us/rancher/rke2-runtime:v1.31.5-rke2r1 --platform linux/amd64 --key carbide-key.pub -# fetch image and rewrite path -hauler store add image busybox --rewrite custom-path/busybox:latest`, + # fetch image and rewrite path + hauler store add image busybox --rewrite custom-path/busybox:latest`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -363,26 +366,26 @@ func addStoreAddChart(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Co cmd := &cobra.Command{ Use: "chart", Short: "Add a helm chart to the store", - Example: `# fetch local helm chart -hauler store add chart path/to/chart/directory --repo . + Example: ` # fetch local helm chart + hauler store add chart path/to/chart/directory --repo . -# fetch local compressed helm chart -hauler store add chart path/to/chart.tar.gz --repo . + # fetch local compressed helm chart + hauler store add chart path/to/chart.tar.gz --repo . -# fetch remote oci helm chart -hauler store add chart hauler-helm --repo oci://ghcr.io/hauler-dev + # fetch remote oci helm chart + hauler store add chart hauler-helm --repo oci://ghcr.io/hauler-dev -# fetch remote oci helm chart with version -hauler store add chart hauler-helm --repo oci://ghcr.io/hauler-dev --version 1.2.0 + # fetch remote oci helm chart with version + hauler store add chart hauler-helm --repo oci://ghcr.io/hauler-dev --version 1.2.0 -# fetch remote helm chart -hauler store add chart rancher --repo https://releases.rancher.com/server-charts/stable + # fetch remote helm chart + hauler store add chart rancher --repo https://releases.rancher.com/server-charts/stable -# fetch remote helm chart with specific version -hauler store add chart rancher --repo https://releases.rancher.com/server-charts/latest --version 2.10.1 + # fetch remote helm chart with specific version + hauler store add chart rancher --repo https://releases.rancher.com/server-charts/latest --version 2.10.1 -# fetch remote helm chart and rewrite path -hauler store add chart hauler-helm --repo oci://ghcr.io/hauler-dev --rewrite custom-path/hauler-chart:latest`, + # fetch remote helm chart and rewrite path + hauler store add chart hauler-helm --repo oci://ghcr.io/hauler-dev --rewrite custom-path/hauler-chart:latest`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -405,26 +408,26 @@ func addStoreRemove(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Comm cmd := &cobra.Command{ Use: "remove ", Short: "(EXPERIMENTAL) Remove an artifact from the content store", - Example: `# remove an image using full store reference -hauler store info -hauler store remove index.docker.io/library/busybox:stable + Example: ` # remove an image using full store reference + hauler store info + hauler store remove index.docker.io/library/busybox:stable -# remove a chart using full store reference -hauler store info -hauler store remove hauler/rancher:2.8.4 + # remove a chart using full store reference + hauler store info + hauler store remove hauler/rancher:2.8.4 -# remove a file using full store reference -hauler store info -hauler store remove hauler/rke2-install.sh + # remove a file using full store reference + hauler store info + hauler store remove hauler/rke2-install.sh -# remove any artifact with the latest tag -hauler store remove :latest + # remove any artifact with the latest tag + hauler store remove :latest -# remove any artifact with 'busybox' in the reference -hauler store remove busybox + # remove any artifact with 'busybox' in the reference + hauler store remove busybox -# force remove without verification -hauler store remove busybox:latest --force`, + # force remove without verification + hauler store remove busybox:latest --force`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() diff --git a/cmd/hauler/cli/store/add_test.go b/cmd/hauler/cli/store/add_test.go index a72f2a1..82799f0 100644 --- a/cmd/hauler/cli/store/add_test.go +++ b/cmd/hauler/cli/store/add_test.go @@ -282,12 +282,12 @@ func TestRewriteReference(t *testing.T) { t.Run("path-only rewrite strips library/ prefix from docker hub official image", func(t *testing.T) { s := newTestStore(t) seedStoreDescriptor(t, s, map[string]string{ - ocispec.AnnotationRefName: "library/nginx:latest", + ocispec.AnnotationRefName: "library/nginx:latest", consts.ContainerdImageNameKey: "index.docker.io/library/nginx:latest", }) - oldRef, _ := name.NewTag("nginx:latest") // → index.docker.io/library/nginx:latest - newRef, _ := name.NewTag("nginx:v2") // → index.docker.io/library/nginx:v2 + oldRef, _ := name.NewTag("nginx:latest") // → index.docker.io/library/nginx:latest + newRef, _ := name.NewTag("nginx:v2") // → index.docker.io/library/nginx:v2 rawRewrite := "nginx:v2" if err := rewriteReference(ctx, s, oldRef, newRef, rawRewrite); err != nil { @@ -300,7 +300,7 @@ func TestRewriteReference(t *testing.T) { t.Run("explicit docker.io rewrite preserves library/ prefix", func(t *testing.T) { s := newTestStore(t) seedStoreDescriptor(t, s, map[string]string{ - ocispec.AnnotationRefName: "library/nginx:latest", + ocispec.AnnotationRefName: "library/nginx:latest", consts.ContainerdImageNameKey: "index.docker.io/library/nginx:latest", }) @@ -318,7 +318,7 @@ func TestRewriteReference(t *testing.T) { t.Run("explicit index.docker.io rewrite preserves library/ prefix", func(t *testing.T) { s := newTestStore(t) seedStoreDescriptor(t, s, map[string]string{ - ocispec.AnnotationRefName: "library/nginx:latest", + ocispec.AnnotationRefName: "library/nginx:latest", consts.ContainerdImageNameKey: "index.docker.io/library/nginx:latest", }) diff --git a/cmd/hauler/cli/store/copy.go b/cmd/hauler/cli/store/copy.go index 756b562..e99868a 100644 --- a/cmd/hauler/cli/store/copy.go +++ b/cmd/hauler/cli/store/copy.go @@ -34,8 +34,8 @@ func CopyCmd(ctx context.Context, o *flags.CopyOpts, s *store.Layout, targetRef components := strings.SplitN(targetRef, "://", 2) switch components[0] { - case "dir": - l.Debugf("identified directory target reference of [%s]", components[1]) + case "directory", "dir": + l.Debugf("identified [directory] target reference of [%s]", components[1]) // Create destination directory if it doesn't exist if err := os.MkdirAll(components[1], 0755); err != nil { @@ -173,8 +173,8 @@ func CopyCmd(ctx context.Context, o *flags.CopyOpts, s *store.Layout, targetRef return err } - case "registry": - l.Debugf("identified registry target reference of [%s]", components[1]) + case "registry", "reg", "oci": + l.Debugf("identified [registry] target reference of [%s]", components[1]) registryOpts := content.RegistryOptions{ PlainHTTP: o.PlainHTTP, Insecure: o.Insecure, diff --git a/cmd/hauler/cli/store/serve.go b/cmd/hauler/cli/store/serve.go index 35401f7..b4cb168 100644 --- a/cmd/hauler/cli/store/serve.go +++ b/cmd/hauler/cli/store/serve.go @@ -145,7 +145,7 @@ func ServeFilesCmd(ctx context.Context, o *flags.ServeFilesOpts, s *store.Layout } opts := &flags.CopyOpts{StoreRootOpts: &flags.StoreRootOpts{}} - if err := CopyCmd(ctx, opts, s, "dir://"+o.RootDir, ro); err != nil { + if err := CopyCmd(ctx, opts, s, "directory://"+o.RootDir, ro); err != nil { return err }