From 1b77295438b7d405467fbde7985e22d3594c2529 Mon Sep 17 00:00:00 2001 From: Zack Brady Date: Thu, 14 Nov 2024 21:37:25 -0500 Subject: [PATCH] updated/fixed hauler directory (#354) * added env variables for haulerDir/tempDir * updated hauler directory for the install script * cleanup/fixes for install script * updated variables based on feedback * revert "updated variables based on feedback" * reverts commit 54f7a4d6959cce72cbefa83ada6becc63882beb8 * minor restructure to root flags * updated logic to include haulerdir flag * cleaned up/formatted new logic * more cleanup and formatting --- cmd/hauler/cli/cli.go | 35 +++++++----- cmd/hauler/cli/completion.go | 19 +++---- cmd/hauler/cli/login.go | 8 +-- cmd/hauler/cli/store.go | 95 ++++++++++++++++----------------- cmd/hauler/cli/store/add.go | 13 +++-- cmd/hauler/cli/store/copy.go | 6 +-- cmd/hauler/cli/store/load.go | 17 ++++-- cmd/hauler/cli/store/save.go | 2 +- cmd/hauler/cli/store/serve.go | 8 +-- cmd/hauler/cli/store/sync.go | 14 ++--- cmd/hauler/cli/version.go | 3 +- cmd/hauler/main.go | 11 ++-- install.sh | 36 ++++++++----- internal/flags/cli.go | 12 ++++- internal/flags/save.go | 7 ++- internal/flags/serve.go | 11 ++-- internal/flags/store.go | 6 ++- internal/mapper/mappers.go | 4 +- internal/server/file.go | 5 +- pkg/consts/consts.go | 35 +++++++++--- pkg/content/chart/chart_test.go | 6 +-- pkg/content/oci.go | 5 +- pkg/cosign/cosign.go | 62 ++++++++++++--------- pkg/log/log.go | 6 +-- pkg/store/store.go | 8 +-- pkg/store/store_test.go | 6 +-- 26 files changed, 256 insertions(+), 184 deletions(-) diff --git a/cmd/hauler/cli/cli.go b/cmd/hauler/cli/cli.go index 7ebc1361..61fe0c59 100644 --- a/cmd/hauler/cli/cli.go +++ b/cmd/hauler/cli/cli.go @@ -1,22 +1,33 @@ package cli import ( + "context" + "embed" + "github.com/spf13/cobra" "hauler.dev/go/hauler/internal/flags" + "hauler.dev/go/hauler/pkg/consts" + "hauler.dev/go/hauler/pkg/cosign" "hauler.dev/go/hauler/pkg/log" ) -var ro = &flags.CliRootOpts{} - -func New() *cobra.Command { +func New(ctx context.Context, binaries embed.FS, ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ - Use: "hauler", - Short: "Airgap Swiss Army Knife", + Use: "hauler", + Short: "Airgap Swiss Army Knife", + Example: " View the Docs: https://docs.hauler.dev\n Environment Variables: " + consts.HaulerDir + " | " + consts.HaulerTempDir, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - l := log.FromContext(cmd.Context()) + l := log.FromContext(ctx) l.SetLevel(ro.LogLevel) l.Debugf("running cli command [%s]", cmd.CommandPath()) + + // ensure cosign binary is available + if err := cosign.EnsureBinaryExists(ctx, binaries, ro); err != nil { + l.Errorf("cosign binary missing: %v", err) + return err + } + return nil }, RunE: func(cmd *cobra.Command, args []string) error { @@ -24,14 +35,12 @@ func New() *cobra.Command { }, } - pf := cmd.PersistentFlags() - pf.StringVarP(&ro.LogLevel, "log-level", "l", "info", "") + flags.AddRootFlags(cmd, ro) - // Add subcommands - addLogin(cmd) - addStore(cmd) - addVersion(cmd) - addCompletion(cmd) + addLogin(cmd, ro) + addStore(cmd, ro) + addVersion(cmd, ro) + addCompletion(cmd, ro) return cmd } diff --git a/cmd/hauler/cli/completion.go b/cmd/hauler/cli/completion.go index bc44b9c3..4caeaa70 100644 --- a/cmd/hauler/cli/completion.go +++ b/cmd/hauler/cli/completion.go @@ -5,25 +5,26 @@ import ( "os" "github.com/spf13/cobra" + "hauler.dev/go/hauler/internal/flags" ) -func addCompletion(parent *cobra.Command) { +func addCompletion(parent *cobra.Command, ro *flags.CliRootOpts) { cmd := &cobra.Command{ Use: "completion", Short: "Generate auto-completion scripts for various shells", } cmd.AddCommand( - addCompletionZsh(), - addCompletionBash(), - addCompletionFish(), - addCompletionPowershell(), + addCompletionZsh(ro), + addCompletionBash(ro), + addCompletionFish(ro), + addCompletionPowershell(ro), ) parent.AddCommand(cmd) } -func addCompletionZsh() *cobra.Command { +func addCompletionZsh(ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ Use: "zsh", Short: "Generates auto-completion scripts for zsh", @@ -52,7 +53,7 @@ func addCompletionZsh() *cobra.Command { return cmd } -func addCompletionBash() *cobra.Command { +func addCompletionBash(ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ Use: "bash", Short: "Generates auto-completion scripts for bash", @@ -71,7 +72,7 @@ func addCompletionBash() *cobra.Command { return cmd } -func addCompletionFish() *cobra.Command { +func addCompletionFish(ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ Use: "fish", Short: "Generates auto-completion scripts for fish", @@ -87,7 +88,7 @@ func addCompletionFish() *cobra.Command { return cmd } -func addCompletionPowershell() *cobra.Command { +func addCompletionPowershell(ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ Use: "powershell", Short: "Generates auto-completion scripts for powershell", diff --git a/cmd/hauler/cli/login.go b/cmd/hauler/cli/login.go index 74fcf79d..4fd515cd 100644 --- a/cmd/hauler/cli/login.go +++ b/cmd/hauler/cli/login.go @@ -14,7 +14,7 @@ import ( "hauler.dev/go/hauler/pkg/cosign" ) -func addLogin(parent *cobra.Command) { +func addLogin(parent *cobra.Command, ro *flags.CliRootOpts) { o := &flags.LoginOpts{} cmd := &cobra.Command{ @@ -39,7 +39,7 @@ func addLogin(parent *cobra.Command) { return fmt.Errorf("username and password required") } - return login(ctx, o, arg[0]) + return login(ctx, o, arg[0], ro) }, } o.AddFlags(cmd) @@ -47,13 +47,13 @@ func addLogin(parent *cobra.Command) { parent.AddCommand(cmd) } -func login(ctx context.Context, o *flags.LoginOpts, registry string) error { +func login(ctx context.Context, o *flags.LoginOpts, registry string, ro *flags.CliRootOpts) error { ropts := content.RegistryOptions{ Username: o.Username, Password: o.Password, } - err := cosign.RegistryLogin(ctx, nil, registry, ropts) + err := cosign.RegistryLogin(ctx, nil, registry, ropts, ro) if err != nil { return err } diff --git a/cmd/hauler/cli/store.go b/cmd/hauler/cli/store.go index c4fae8e1..9d1b18fc 100644 --- a/cmd/hauler/cli/store.go +++ b/cmd/hauler/cli/store.go @@ -10,9 +10,9 @@ import ( "hauler.dev/go/hauler/internal/flags" ) -var rootStoreOpts = &flags.StoreRootOpts{} +func addStore(parent *cobra.Command, ro *flags.CliRootOpts) { + rso := &flags.StoreRootOpts{} -func addStore(parent *cobra.Command) { cmd := &cobra.Command{ Use: "store", Aliases: []string{"s"}, @@ -21,24 +21,24 @@ func addStore(parent *cobra.Command) { return cmd.Help() }, } - rootStoreOpts.AddFlags(cmd) + rso.AddFlags(cmd) cmd.AddCommand( - addStoreSync(), - addStoreExtract(), - addStoreLoad(), - addStoreSave(), - addStoreServe(), - addStoreInfo(), - addStoreCopy(), - addStoreAdd(), + addStoreSync(rso, ro), + addStoreExtract(rso, ro), + addStoreLoad(rso, ro), + addStoreSave(rso, ro), + addStoreServe(rso, ro), + addStoreInfo(rso, ro), + addStoreCopy(rso, ro), + addStoreAdd(rso, ro), ) parent.AddCommand(cmd) } -func addStoreExtract() *cobra.Command { - o := &flags.ExtractOpts{StoreRootOpts: rootStoreOpts} +func addStoreExtract(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.ExtractOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "extract", @@ -61,8 +61,8 @@ func addStoreExtract() *cobra.Command { return cmd } -func addStoreSync() *cobra.Command { - o := &flags.SyncOpts{StoreRootOpts: rootStoreOpts} +func addStoreSync(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.SyncOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "sync", @@ -75,7 +75,7 @@ func addStoreSync() *cobra.Command { return err } - return store.SyncCmd(ctx, o, s) + return store.SyncCmd(ctx, o, s, ro) }, } o.AddFlags(cmd) @@ -83,8 +83,8 @@ func addStoreSync() *cobra.Command { return cmd } -func addStoreLoad() *cobra.Command { - o := &flags.LoadOpts{StoreRootOpts: rootStoreOpts} +func addStoreLoad(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.LoadOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "load", @@ -107,7 +107,7 @@ func addStoreLoad() *cobra.Command { return cmd } -func addStoreServe() *cobra.Command { +func addStoreServe(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ Use: "serve", Short: "Serve the content store via an OCI Compliant Registry or Fileserver", @@ -116,16 +116,17 @@ func addStoreServe() *cobra.Command { }, } cmd.AddCommand( - addStoreServeRegistry(), - addStoreServeFiles(), + addStoreServeRegistry(rso, ro), + addStoreServeFiles(rso, ro), ) return cmd } // RegistryCmd serves the registry -func addStoreServeRegistry() *cobra.Command { - o := &flags.ServeRegistryOpts{StoreRootOpts: rootStoreOpts} +func addStoreServeRegistry(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.ServeRegistryOpts{StoreRootOpts: rso} + cmd := &cobra.Command{ Use: "registry", Short: "Serve the OCI Compliant Registry", @@ -137,7 +138,7 @@ func addStoreServeRegistry() *cobra.Command { return err } - return store.ServeRegistryCmd(ctx, o, s) + return store.ServeRegistryCmd(ctx, o, s, ro) }, } @@ -147,8 +148,9 @@ func addStoreServeRegistry() *cobra.Command { } // FileServerCmd serves the file server -func addStoreServeFiles() *cobra.Command { - o := &flags.ServeFilesOpts{StoreRootOpts: rootStoreOpts} +func addStoreServeFiles(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.ServeFilesOpts{StoreRootOpts: rso} + cmd := &cobra.Command{ Use: "fileserver", Short: "Serve the Fileserver", @@ -160,7 +162,7 @@ func addStoreServeFiles() *cobra.Command { return err } - return store.ServeFilesCmd(ctx, o, s) + return store.ServeFilesCmd(ctx, o, s, ro) }, } @@ -169,8 +171,8 @@ func addStoreServeFiles() *cobra.Command { return cmd } -func addStoreSave() *cobra.Command { - o := &flags.SaveOpts{StoreRootOpts: rootStoreOpts} +func addStoreSave(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.SaveOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "save", @@ -193,8 +195,8 @@ func addStoreSave() *cobra.Command { return cmd } -func addStoreInfo() *cobra.Command { - o := &flags.InfoOpts{StoreRootOpts: rootStoreOpts} +func addStoreInfo(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.InfoOpts{StoreRootOpts: rso} var allowedValues = []string{"image", "chart", "file", "sigs", "atts", "sbom", "all"} @@ -224,8 +226,8 @@ func addStoreInfo() *cobra.Command { return cmd } -func addStoreCopy() *cobra.Command { - o := &flags.CopyOpts{StoreRootOpts: rootStoreOpts} +func addStoreCopy(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.CopyOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "copy", @@ -239,7 +241,7 @@ func addStoreCopy() *cobra.Command { return err } - return store.CopyCmd(ctx, o, s, args[0]) + return store.CopyCmd(ctx, o, s, args[0], ro) }, } o.AddFlags(cmd) @@ -247,7 +249,7 @@ func addStoreCopy() *cobra.Command { return cmd } -func addStoreAdd() *cobra.Command { +func addStoreAdd(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Add content to the store", @@ -257,16 +259,16 @@ func addStoreAdd() *cobra.Command { } cmd.AddCommand( - addStoreAddFile(), - addStoreAddImage(), - addStoreAddChart(), + addStoreAddFile(rso, ro), + addStoreAddImage(rso, ro), + addStoreAddChart(rso, ro), ) return cmd } -func addStoreAddFile() *cobra.Command { - o := &flags.AddFileOpts{StoreRootOpts: rootStoreOpts} +func addStoreAddFile(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.AddFileOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "file", @@ -296,8 +298,8 @@ hauler store add file https://get.hauler.dev --name hauler-install.sh`, return cmd } -func addStoreAddImage() *cobra.Command { - o := &flags.AddImageOpts{StoreRootOpts: rootStoreOpts} +func addStoreAddImage(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.AddImageOpts{StoreRootOpts: rso} cmd := &cobra.Command{ Use: "image", @@ -325,7 +327,7 @@ hauler store add image rgcrprod.azurecr.us/hauler/rke2-manifest.yaml:v1.28.12-rk return err } - return store.AddImageCmd(ctx, o, s, args[0]) + return store.AddImageCmd(ctx, o, s, args[0], ro) }, } o.AddFlags(cmd) @@ -333,11 +335,8 @@ hauler store add image rgcrprod.azurecr.us/hauler/rke2-manifest.yaml:v1.28.12-rk return cmd } -func addStoreAddChart() *cobra.Command { - o := &flags.AddChartOpts{ - StoreRootOpts: rootStoreOpts, - ChartOpts: &action.ChartPathOptions{}, - } +func addStoreAddChart(rso *flags.StoreRootOpts, ro *flags.CliRootOpts) *cobra.Command { + o := &flags.AddChartOpts{StoreRootOpts: rso, ChartOpts: &action.ChartPathOptions{}} cmd := &cobra.Command{ Use: "chart", diff --git a/cmd/hauler/cli/store/add.go b/cmd/hauler/cli/store/add.go index 47580d8d..41466163 100644 --- a/cmd/hauler/cli/store/add.go +++ b/cmd/hauler/cli/store/add.go @@ -52,8 +52,9 @@ func storeFile(ctx context.Context, s *store.Layout, fi v1alpha1.File) error { return nil } -func AddImageCmd(ctx context.Context, o *flags.AddImageOpts, s *store.Layout, reference string) error { +func AddImageCmd(ctx context.Context, o *flags.AddImageOpts, s *store.Layout, reference string, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) + cfg := v1alpha1.Image{ Name: reference, } @@ -61,18 +62,19 @@ func AddImageCmd(ctx context.Context, o *flags.AddImageOpts, s *store.Layout, re // Check if the user provided a key. if o.Key != "" { // verify signature using the provided key. - err := cosign.VerifySignature(ctx, s, o.Key, cfg.Name) + err := cosign.VerifySignature(ctx, s, o.Key, cfg.Name, ro) if err != nil { return err } l.Infof("signature verified for image [%s]", cfg.Name) } - return storeImage(ctx, s, cfg, o.Platform) + return storeImage(ctx, s, cfg, o.Platform, ro) } -func storeImage(ctx context.Context, s *store.Layout, i v1alpha1.Image, platform string) error { +func storeImage(ctx context.Context, s *store.Layout, i v1alpha1.Image, platform string, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) + l.Infof("adding 'image' [%s] to the store", i.Name) r, err := name.ParseReference(i.Name) @@ -81,7 +83,7 @@ func storeImage(ctx context.Context, s *store.Layout, i v1alpha1.Image, platform return nil } - err = cosign.SaveImage(ctx, s, r.Name(), platform) + err = cosign.SaveImage(ctx, s, r.Name(), platform, ro) if err != nil { l.Warnf("unable to add 'image' [%s] to store. skipping...", r.Name()) return nil @@ -104,6 +106,7 @@ func AddChartCmd(ctx context.Context, o *flags.AddChartOpts, s *store.Layout, ch func storeChart(ctx context.Context, s *store.Layout, cfg v1alpha1.Chart, opts *action.ChartPathOptions) error { l := log.FromContext(ctx) + l.Infof("adding 'chart' [%s] to the store", cfg.Name) // TODO: This shouldn't be necessary diff --git a/cmd/hauler/cli/store/copy.go b/cmd/hauler/cli/store/copy.go index 4cc6845b..29af234b 100644 --- a/cmd/hauler/cli/store/copy.go +++ b/cmd/hauler/cli/store/copy.go @@ -13,7 +13,7 @@ import ( "hauler.dev/go/hauler/pkg/store" ) -func CopyCmd(ctx context.Context, o *flags.CopyOpts, s *store.Layout, targetRef string) error { +func CopyCmd(ctx context.Context, o *flags.CopyOpts, s *store.Layout, targetRef string, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) components := strings.SplitN(targetRef, "://", 2) @@ -38,13 +38,13 @@ func CopyCmd(ctx context.Context, o *flags.CopyOpts, s *store.Layout, targetRef } if ropts.Username != "" { - err := cosign.RegistryLogin(ctx, s, components[1], ropts) + err := cosign.RegistryLogin(ctx, s, components[1], ropts, ro) if err != nil { return err } } - err := cosign.LoadImages(ctx, s, components[1], ropts) + err := cosign.LoadImages(ctx, s, components[1], ropts, ro) if err != nil { return err } diff --git a/cmd/hauler/cli/store/load.go b/cmd/hauler/cli/store/load.go index 4e00a7b6..913e248f 100644 --- a/cmd/hauler/cli/store/load.go +++ b/cmd/hauler/cli/store/load.go @@ -7,6 +7,7 @@ import ( "github.com/mholt/archiver/v3" "hauler.dev/go/hauler/internal/flags" + "hauler.dev/go/hauler/pkg/consts" "hauler.dev/go/hauler/pkg/content" "hauler.dev/go/hauler/pkg/log" "hauler.dev/go/hauler/pkg/store" @@ -30,17 +31,25 @@ func LoadCmd(ctx context.Context, o *flags.LoadOpts, archiveRefs ...string) erro // unarchiveLayoutTo accepts an archived oci layout and extracts the contents to an existing oci layout, preserving the index func unarchiveLayoutTo(ctx context.Context, archivePath string, dest string, tempOverride string) error { - tmpdir, err := os.MkdirTemp(tempOverride, "hauler") + l := log.FromContext(ctx) + + if tempOverride == "" { + tempOverride = os.Getenv(consts.HaulerTempDir) + } + + tempDir, err := os.MkdirTemp(tempOverride, consts.DefaultHaulerTempDirName) if err != nil { return err } - defer os.RemoveAll(tmpdir) + defer os.RemoveAll(tempDir) + + l.Debugf("using temporary directory at %s", tempDir) - if err := archiver.Unarchive(archivePath, tmpdir); err != nil { + if err := archiver.Unarchive(archivePath, tempDir); err != nil { return err } - s, err := store.NewLayout(tmpdir) + s, err := store.NewLayout(tempDir) if err != nil { return err } diff --git a/cmd/hauler/cli/store/save.go b/cmd/hauler/cli/store/save.go index 3dd5f2a9..ae083030 100644 --- a/cmd/hauler/cli/store/save.go +++ b/cmd/hauler/cli/store/save.go @@ -161,7 +161,7 @@ func writeExportsManifest(ctx context.Context, dir string, platformStr string) e return err } - return oci.WriteFile("manifest.json", buf.Bytes(), 0666) + return oci.WriteFile(consts.OCIImageManifestFile, buf.Bytes(), 0666) } func (x *exports) describe() tarball.Manifest { diff --git a/cmd/hauler/cli/store/serve.go b/cmd/hauler/cli/store/serve.go index 0fa900b7..1ba3a7a3 100644 --- a/cmd/hauler/cli/store/serve.go +++ b/cmd/hauler/cli/store/serve.go @@ -17,7 +17,7 @@ import ( "hauler.dev/go/hauler/pkg/store" ) -func ServeRegistryCmd(ctx context.Context, o *flags.ServeRegistryOpts, s *store.Layout) error { +func ServeRegistryCmd(ctx context.Context, o *flags.ServeRegistryOpts, s *store.Layout, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) ctx = dcontext.WithVersion(ctx, version.Version) @@ -27,7 +27,7 @@ func ServeRegistryCmd(ctx context.Context, o *flags.ServeRegistryOpts, s *store. } opts := &flags.CopyOpts{} - if err := CopyCmd(ctx, opts, s, "registry://"+tr.Registry()); err != nil { + if err := CopyCmd(ctx, opts, s, "registry://"+tr.Registry(), ro); err != nil { return err } @@ -55,12 +55,12 @@ func ServeRegistryCmd(ctx context.Context, o *flags.ServeRegistryOpts, s *store. return nil } -func ServeFilesCmd(ctx context.Context, o *flags.ServeFilesOpts, s *store.Layout) error { +func ServeFilesCmd(ctx context.Context, o *flags.ServeFilesOpts, s *store.Layout, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) ctx = dcontext.WithVersion(ctx, version.Version) opts := &flags.CopyOpts{} - if err := CopyCmd(ctx, opts, s, "dir://"+o.RootDir); err != nil { + if err := CopyCmd(ctx, opts, s, "dir://"+o.RootDir, ro); err != nil { return err } diff --git a/cmd/hauler/cli/store/sync.go b/cmd/hauler/cli/store/sync.go index bd883902..04c338ff 100644 --- a/cmd/hauler/cli/store/sync.go +++ b/cmd/hauler/cli/store/sync.go @@ -24,7 +24,7 @@ import ( "hauler.dev/go/hauler/pkg/store" ) -func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout) error { +func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) // if passed products, check for a remote manifest to retrieve and use. @@ -44,7 +44,7 @@ func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout) error { img := v1alpha1.Image{ Name: manifestLoc, } - err := storeImage(ctx, s, img, o.Platform) + err := storeImage(ctx, s, img, o.Platform, ro) if err != nil { return err } @@ -58,7 +58,7 @@ func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout) error { if err != nil { return err } - err = processContent(ctx, fi, o, s) + err = processContent(ctx, fi, o, s, ro) if err != nil { return err } @@ -71,7 +71,7 @@ func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout) error { if err != nil { return err } - err = processContent(ctx, fi, o, s) + err = processContent(ctx, fi, o, s, ro) if err != nil { return err } @@ -80,7 +80,7 @@ func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout) error { return nil } -func processContent(ctx context.Context, fi *os.File, o *flags.SyncOpts, s *store.Layout) error { +func processContent(ctx context.Context, fi *os.File, o *flags.SyncOpts, s *store.Layout, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) reader := yaml.NewYAMLReader(bufio.NewReader(fi)) @@ -169,7 +169,7 @@ func processContent(ctx context.Context, fi *os.File, o *flags.SyncOpts, s *stor l.Debugf("key for image [%s]", key) // verify signature using the provided key. - err := cosign.VerifySignature(ctx, s, key, i.Name) + err := cosign.VerifySignature(ctx, s, key, i.Name, ro) if err != nil { l.Errorf("signature verification failed for image [%s]. ** hauler will skip adding this image to the store **:\n%v", i.Name, err) continue @@ -188,7 +188,7 @@ func processContent(ctx context.Context, fi *os.File, o *flags.SyncOpts, s *stor platform = i.Platform } - err = storeImage(ctx, s, i, platform) + err = storeImage(ctx, s, i, platform, ro) if err != nil { return err } diff --git a/cmd/hauler/cli/version.go b/cmd/hauler/cli/version.go index c455da7b..24d194ba 100644 --- a/cmd/hauler/cli/version.go +++ b/cmd/hauler/cli/version.go @@ -5,10 +5,11 @@ import ( "github.com/spf13/cobra" + "hauler.dev/go/hauler/internal/flags" "hauler.dev/go/hauler/internal/version" ) -func addVersion(parent *cobra.Command) { +func addVersion(parent *cobra.Command, ro *flags.CliRootOpts) { var json bool cmd := &cobra.Command{ diff --git a/cmd/hauler/main.go b/cmd/hauler/main.go index e4f2b4a3..d74ca180 100644 --- a/cmd/hauler/main.go +++ b/cmd/hauler/main.go @@ -6,7 +6,7 @@ import ( "os" "hauler.dev/go/hauler/cmd/hauler/cli" - "hauler.dev/go/hauler/pkg/cosign" + "hauler.dev/go/hauler/internal/flags" "hauler.dev/go/hauler/pkg/log" ) @@ -20,13 +20,8 @@ func main() { logger := log.NewLogger(os.Stdout) ctx = logger.WithContext(ctx) - // ensure cosign binary is available - if err := cosign.EnsureBinaryExists(ctx, binaries); err != nil { - logger.Errorf("%v", err) - os.Exit(1) - } - - if err := cli.New().ExecuteContext(ctx); err != nil { + // pass the embedded binaries to the cli package + if err := cli.New(ctx, binaries, &flags.CliRootOpts{}).ExecuteContext(ctx); err != nil { logger.Errorf("%v", err) cancel() os.Exit(1) diff --git a/install.sh b/install.sh index f0e4958b..f762feda 100755 --- a/install.sh +++ b/install.sh @@ -17,6 +17,10 @@ # - curl -sfL https://get.hauler.dev | HAULER_INSTALL_DIR=/usr/local/bin bash # - HAULER_INSTALL_DIR=/usr/local/bin ./install.sh # +# Set Hauler Directory +# - curl -sfL https://get.hauler.dev | HAULER_DIR=$HOME/.hauler bash +# - HAULER_DIR=$HOME/.hauler ./install.sh +# # Debug Usage: # - curl -sfL https://get.hauler.dev | HAULER_DEBUG=true bash # - HAULER_DEBUG=true ./install.sh @@ -65,7 +69,7 @@ done # set install directory from argument or environment variable HAULER_INSTALL_DIR=${HAULER_INSTALL_DIR:-/usr/local/bin} -# ensure install directory exists +# ensure install directory exists and/or create it if [ ! -d "${HAULER_INSTALL_DIR}" ]; then mkdir -p "${HAULER_INSTALL_DIR}" || fatal "Failed to Create Install Directory: ${HAULER_INSTALL_DIR}" fi @@ -82,8 +86,8 @@ if [ "${HAULER_UNINSTALL}" = "true" ]; then # remove the hauler binary rm -rf "${HAULER_INSTALL_DIR}/hauler" || fatal "Failed to Remove Hauler from ${HAULER_INSTALL_DIR}" - # remove the working directory - rm -rf "$HOME/.hauler" || fatal "Failed to Remove Hauler Directory: $HOME/.hauler" + # remove the hauler directory + rm -rf "${HAULER_DIR}" || fatal "Failed to Remove Hauler Directory: ${HAULER_DIR}" info "Successfully Uninstalled Hauler" && echo exit 0 @@ -110,7 +114,7 @@ case $PLATFORM in PLATFORM="darwin" ;; *) - fatal "Unsupported Platform: $PLATFORM" + fatal "Unsupported Platform: ${PLATFORM}" ;; esac @@ -124,29 +128,33 @@ case $ARCH in ARCH="arm64" ;; *) - fatal "Unsupported Architecture: $ARCH" + fatal "Unsupported Architecture: ${ARCH}" ;; esac +# set hauler directory from argument or environment variable +HAULER_DIR=${HAULER_DIR:-$HOME/.hauler} + # start hauler installation info "Starting Installation..." # display the version, platform, and architecture verbose "- Version: v${HAULER_VERSION}" -verbose "- Platform: $PLATFORM" -verbose "- Architecture: $ARCH" +verbose "- Platform: ${PLATFORM}" +verbose "- Architecture: ${ARCH}" verbose "- Install Directory: ${HAULER_INSTALL_DIR}" +verbose "- Hauler Directory: ${HAULER_DIR}" -# check working directory and/or create it -if [ ! -d "$HOME/.hauler" ]; then - mkdir -p "$HOME/.hauler" || fatal "Failed to Create Directory: $HOME/.hauler" +# ensure hauler directory exists and/or create it +if [ ! -d "${HAULER_DIR}" ]; then + mkdir -p "${HAULER_DIR}" || fatal "Failed to Create Hauler Directory: ${HAULER_DIR}" fi -# update permissions of working directory -chmod -R 777 "$HOME/.hauler" || fatal "Failed to Update Permissions of Directory: $HOME/.hauler" +# ensure hauler directory is writable (by user or root privileges) +chmod -R 777 "${HAULER_DIR}" || fatal "Failed to Update Permissions of Hauler Directory: ${HAULER_DIR}" -# change to working directory -cd "$HOME/.hauler" || fatal "Failed to Change Directory: $HOME/.hauler" +# change to hauler directory +cd "${HAULER_DIR}" || fatal "Failed to Change Directory to Hauler Directory: ${HAULER_DIR}" # start hauler artifacts download info "Starting Download..." diff --git a/internal/flags/cli.go b/internal/flags/cli.go index 54cb01f1..0ad38a15 100644 --- a/internal/flags/cli.go +++ b/internal/flags/cli.go @@ -1,5 +1,15 @@ package flags +import "github.com/spf13/cobra" + type CliRootOpts struct { - LogLevel string + LogLevel string + HaulerDir string +} + +func AddRootFlags(cmd *cobra.Command, ro *CliRootOpts) { + pf := cmd.PersistentFlags() + + pf.StringVarP(&ro.LogLevel, "log-level", "l", "info", "Set the logging level (i.e. info, debug, warn)") + pf.StringVarP(&ro.HaulerDir, "haulerdir", "d", "", "Set the location of the hauler directory (default $HOME/.hauler)") } diff --git a/internal/flags/save.go b/internal/flags/save.go index fa9a63de..a447d76b 100644 --- a/internal/flags/save.go +++ b/internal/flags/save.go @@ -1,6 +1,9 @@ package flags -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" + "hauler.dev/go/hauler/pkg/consts" +) type SaveOpts struct { *StoreRootOpts @@ -11,6 +14,6 @@ type SaveOpts struct { func (o *SaveOpts) AddFlags(cmd *cobra.Command) { f := cmd.Flags() - f.StringVarP(&o.FileName, "filename", "f", "haul.tar.zst", "(Optional) Specify the name of outputted archive") + f.StringVarP(&o.FileName, "filename", "f", consts.DefaultHaulArchiveName, "(Optional) Specify the name of outputted archive") f.StringVarP(&o.Platform, "platform", "p", "", "(Optional) Specify the platform for runtime imports... i.e. linux/amd64 (unspecified implies all)") } diff --git a/internal/flags/serve.go b/internal/flags/serve.go index 452b57cb..4584ae77 100644 --- a/internal/flags/serve.go +++ b/internal/flags/serve.go @@ -6,6 +6,7 @@ import ( "github.com/distribution/distribution/v3/configuration" "github.com/spf13/cobra" + "hauler.dev/go/hauler/pkg/consts" ) type ServeRegistryOpts struct { @@ -23,8 +24,8 @@ type ServeRegistryOpts struct { func (o *ServeRegistryOpts) AddFlags(cmd *cobra.Command) { f := cmd.Flags() - f.IntVarP(&o.Port, "port", "p", 5000, "(Optional) Specify the port to use for incoming connections") - f.StringVar(&o.RootDir, "directory", "registry", "(Optional) Directory to use for backend. Defaults to $PWD/registry") + f.IntVarP(&o.Port, "port", "p", consts.DefaultRegistryPort, "(Optional) Specify the port to use for incoming connections") + f.StringVar(&o.RootDir, "directory", consts.DefaultRegistryRootDir, "(Optional) Directory to use for backend. Defaults to $PWD/registry") f.StringVarP(&o.ConfigFile, "config", "c", "", "(Optional) Location of config file (overrides all flags)") f.BoolVar(&o.ReadOnly, "readonly", true, "(Optional) Run the registry as readonly") @@ -76,9 +77,9 @@ type ServeFilesOpts struct { func (o *ServeFilesOpts) AddFlags(cmd *cobra.Command) { f := cmd.Flags() - f.IntVarP(&o.Port, "port", "p", 8080, "(Optional) Specify the port to use for incoming connections") - f.IntVarP(&o.Timeout, "timeout", "t", 60, "(Optional) Timeout duration for HTTP Requests in seconds for both reads/writes") - f.StringVar(&o.RootDir, "directory", "fileserver", "(Optional) Directory to use for backend. Defaults to $PWD/fileserver") + f.IntVarP(&o.Port, "port", "p", consts.DefaultFileserverPort, "(Optional) Specify the port to use for incoming connections") + f.IntVarP(&o.Timeout, "timeout", "t", consts.DefaultFileserverTimeout, "(Optional) Timeout duration for HTTP Requests in seconds for both reads/writes") + f.StringVar(&o.RootDir, "directory", consts.DefaultFileserverRootDir, "(Optional) Directory to use for backend. Defaults to $PWD/fileserver") f.StringVar(&o.TLSCert, "tls-cert", "", "(Optional) Location of the TLS Certificate to use for server authenication") f.StringVar(&o.TLSKey, "tls-key", "", "(Optional) Location of the TLS Key to use for server authenication") diff --git a/internal/flags/store.go b/internal/flags/store.go index 23732447..01e64e0e 100644 --- a/internal/flags/store.go +++ b/internal/flags/store.go @@ -23,14 +23,16 @@ func (o *StoreRootOpts) AddFlags(cmd *cobra.Command) { func (o *StoreRootOpts) Store(ctx context.Context) (*store.Layout, error) { l := log.FromContext(ctx) - dir := o.StoreDir - abs, err := filepath.Abs(dir) + storeDir := o.StoreDir + + abs, err := filepath.Abs(storeDir) if err != nil { return nil, err } l.Debugf("using store at %s", abs) + if _, err := os.Stat(abs); errors.Is(err, os.ErrNotExist) { err := os.Mkdir(abs, os.ModePerm) if err != nil { diff --git a/internal/mapper/mappers.go b/internal/mapper/mappers.go index c4e65d34..1cfb5867 100644 --- a/internal/mapper/mappers.go +++ b/internal/mapper/mappers.go @@ -36,7 +36,7 @@ func Images() map[string]Fn { m := make(map[string]Fn) manifestMapperFn := Fn(func(desc ocispec.Descriptor) (string, error) { - return "manifest.json", nil + return consts.OCIImageManifestFile, nil }) for _, l := range []string{consts.DockerManifestSchema2, consts.DockerManifestListSchema2, consts.OCIManifestSchema1} { @@ -52,7 +52,7 @@ func Images() map[string]Fn { } configMapperFn := Fn(func(desc ocispec.Descriptor) (string, error) { - return "config.json", nil + return consts.OCIImageConfigFile, nil }) for _, l := range []string{consts.DockerConfigJSON} { diff --git a/internal/server/file.go b/internal/server/file.go index ac6b8d19..8cade10a 100644 --- a/internal/server/file.go +++ b/internal/server/file.go @@ -10,6 +10,7 @@ import ( "github.com/gorilla/handlers" "github.com/gorilla/mux" "hauler.dev/go/hauler/internal/flags" + "hauler.dev/go/hauler/pkg/consts" ) // NewFile returns a fileserver @@ -22,11 +23,11 @@ func NewFile(ctx context.Context, cfg flags.ServeFilesOpts) (Server, error) { } if cfg.Port == 0 { - cfg.Port = 8080 + cfg.Port = consts.DefaultFileserverPort } if cfg.Timeout == 0 { - cfg.Timeout = 60 + cfg.Timeout = consts.DefaultFileserverTimeout } srv := &http.Server{ diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 59035af7..3c6a0c7e 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -61,13 +61,32 @@ const ( ContentGroup = "content.hauler.cattle.io" CollectionGroup = "collection.hauler.cattle.io" + // environment variables + HaulerDir = "HAULER_DIR" + HaulerTempDir = "HAULER_TEMP_DIR" + + // container files and directories + OCIImageIndexFile = "index.json" + OCIImageManifestFile = "manifest.json" + OCIImageConfigFile = "config.json" + OCIImageLayoutFile = "oci-layout" + OCIImageBlobsDir = "blobs" + // other constraints - CarbideRegistry = "rgcrprod.azurecr.us" - APIVersion = "v1alpha1" - DefaultNamespace = "hauler" - DefaultTag = "latest" - DefaultStoreName = "store" - DefaultRetries = 3 - RetriesInterval = 5 - OCIImageIndexFile = "index.json" + CarbideRegistry = "rgcrprod.azurecr.us" + APIVersion = "v1alpha1" + DefaultNamespace = "hauler" + DefaultTag = "latest" + DefaultStoreName = "store" + DefaultHaulerDirName = ".hauler" + DefaultHaulerTempDirName = "hauler" + DefaultRegistryRootDir = "registry" + DefaultRegistryPort = 5000 + DefaultFileserverRootDir = "fileserver" + DefaultFileserverPort = 8080 + DefaultFileserverTimeout = 60 + DefaultHaulArchiveName = "haul.tar.zst" + DefaultRetries = 3 + RetriesInterval = 5 + CustomTimeFormat = "2006-01-02 15:04:05" ) diff --git a/pkg/content/chart/chart_test.go b/pkg/content/chart/chart_test.go index fda3f76d..94133e92 100644 --- a/pkg/content/chart/chart_test.go +++ b/pkg/content/chart/chart_test.go @@ -14,11 +14,11 @@ import ( ) func TestNewChart(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "hauler") + tempDir, err := os.MkdirTemp("", "hauler") if err != nil { t.Fatal(err) } - defer os.RemoveAll(tmpdir) + defer os.RemoveAll(tempDir) type args struct { name string @@ -53,7 +53,7 @@ func TestNewChart(t *testing.T) { // { // name: "should create from a chart directory", // args: args{ - // path: filepath.Join(tmpdir, "podinfo"), + // path: filepath.Join(tempDir, "podinfo"), // }, // want: want, // wantErr: false, diff --git a/pkg/content/oci.go b/pkg/content/oci.go index 092d2d5f..dd077433 100644 --- a/pkg/content/oci.go +++ b/pkg/content/oci.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/google/go-containerregistry/pkg/name" "io" "os" "path/filepath" @@ -12,6 +11,8 @@ import ( "strings" "sync" + "github.com/google/go-containerregistry/pkg/name" + ccontent "github.com/containerd/containerd/content" "github.com/containerd/containerd/remotes" "github.com/opencontainers/image-spec/specs-go" @@ -258,7 +259,7 @@ func (o *OCI) blobWriterAt(desc ocispec.Descriptor) (*os.File, error) { } func (o *OCI) ensureBlob(alg string, hex string) (string, error) { - dir := o.path("blobs", alg) + dir := o.path(consts.OCIImageBlobsDir, alg) if err := os.MkdirAll(dir, os.ModePerm); err != nil && !os.IsExist(err) { return "", err } diff --git a/pkg/cosign/cosign.go b/pkg/cosign/cosign.go index 7f1bcf72..5101cfb2 100644 --- a/pkg/cosign/cosign.go +++ b/pkg/cosign/cosign.go @@ -15,6 +15,7 @@ import ( "oras.land/oras-go/pkg/content" + "hauler.dev/go/hauler/internal/flags" "hauler.dev/go/hauler/pkg/artifacts/image" "hauler.dev/go/hauler/pkg/consts" "hauler.dev/go/hauler/pkg/log" @@ -22,9 +23,9 @@ import ( ) // VerifyFileSignature verifies the digital signature of a file using Sigstore/Cosign. -func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref string) error { +func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref string, ro *flags.CliRootOpts) error { operation := func() error { - cosignBinaryPath, err := getCosignPath() + cosignBinaryPath, err := getCosignPath(ro.HaulerDir) if err != nil { return err } @@ -42,10 +43,11 @@ func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref s } // SaveImage saves image and any signatures/attestations to the store. -func SaveImage(ctx context.Context, s *store.Layout, ref string, platform string) error { +func SaveImage(ctx context.Context, s *store.Layout, ref string, platform string, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) + operation := func() error { - cosignBinaryPath, err := getCosignPath() + cosignBinaryPath, err := getCosignPath(ro.HaulerDir) if err != nil { return err } @@ -110,10 +112,10 @@ func SaveImage(ctx context.Context, s *store.Layout, ref string, platform string } // LoadImage loads store to a remote registry. -func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error { +func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions, ro *flags.CliRootOpts) error { l := log.FromContext(ctx) - cosignBinaryPath, err := getCosignPath() + cosignBinaryPath, err := getCosignPath(ro.HaulerDir) if err != nil { return err } @@ -171,9 +173,9 @@ func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts con } // RegistryLogin - performs cosign login -func RegistryLogin(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error { +func RegistryLogin(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions, ro *flags.CliRootOpts) error { log := log.FromContext(ctx) - cosignBinaryPath, err := getCosignPath() + cosignBinaryPath, err := getCosignPath(ro.HaulerDir) if err != nil { return err } @@ -190,6 +192,7 @@ func RegistryLogin(ctx context.Context, s *store.Layout, registry string, ropts func RetryOperation(ctx context.Context, operation func() error) error { l := log.FromContext(ctx) + for attempt := 1; attempt <= consts.DefaultRetries; attempt++ { err := operation() if err == nil { @@ -210,14 +213,18 @@ func RetryOperation(ctx context.Context, operation func() error) error { return fmt.Errorf("operation failed after %d attempts", consts.DefaultRetries) } -func EnsureBinaryExists(ctx context.Context, bin embed.FS) error { - // Set up a path for the binary to be copied. - binaryPath, err := getCosignPath() +func EnsureBinaryExists(ctx context.Context, bin embed.FS, ro *flags.CliRootOpts) error { + l := log.FromContext(ctx) + + // Set up a path for the binary to be copied + binaryPath, err := getCosignPath(ro.HaulerDir) if err != nil { return fmt.Errorf("error: %v", err) } - // Determine the architecture so that we pull the correct embedded binary. + l.Debugf("using hauler directory at %s", filepath.Dir(binaryPath)) + + // Determine the architecture so that we pull the correct embedded binary arch := runtime.GOARCH rOS := runtime.GOOS binaryName := "cosign" @@ -243,35 +250,38 @@ func EnsureBinaryExists(ctx context.Context, bin embed.FS) error { } // getCosignPath returns the binary path -func getCosignPath() (string, error) { - // Get the current user's information - currentUser, err := user.Current() - if err != nil { - return "", fmt.Errorf("error: %v", err) +func getCosignPath(haulerDir string) (string, error) { + if haulerDir == "" { + haulerDir = os.Getenv(consts.HaulerDir) } - // Get the user's home directory - homeDir := currentUser.HomeDir + if haulerDir == "" { + // Get the current user's information + currentUser, err := user.Current() + if err != nil { + return "", fmt.Errorf("error retrieving user information: %v", err) + } - // Construct the path to the .hauler directory - haulerDir := filepath.Join(homeDir, ".hauler") + // Get the current user's home directory + homeDir := currentUser.HomeDir + haulerDir = filepath.Join(homeDir, consts.DefaultHaulerDirName) + } - // Create the .hauler directory if it doesn't exist + // Create the .hauler directory (if it doesn't exist) if _, err := os.Stat(haulerDir); os.IsNotExist(err) { - // .hauler directory does not exist, create it if err := os.MkdirAll(haulerDir, 0755); err != nil { - return "", fmt.Errorf("error creating .hauler directory: %v", err) + return "", fmt.Errorf("error creating %s directory: %v", consts.DefaultHaulerDirName, err) } } - // Determine the binary name. + // Determine the binary name rOS := runtime.GOOS binaryName := "cosign" if rOS == "windows" { binaryName = "cosign.exe" } - // construct path to binary + // Construct the path to the binary binaryPath := filepath.Join(haulerDir, binaryName) return binaryPath, nil diff --git a/pkg/log/log.go b/pkg/log/log.go index 82de3b29..3f5371d6 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -7,6 +7,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "hauler.dev/go/hauler/pkg/consts" ) // Logger provides an interface for all used logger features regardless of logging backend @@ -30,9 +31,8 @@ type Fields map[string]string // NewLogger returns a new Logger func NewLogger(out io.Writer) Logger { - customTimeFormat := "2006-01-02 15:04:05" - zerolog.TimeFieldFormat = customTimeFormat - output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: customTimeFormat} + zerolog.TimeFieldFormat = consts.CustomTimeFormat + output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: consts.CustomTimeFormat} l := log.Output(output) return &logger{ zl: l.With().Timestamp().Logger(), diff --git a/pkg/store/store.go b/pkg/store/store.go index 1e7ea914..aebb7903 100644 --- a/pkg/store/store.go +++ b/pkg/store/store.go @@ -151,17 +151,17 @@ func (l *Layout) AddOCICollection(ctx context.Context, collection artifacts.OCIC // This can be a highly destructive operation if the store's directory happens to be inline with other non-store contents // To reduce the blast radius and likelihood of deleting things we don't own, Flush explicitly deletes oci-layout content only func (l *Layout) Flush(ctx context.Context) error { - blobs := filepath.Join(l.Root, "blobs") + blobs := filepath.Join(l.Root, consts.OCIImageBlobsDir) if err := os.RemoveAll(blobs); err != nil { return err } - index := filepath.Join(l.Root, "index.json") + index := filepath.Join(l.Root, consts.OCIImageIndexFile) if err := os.RemoveAll(index); err != nil { return err } - layout := filepath.Join(l.Root, "oci-layout") + layout := filepath.Join(l.Root, consts.OCIImageLayoutFile) if err := os.RemoveAll(layout); err != nil { return err } @@ -240,7 +240,7 @@ func (l *Layout) writeLayer(layer v1.Layer) error { return err } - dir := filepath.Join(l.Root, "blobs", d.Algorithm) + dir := filepath.Join(l.Root, consts.OCIImageBlobsDir, d.Algorithm) if err := os.MkdirAll(dir, os.ModePerm); err != nil && !os.IsExist(err) { return err } diff --git a/pkg/store/store_test.go b/pkg/store/store_test.go index 5c4bd590..c7bcf762 100644 --- a/pkg/store/store_test.go +++ b/pkg/store/store_test.go @@ -63,16 +63,16 @@ func TestLayout_AddOCI(t *testing.T) { } func setup(t *testing.T) func() error { - tmpdir, err := os.MkdirTemp("", "hauler") + tempDir, err := os.MkdirTemp("", "hauler") if err != nil { t.Fatal(err) } - root = tmpdir + root = tempDir ctx = context.Background() return func() error { - os.RemoveAll(tmpdir) + os.RemoveAll(tempDir) return nil } }