mirror of
https://github.com/hauler-dev/hauler.git
synced 2026-02-14 09:59:50 +00:00
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 54f7a4d695
* minor restructure to root flags
* updated logic to include haulerdir flag
* cleaned up/formatted new logic
* more cleanup and formatting
This commit is contained in:
@@ -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",
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
if err := archiver.Unarchive(archivePath, tmpdir); err != nil {
|
||||
l.Debugf("using temporary directory at %s", tempDir)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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)
|
||||
|
||||
36
install.sh
36
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..."
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
package flags
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
type CliRootOpts struct {
|
||||
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)")
|
||||
}
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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} {
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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"
|
||||
DefaultHaulerDirName = ".hauler"
|
||||
DefaultHaulerTempDirName = "hauler"
|
||||
DefaultRegistryRootDir = "registry"
|
||||
DefaultRegistryPort = 5000
|
||||
DefaultFileserverRootDir = "fileserver"
|
||||
DefaultFileserverPort = 8080
|
||||
DefaultFileserverTimeout = 60
|
||||
DefaultHaulArchiveName = "haul.tar.zst"
|
||||
DefaultRetries = 3
|
||||
RetriesInterval = 5
|
||||
OCIImageIndexFile = "index.json"
|
||||
CustomTimeFormat = "2006-01-02 15:04:05"
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
func getCosignPath(haulerDir string) (string, error) {
|
||||
if haulerDir == "" {
|
||||
haulerDir = os.Getenv(consts.HaulerDir)
|
||||
}
|
||||
|
||||
if haulerDir == "" {
|
||||
// Get the current user's information
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error: %v", err)
|
||||
return "", fmt.Errorf("error retrieving user information: %v", err)
|
||||
}
|
||||
|
||||
// Get the user's home directory
|
||||
// Get the current user's home directory
|
||||
homeDir := currentUser.HomeDir
|
||||
haulerDir = filepath.Join(homeDir, consts.DefaultHaulerDirName)
|
||||
}
|
||||
|
||||
// Construct the path to the .hauler directory
|
||||
haulerDir := filepath.Join(homeDir, ".hauler")
|
||||
|
||||
// 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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user