From ffa6943d6dd0dd9c38d9998d3121cae135a8724a Mon Sep 17 00:00:00 2001 From: Josh Wolf Date: Mon, 1 Nov 2021 11:10:32 -0600 Subject: [PATCH 1/4] cli ux and verbiage cleanup --- cmd/hauler/cli/cli.go | 6 +- cmd/hauler/cli/load.go | 29 ------- cmd/hauler/cli/save.go | 28 ------- cmd/hauler/cli/serve.go | 27 ------- cmd/hauler/cli/store.go | 85 +++++++++++++++++++-- cmd/hauler/cli/store/{get.go => extract.go} | 8 +- cmd/hauler/cli/{load => store}/load.go | 16 ++-- cmd/hauler/cli/{save => store}/save.go | 12 +-- cmd/hauler/cli/{serve => store}/serve.go | 12 +-- 9 files changed, 108 insertions(+), 115 deletions(-) delete mode 100644 cmd/hauler/cli/load.go rename cmd/hauler/cli/store/{get.go => extract.go} (75%) rename cmd/hauler/cli/{load => store}/load.go (62%) rename cmd/hauler/cli/{save => store}/save.go (78%) rename cmd/hauler/cli/{serve => store}/serve.go (83%) diff --git a/cmd/hauler/cli/cli.go b/cmd/hauler/cli/cli.go index bd70f0f..abf915e 100644 --- a/cmd/hauler/cli/cli.go +++ b/cmd/hauler/cli/cli.go @@ -40,9 +40,9 @@ func New() *cobra.Command { // Add subcommands addGet(cmd) - addSave(cmd) - addLoad(cmd) - addServe(cmd) + addStoreSave(cmd) + addStoreLoad(cmd) + addStoreServe(cmd) addStore(cmd) return cmd diff --git a/cmd/hauler/cli/load.go b/cmd/hauler/cli/load.go deleted file mode 100644 index d974afa..0000000 --- a/cmd/hauler/cli/load.go +++ /dev/null @@ -1,29 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/rancherfederal/hauler/cmd/hauler/cli/load" -) - -func addLoad(parent *cobra.Command) { - o := &load.Opts{} - - cmd := &cobra.Command{ - Use: "load", - Short: "Load archived content into hauler's store", - Args: cobra.MinimumNArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - s, err := ro.getStore(ctx) - if err != nil { - return err - } - - return load.Cmd(ctx, o, s.DataDir, args...) - }, - } - - parent.AddCommand(cmd) -} diff --git a/cmd/hauler/cli/save.go b/cmd/hauler/cli/save.go index a405d70..c56a805 100644 --- a/cmd/hauler/cli/save.go +++ b/cmd/hauler/cli/save.go @@ -1,30 +1,2 @@ package cli -import ( - "github.com/spf13/cobra" - - "github.com/rancherfederal/hauler/cmd/hauler/cli/save" -) - -func addSave(parent *cobra.Command) { - o := &save.Opts{} - - cmd := &cobra.Command{ - Use: "save", - Short: "Save hauler's store into a transportable compressed archive", - Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - s, err := ro.getStore(ctx) - if err != nil { - return err - } - - return save.Cmd(ctx, o, o.FileName, s.DataDir) - }, - } - o.AddArgs(cmd) - - parent.AddCommand(cmd) -} diff --git a/cmd/hauler/cli/serve.go b/cmd/hauler/cli/serve.go index 0029333..c56a805 100644 --- a/cmd/hauler/cli/serve.go +++ b/cmd/hauler/cli/serve.go @@ -1,29 +1,2 @@ package cli -import ( - "github.com/spf13/cobra" - - "github.com/rancherfederal/hauler/cmd/hauler/cli/serve" -) - -func addServe(parent *cobra.Command) { - o := &serve.Opts{} - - cmd := &cobra.Command{ - Use: "serve", - Short: "Serve artifacts in hauler's embedded store", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - s, err := ro.getStore(ctx) - if err != nil { - return err - } - - return serve.Cmd(ctx, o, s.DataDir) - }, - } - o.AddFlags(cmd) - - parent.AddCommand(cmd) -} diff --git a/cmd/hauler/cli/store.go b/cmd/hauler/cli/store.go index 10ab191..0e5c88e 100644 --- a/cmd/hauler/cli/store.go +++ b/cmd/hauler/cli/store.go @@ -17,18 +17,21 @@ func addStore(parent *cobra.Command) { cmd.AddCommand( addStoreSync(), - addStoreGet(), + addStoreExtract(), + addStoreLoad(), + addStoreSave(), + addStoreServe(), ) parent.AddCommand(cmd) } -func addStoreGet() *cobra.Command { - o := &store.GetOpts{} +func addStoreExtract() *cobra.Command { + o := &store.ExtractOpts{} cmd := &cobra.Command{ - Use: "get", - Short: "Get content from hauler's embedded content store", + Use: "extract", + Short: "Extract content from the embedded content store", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -38,7 +41,7 @@ func addStoreGet() *cobra.Command { return err } - return store.GetCmd(ctx, o, s, args[0]) + return store.ExtractCmd(ctx, o, s, args[0]) }, } o.AddArgs(cmd) @@ -51,7 +54,7 @@ func addStoreSync() *cobra.Command { cmd := &cobra.Command{ Use: "sync", - Short: "Sync content to hauler's embedded content store", + Short: "Sync content to the embedded content store", RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -67,3 +70,71 @@ func addStoreSync() *cobra.Command { return cmd } + +func addStoreLoad() *cobra.Command { + o := &store.LoadOpts{} + + cmd := &cobra.Command{ + Use: "load", + Short: "Load archived content into the embedded content store", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + s, err := ro.getStore(ctx) + if err != nil { + return err + } + + return store.LoadCmd(ctx, o, s.DataDir, args...) + }, + } + o.AddFlags(cmd) + + return cmd +} + +func addStoreServe() *cobra.Command { + o := &store.ServeOpts{} + + cmd := &cobra.Command{ + Use: "serve", + Short: "Serve artifacts from the embedded content store", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + s, err := ro.getStore(ctx) + if err != nil { + return err + } + + return store.ServeCmd(ctx, o, s.DataDir) + }, + } + o.AddFlags(cmd) + + return cmd +} + +func addStoreSave() *cobra.Command { + o := &store.SaveOpts{} + + cmd := &cobra.Command{ + Use: "save", + Short: "Save the embedded content store into a transportable compressed archive", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + s, err := ro.getStore(ctx) + if err != nil { + return err + } + + return store.SaveCmd(ctx, o, o.FileName, s.DataDir) + }, + } + o.AddArgs(cmd) + + return cmd +} diff --git a/cmd/hauler/cli/store/get.go b/cmd/hauler/cli/store/extract.go similarity index 75% rename from cmd/hauler/cli/store/get.go rename to cmd/hauler/cli/store/extract.go index 6483bed..463ae7c 100644 --- a/cmd/hauler/cli/store/get.go +++ b/cmd/hauler/cli/store/extract.go @@ -11,19 +11,19 @@ import ( "github.com/rancherfederal/hauler/pkg/store" ) -type GetOpts struct { +type ExtractOpts struct { DestinationDir string } -func (o *GetOpts) AddArgs(cmd *cobra.Command) { +func (o *ExtractOpts) AddArgs(cmd *cobra.Command) { f := cmd.Flags() f.StringVar(&o.DestinationDir, "dir", "", "Directory to save contents to (defaults to current directory)") } -func GetCmd(ctx context.Context, o *GetOpts, s *store.Store, reference string) error { +func ExtractCmd(ctx context.Context, o *ExtractOpts, s *store.Store, reference string) error { l := log.FromContext(ctx) - l.Debugf("running command `hauler store get`") + l.Debugf("running command `hauler store extract`") s.Open() defer s.Close() diff --git a/cmd/hauler/cli/load/load.go b/cmd/hauler/cli/store/load.go similarity index 62% rename from cmd/hauler/cli/load/load.go rename to cmd/hauler/cli/store/load.go index e0c1fa4..683b3dd 100644 --- a/cmd/hauler/cli/load/load.go +++ b/cmd/hauler/cli/store/load.go @@ -1,20 +1,26 @@ -package load +package store import ( "context" "github.com/mholt/archiver/v3" + "github.com/spf13/cobra" "github.com/rancherfederal/hauler/pkg/log" ) -type Opts struct{} +type LoadOpts struct{} -// Cmd +func (o *LoadOpts) AddFlags(cmd *cobra.Command) { + f := cmd.Flags() + _ = f +} + +// LoadCmd // TODO: Just use mholt/archiver for now, even though we don't need most of it -func Cmd(ctx context.Context, o *Opts, dir string, archiveRefs ...string) error { +func LoadCmd(ctx context.Context, o *LoadOpts, dir string, archiveRefs ...string) error { l := log.FromContext(ctx) - l.Debugf("running command `hauler load`") + l.Debugf("running command `hauler store load`") // TODO: Support more formats? a := archiver.NewTarZstd() diff --git a/cmd/hauler/cli/save/save.go b/cmd/hauler/cli/store/save.go similarity index 78% rename from cmd/hauler/cli/save/save.go rename to cmd/hauler/cli/store/save.go index 1335101..dd1d045 100644 --- a/cmd/hauler/cli/save/save.go +++ b/cmd/hauler/cli/store/save.go @@ -1,4 +1,4 @@ -package save +package store import ( "context" @@ -11,21 +11,21 @@ import ( "github.com/rancherfederal/hauler/pkg/log" ) -type Opts struct { +type SaveOpts struct { FileName string } -func (o *Opts) AddArgs(cmd *cobra.Command) { +func (o *SaveOpts) AddArgs(cmd *cobra.Command) { f := cmd.Flags() f.StringVarP(&o.FileName, "filename", "f", "pkg.tar.zst", "Name of archive") } -// Cmd +// SaveCmd // TODO: Just use mholt/archiver for now, even though we don't need most of it -func Cmd(ctx context.Context, o *Opts, outputFile string, dir string) error { +func SaveCmd(ctx context.Context, o *SaveOpts, outputFile string, dir string) error { l := log.FromContext(ctx) - l.Debugf("running command `hauler save`") + l.Debugf("running command `hauler store save`") // TODO: Support more formats? a := archiver.NewTarZstd() diff --git a/cmd/hauler/cli/serve/serve.go b/cmd/hauler/cli/store/serve.go similarity index 83% rename from cmd/hauler/cli/serve/serve.go rename to cmd/hauler/cli/store/serve.go index f71bf6a..13571d5 100644 --- a/cmd/hauler/cli/serve/serve.go +++ b/cmd/hauler/cli/store/serve.go @@ -1,4 +1,4 @@ -package serve +package store import ( "context" @@ -12,21 +12,21 @@ import ( "github.com/rancherfederal/hauler/pkg/log" ) -type Opts struct { +type ServeOpts struct { Port int configFile string } -func (o *Opts) AddFlags(cmd *cobra.Command) { +func (o *ServeOpts) AddFlags(cmd *cobra.Command) { f := cmd.Flags() f.IntVarP(&o.Port, "port", "p", 5000, "Port to listen on") } -// Cmd does -func Cmd(ctx context.Context, o *Opts, dir string) error { +// ServeCmd does +func ServeCmd(ctx context.Context, o *ServeOpts, dir string) error { l := log.FromContext(ctx) - l.Debugf("running command `hauler serve`") + l.Debugf("running command `hauler store serve`") cfg := &configuration.Configuration{ Version: "0.1", From e5384251f2618bd35e0043d020bc60e3980df869 Mon Sep 17 00:00:00 2001 From: Josh Wolf Date: Mon, 1 Nov 2021 11:22:26 -0600 Subject: [PATCH 2/4] add cli aliases --- cmd/hauler/cli/cli.go | 5 +--- cmd/hauler/cli/download.go | 26 +++++++++++++++++++ .../cli/{get/get.go => download/download.go} | 4 +-- cmd/hauler/cli/get.go | 25 ------------------ cmd/hauler/cli/save.go | 2 -- cmd/hauler/cli/serve.go | 2 -- cmd/hauler/cli/store.go | 15 ++++++----- cmd/hauler/cli/store/extract.go | 6 ++--- 8 files changed, 40 insertions(+), 45 deletions(-) create mode 100644 cmd/hauler/cli/download.go rename cmd/hauler/cli/{get/get.go => download/download.go} (96%) delete mode 100644 cmd/hauler/cli/get.go delete mode 100644 cmd/hauler/cli/save.go delete mode 100644 cmd/hauler/cli/serve.go diff --git a/cmd/hauler/cli/cli.go b/cmd/hauler/cli/cli.go index abf915e..3a09cd2 100644 --- a/cmd/hauler/cli/cli.go +++ b/cmd/hauler/cli/cli.go @@ -39,10 +39,7 @@ func New() *cobra.Command { pf.StringVar(&ro.cacheDir, "cache", "", "Location of where to store cache data (defaults to XDG_CACHE_DIR/hauler)") // Add subcommands - addGet(cmd) - addStoreSave(cmd) - addStoreLoad(cmd) - addStoreServe(cmd) + addDownload(cmd) addStore(cmd) return cmd diff --git a/cmd/hauler/cli/download.go b/cmd/hauler/cli/download.go new file mode 100644 index 0000000..579323f --- /dev/null +++ b/cmd/hauler/cli/download.go @@ -0,0 +1,26 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/rancherfederal/hauler/cmd/hauler/cli/download" +) + +func addDownload(parent *cobra.Command) { + o := &download.Opts{} + + cmd := &cobra.Command{ + Use: "download", + Short: "Download OCI content from a registry and populate it on disk", + Aliases: []string{"dl"}, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, arg []string) error { + ctx := cmd.Context() + + return download.Cmd(ctx, o, arg[0]) + }, + } + o.AddArgs(cmd) + + parent.AddCommand(cmd) +} diff --git a/cmd/hauler/cli/get/get.go b/cmd/hauler/cli/download/download.go similarity index 96% rename from cmd/hauler/cli/get/get.go rename to cmd/hauler/cli/download/download.go index 43f2767..18b377c 100644 --- a/cmd/hauler/cli/get/get.go +++ b/cmd/hauler/cli/download/download.go @@ -1,4 +1,4 @@ -package get +package download import ( "context" @@ -29,7 +29,7 @@ func (o *Opts) AddArgs(cmd *cobra.Command) { func Cmd(ctx context.Context, o *Opts, reference string) error { l := log.FromContext(ctx) - l.Debugf("running command `hauler get`") + l.Debugf("running command `hauler download`") cs := content.NewFileStore(o.DestinationDir) defer cs.Close() diff --git a/cmd/hauler/cli/get.go b/cmd/hauler/cli/get.go deleted file mode 100644 index 6c87ae8..0000000 --- a/cmd/hauler/cli/get.go +++ /dev/null @@ -1,25 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/rancherfederal/hauler/cmd/hauler/cli/get" -) - -func addGet(parent *cobra.Command) { - o := &get.Opts{} - - cmd := &cobra.Command{ - Use: "get", - Short: "Get OCI content from a registry", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, arg []string) error { - ctx := cmd.Context() - - return get.Cmd(ctx, o, arg[0]) - }, - } - o.AddArgs(cmd) - - parent.AddCommand(cmd) -} diff --git a/cmd/hauler/cli/save.go b/cmd/hauler/cli/save.go deleted file mode 100644 index c56a805..0000000 --- a/cmd/hauler/cli/save.go +++ /dev/null @@ -1,2 +0,0 @@ -package cli - diff --git a/cmd/hauler/cli/serve.go b/cmd/hauler/cli/serve.go deleted file mode 100644 index c56a805..0000000 --- a/cmd/hauler/cli/serve.go +++ /dev/null @@ -1,2 +0,0 @@ -package cli - diff --git a/cmd/hauler/cli/store.go b/cmd/hauler/cli/store.go index 0e5c88e..7ce2bd0 100644 --- a/cmd/hauler/cli/store.go +++ b/cmd/hauler/cli/store.go @@ -9,7 +9,7 @@ import ( func addStore(parent *cobra.Command) { cmd := &cobra.Command{ Use: "store", - Short: "Interact with hauler's content store", + Short: "Interact with hauler's embedded content store", RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, @@ -30,9 +30,10 @@ func addStoreExtract() *cobra.Command { o := &store.ExtractOpts{} cmd := &cobra.Command{ - Use: "extract", - Short: "Extract content from the embedded content store", - Args: cobra.ExactArgs(1), + Use: "extract", + Short: "Extract content from the store to disk", + Aliases: []string{"x"}, + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -76,7 +77,7 @@ func addStoreLoad() *cobra.Command { cmd := &cobra.Command{ Use: "load", - Short: "Load archived content into the embedded content store", + Short: "Load a content store from a store archive", Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -99,7 +100,7 @@ func addStoreServe() *cobra.Command { cmd := &cobra.Command{ Use: "serve", - Short: "Serve artifacts from the embedded content store", + Short: "Expose the content of a local store through an OCI compliant server", RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() @@ -121,7 +122,7 @@ func addStoreSave() *cobra.Command { cmd := &cobra.Command{ Use: "save", - Short: "Save the embedded content store into a transportable compressed archive", + Short: "Save a content store to a store archive", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() diff --git a/cmd/hauler/cli/store/extract.go b/cmd/hauler/cli/store/extract.go index 463ae7c..66e1c62 100644 --- a/cmd/hauler/cli/store/extract.go +++ b/cmd/hauler/cli/store/extract.go @@ -6,7 +6,7 @@ import ( "github.com/google/go-containerregistry/pkg/name" "github.com/spf13/cobra" - "github.com/rancherfederal/hauler/cmd/hauler/cli/get" + "github.com/rancherfederal/hauler/cmd/hauler/cli/download" "github.com/rancherfederal/hauler/pkg/log" "github.com/rancherfederal/hauler/pkg/store" ) @@ -35,9 +35,9 @@ func ExtractCmd(ctx context.Context, o *ExtractOpts, s *store.Store, reference s eref := s.RelocateReference(ref) - gopts := &get.Opts{ + gopts := &download.Opts{ DestinationDir: o.DestinationDir, } - return get.Cmd(ctx, gopts, eref.Name()) + return download.Cmd(ctx, gopts, eref.Name()) } From 786e63f2eff9a4687e90996aa4918affd497380c Mon Sep 17 00:00:00 2001 From: Josh Wolf Date: Mon, 1 Nov 2021 14:06:22 -0600 Subject: [PATCH 3/4] allow config file to be passed to hauler store serve --- cmd/hauler/cli/store.go | 2 +- cmd/hauler/cli/store/serve.go | 59 +++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/cmd/hauler/cli/store.go b/cmd/hauler/cli/store.go index 7ce2bd0..363463d 100644 --- a/cmd/hauler/cli/store.go +++ b/cmd/hauler/cli/store.go @@ -109,7 +109,7 @@ func addStoreServe() *cobra.Command { return err } - return store.ServeCmd(ctx, o, s.DataDir) + return store.ServeCmd(ctx, o, s) }, } o.AddFlags(cmd) diff --git a/cmd/hauler/cli/store/serve.go b/cmd/hauler/cli/store/serve.go index 13571d5..484951f 100644 --- a/cmd/hauler/cli/store/serve.go +++ b/cmd/hauler/cli/store/serve.go @@ -4,44 +4,42 @@ import ( "context" "fmt" "net/http" + "os" "github.com/distribution/distribution/v3/configuration" "github.com/distribution/distribution/v3/registry" "github.com/spf13/cobra" "github.com/rancherfederal/hauler/pkg/log" + "github.com/rancherfederal/hauler/pkg/store" ) type ServeOpts struct { Port int - configFile string + ConfigFile string + + storedir string } func (o *ServeOpts) AddFlags(cmd *cobra.Command) { f := cmd.Flags() f.IntVarP(&o.Port, "port", "p", 5000, "Port to listen on") + f.StringVarP(&o.ConfigFile, "config", "c", "", "Path to a config file, will override all other configs") } // ServeCmd does -func ServeCmd(ctx context.Context, o *ServeOpts, dir string) error { +func ServeCmd(ctx context.Context, o *ServeOpts, s *store.Store) error { l := log.FromContext(ctx) l.Debugf("running command `hauler store serve`") - cfg := &configuration.Configuration{ - Version: "0.1", - Storage: configuration.Storage{ - "cache": configuration.Parameters{"blobdescriptor": "inmemory"}, - "filesystem": configuration.Parameters{"rootdirectory": dir}, - - // TODO: Ensure this is toggleable via cli arg if necessary - "maintenance": configuration.Parameters{"readonly.enabled": true}, - }, - } - cfg.Log.Level = "info" - cfg.HTTP.Addr = fmt.Sprintf(":%d", o.Port) - cfg.HTTP.Headers = http.Header{ - "X-Content-Type-Options": []string{"nosniff"}, + cfg := o.defaultConfig(s) + if o.ConfigFile != "" { + ucfg, err := loadConfig(o.ConfigFile) + if err != nil { + return err + } + cfg = ucfg } r, err := registry.NewRegistry(ctx, cfg) @@ -56,3 +54,32 @@ func ServeCmd(ctx context.Context, o *ServeOpts, dir string) error { return nil } + +func loadConfig(filename string) (*configuration.Configuration, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + + return configuration.Parse(f) +} + +func (o *ServeOpts) defaultConfig(s *store.Store) *configuration.Configuration { + cfg := &configuration.Configuration{ + Version: "0.1", + Storage: configuration.Storage{ + "cache": configuration.Parameters{"blobdescriptor": "inmemory"}, + "filesystem": configuration.Parameters{"rootdirectory": s.DataDir}, + + // TODO: Ensure this is toggleable via cli arg if necessary + "maintenance": configuration.Parameters{"readonly.enabled": true}, + }, + } + cfg.Log.Level = "info" + cfg.HTTP.Addr = fmt.Sprintf(":%d", o.Port) + cfg.HTTP.Headers = http.Header{ + "X-Content-Type-Options": []string{"nosniff"}, + } + + return cfg +} From cde59cea74733d67605cb772b4870a5cabe32f00 Mon Sep 17 00:00:00 2001 From: Josh Wolf Date: Mon, 1 Nov 2021 15:29:08 -0600 Subject: [PATCH 4/4] add 'store add' set of commands for content adding --- cmd/hauler/cli/store.go | 101 ++++++++++++++++++++++++++++++++++ cmd/hauler/cli/store/add.go | 104 ++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 cmd/hauler/cli/store/add.go diff --git a/cmd/hauler/cli/store.go b/cmd/hauler/cli/store.go index 363463d..4bd0d88 100644 --- a/cmd/hauler/cli/store.go +++ b/cmd/hauler/cli/store.go @@ -21,6 +21,9 @@ func addStore(parent *cobra.Command) { addStoreLoad(), addStoreSave(), addStoreServe(), + + // TODO: Remove this in favor of sync only + addStoreAdd(), ) parent.AddCommand(cmd) @@ -139,3 +142,101 @@ func addStoreSave() *cobra.Command { return cmd } + +func addStoreAdd() *cobra.Command { + cmd := &cobra.Command{ + Use: "add", + Short: "Add content to store", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } + + cmd.AddCommand( + addStoreAddFile(), + addStoreAddImage(), + addStoreAddChart(), + ) + + return cmd +} + +func addStoreAddFile() *cobra.Command { + o := &store.AddFileOpts{} + + cmd := &cobra.Command{ + Use: "file", + Short: "Add a file to the content store", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + s, err := ro.getStore(ctx) + if err != nil { + return err + } + + ref := args[0] + + return store.AddFileCmd(ctx, o, s, ref) + }, + } + o.AddFlags(cmd) + + return cmd +} + +func addStoreAddImage() *cobra.Command { + o := &store.AddImageOpts{} + + cmd := &cobra.Command{ + Use: "image", + Short: "Add an image to the content store", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + s, err := ro.getStore(ctx) + if err != nil { + return err + } + + ref := args[0] + + return store.AddImageCmd(ctx, o, s, ref) + }, + } + o.AddFlags(cmd) + + return cmd +} + +func addStoreAddChart() *cobra.Command { + o := &store.AddChartOpts{} + + cmd := &cobra.Command{ + Use: "chart", + Short: "Add a chart to the content store", + Example: ` +# add a chart +hauler store add longhorn --repo "https://charts.longhorn.io" + +# add a specific version of a chart +hauler store add chart rancher --repo "https://releases.rancher.com/server-charts/latest" --version "2.6.2" +`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + s, err := ro.getStore(ctx) + if err != nil { + return err + } + + return store.AddChartCmd(ctx, o, s, args[0]) + }, + } + o.AddFlags(cmd) + + return cmd +} diff --git a/cmd/hauler/cli/store/add.go b/cmd/hauler/cli/store/add.go new file mode 100644 index 0000000..fb3aac5 --- /dev/null +++ b/cmd/hauler/cli/store/add.go @@ -0,0 +1,104 @@ +package store + +import ( + "context" + + "github.com/spf13/cobra" + + "github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1" + "github.com/rancherfederal/hauler/pkg/content/chart" + "github.com/rancherfederal/hauler/pkg/content/file" + "github.com/rancherfederal/hauler/pkg/content/image" + "github.com/rancherfederal/hauler/pkg/log" + "github.com/rancherfederal/hauler/pkg/store" +) + +type AddFileOpts struct { + Name string +} + +func (o *AddFileOpts) AddFlags(cmd *cobra.Command) { + f := cmd.Flags() + f.StringVarP(&o.Name, "name", "n", "", "(Optional) Name to assign to file in store") +} + +func AddFileCmd(ctx context.Context, o *AddFileOpts, s *store.Store, ref string) error { + l := log.FromContext(ctx) + l.Debugf("running cli command `hauler store add`") + + s.Open() + defer s.Close() + + cfg := v1alpha1.File{ + Ref: ref, + Name: o.Name, + } + + f := file.NewFile(cfg) + return s.Add(ctx, f) +} + +type AddImageOpts struct { + Name string +} + +func (o *AddImageOpts) AddFlags(cmd *cobra.Command) { + f := cmd.Flags() + _ = f +} + +func AddImageCmd(ctx context.Context, o *AddImageOpts, s *store.Store, ref string) error { + l := log.FromContext(ctx) + l.Debugf("running cli command `hauler store add image`") + + s.Open() + defer s.Close() + + cfg := v1alpha1.Image{ + Ref: ref, + } + + i := image.NewImage(cfg) + return s.Add(ctx, i) +} + +type AddChartOpts struct { + Name string + Version string + RepoURL string + + // TODO: Support helm auth + Username string + Password string + PassCredentialsAll bool + CertFile string + KeyFile string + CaFile string + InsecureSkipTLSverify bool + RepositoryConfig string + RepositoryCache string +} + +func (o *AddChartOpts) AddFlags(cmd *cobra.Command) { + f := cmd.Flags() + + f.StringVarP(&o.RepoURL, "repo", "r", "", "Chart repository URL") + f.StringVar(&o.Version, "version", "", "(Optional) Version of the chart to download, defaults to latest if not specified") +} + +func AddChartCmd(ctx context.Context, o *AddChartOpts, s *store.Store, name string) error { + l := log.FromContext(ctx) + l.Debugf("running cli command `hauler store add chart`") + + s.Open() + defer s.Close() + + cfg := v1alpha1.Chart{ + Name: name, + RepoURL: o.RepoURL, + Version: o.Version, + } + + c := chart.NewChart(cfg) + return s.Add(ctx, c) +}