From 2536848541927dacc214dbde056f509f88205946 Mon Sep 17 00:00:00 2001 From: David Allen Date: Thu, 28 Aug 2025 18:20:40 -0600 Subject: [PATCH] refactor: changed how file/archives are downloaded and saved --- cmd/download.go | 62 +++++++++++++++++++++++++++++-------------- pkg/service/routes.go | 23 +++++++++++----- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/cmd/download.go b/cmd/download.go index edf09df..7d00d01 100644 --- a/cmd/download.go +++ b/cmd/download.go @@ -5,9 +5,7 @@ import ( "net/http" "net/url" "os" - "path/filepath" "strings" - "time" "git.towk2.me/towk/makeshift/pkg/client" "github.com/rs/zerolog/log" @@ -30,7 +28,7 @@ var downloadCmd = cobra.Command{ curl $MAKESHIFT_HOST/download/test?plugins=smd,jinja2&profile=test # download directory and extract it's contents automatically - makeshift download --extract + makeshift download -xr `, Short: "Download and modify files with plugins", PreRun: func(cmd *cobra.Command, args []string) { @@ -52,15 +50,6 @@ var downloadCmd = cobra.Command{ err error ) - // set output path to match path if empty - if outputPath == "" { - if path != "." || path != "" { - outputPath = filepath.Base(path) - } else { - outputPath = fmt.Sprintf("%d.file", time.Now().Unix()) - } - } - query = fmt.Sprintf("/download/%s?", path) if len(pluginNames) > 0 { query += "plugins=" + url.QueryEscape(strings.Join(pluginNames, ",")) @@ -102,33 +91,66 @@ var downloadCmd = cobra.Command{ Msg("response returned bad status") os.Exit(1) } - if outputPath != "" { + + // helper to write downloaded files + var writeFiles = func(path string, body []byte) { err = os.WriteFile(outputPath, body, 0o755) if err != nil { log.Error().Err(err).Msg("failed to write file(s) from download") os.Exit(1) } - } else { - fmt.Println(string(body)) } + // determine if output path is an archive or file + switch res.Header.Get("FILETYPE") { + case "archive": + // write archive to disk with or without '-o' specified + if outputPath == "" { + outputPath = fmt.Sprintf("%s.tar.gz", path) + writeFiles(outputPath, body) + log.Debug().Str("path", outputPath).Msg("wrote archive to pre-determined path") + } else { + writeFiles(outputPath, body) + log.Debug().Str("path", outputPath).Msg("wrote archive to specified path") + } + case "file": + // write to file if '-o' specified otherwise stdout + if outputPath != "" { + writeFiles(outputPath, body) + log.Debug().Str("path", outputPath).Msg("wrote file to specified path") + } else { + fmt.Println(string(body)) + } + } }, } var downloadProfileCmd = &cobra.Command{ - Use: "profile", + Use: "profile", + Short: "Download a profile", + Run: func(cmd *cobra.Command, args []string) { + + }, } + var downloadPluginCmd = &cobra.Command{ - Use: "plugin", + Use: "plugin", + Short: "Download a plugin", + Run: func(cmd *cobra.Command, args []string) { + + }, } func init() { downloadCmd.Flags().String("host", "http://localhost:5050", "Set the makeshift remote host (can be set with MAKESHIFT_HOST)") downloadCmd.Flags().StringP("path", "p", ".", "Set the path to list files (can be set with MAKESHIFT_PATH)") downloadCmd.Flags().StringP("output", "o", "", "Set the output path to write files") - downloadCmd.Flags().StringSlice("profiles", []string{}, "Set the profile to use to populate data store") - downloadCmd.Flags().StringSlice("plugins", []string{}, "Set the plugins to run before downloading files") - downloadCmd.Flags().Bool("extract", false, "Set whether to extract archive locally after downloading") + downloadCmd.Flags().StringSlice("profiles", []string{}, "Set the profile(s) to use to populate data store") + downloadCmd.Flags().StringSlice("plugins", []string{}, "Set the plugin(s) to run before downloading files") + downloadCmd.Flags().BoolP("extract", "x", false, "Set whether to extract archive locally after downloading") + downloadCmd.Flags().BoolP("remove-archive", "r", false, "Set whether to remove the archive after extracting (used with '--extract' flag)") + + downloadCmd.MarkFlagsRequiredTogether("remove-archive", "extract") downloadCmd.AddCommand(downloadProfileCmd, downloadPluginCmd) diff --git a/pkg/service/routes.go b/pkg/service/routes.go index cd96218..3d2db0b 100644 --- a/pkg/service/routes.go +++ b/pkg/service/routes.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "strings" - "time" "git.towk2.me/towk/makeshift/internal/archive" makeshift "git.towk2.me/towk/makeshift/pkg" @@ -54,7 +53,7 @@ func (s *Service) Download() http.HandlerFunc { if fileInfo, err = os.Stat(path); err == nil { if fileInfo.IsDir() { // get the final archive path - archivePath := fmt.Sprintf("%d.tar.gz", time.Now().Unix()) + archivePath := fmt.Sprintf("%s.tar.gz", path) log.Debug(). Str("archive_path", archivePath). @@ -98,6 +97,8 @@ func (s *Service) Download() http.HandlerFunc { return } + // send the archive back as response + w.Header().Add("FILETYPE", "archive") w.Write(contents) // clean up the temporary archive @@ -128,7 +129,6 @@ func (s *Service) Download() http.HandlerFunc { errs = []error{} } if len(hooks) > 0 { - // run pre-hooks to modify the contents of the file before archiving log.Debug().Int("hook_count", len(hooks)).Msg("running hooks") for _, hook := range hooks { @@ -143,7 +143,10 @@ func (s *Service) Download() http.HandlerFunc { }).Send() err = hook.Run() if err != nil { - log.Error().Err(err).Str("plugin", hook.Plugin.Name()).Msg("failed to run plugin") + log.Error(). + Err(err). + Str("plugin", hook.Plugin.Name()). + Msg("failed to run plugin") continue } } @@ -158,8 +161,13 @@ func (s *Service) Download() http.HandlerFunc { s.writeErrorResponse(w, fmt.Sprintf("failed to get data from hook: %v", err), http.StatusInternalServerError) return } + + // send processed (with plugins) file back as response + w.Header().Add("FILETYPE", "file") w.Write(data.([]byte)) } else { + // send non-processed file back as response + w.Header().Add("FILETYPE", "file") w.Write(contents) } @@ -223,7 +231,7 @@ func (s *Service) GetStatus(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") err := json.NewEncoder(w).Encode(map[string]any{ "code": http.StatusOK, - "message": "Configurator is healthy", + "message": "The makeshift server is healthy", }) if err != nil { fmt.Printf("failed to encode JSON response body: %v\n", err) @@ -274,17 +282,18 @@ func (s *Service) loadPlugins(pluginNames []string, store storage.KVStore, args err error ) if i > DEFAULT_PLUGINS_MAX_COUNT { - log.Warn().Msg("max plugins count reached...stopping") + log.Warn().Msg("max plugins count reached or exceeded...stopping") return hooks, errs } if pluginName == "" { - log.Warn().Msg("plugin name is empty...skipping") + log.Warn().Msgf("no plugin name found with index %d...skipping", i) continue } log.Debug(). Str("name", pluginName). Str("path", pluginPath). Msg("load plugin") + // load the plugin from disk plugin, err = LoadPluginFromFile(pluginPath) if err != nil {