/* * Copyright 2026 Oleg Borodin */ package filecmd import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "sigs.k8s.io/yaml" ) type FileUtil struct { fileInfoParams FileInfoParams putFileParams PutFileParams getFileParams GetFileParams deleteFileParams DeleteFileParams listFilesParams ListFilesParams importFilesParams ImportFilesParams exportFilesParams ExportFilesParams deleteCollectionParams DeleteCollectionParams listCollectionsParams ListCollectionsParams commonFileParams CommonFileParams } func NewFileUtil() *FileUtil { return &FileUtil{} } func (util *FileUtil) MakeFileCmds() *cobra.Command { var subCmd = &cobra.Command{ Use: "files", Short: "File operations", Aliases: []string{"file"}, } const defaultTimeout uint64 = 10 subCmd.PersistentFlags().StringVarP(&util.commonFileParams.Username, "user", "u", "", "Username") subCmd.PersistentFlags().StringVarP(&util.commonFileParams.Password, "pass", "p", "", "Password") subCmd.PersistentFlags().Uint64VarP(&util.commonFileParams.Timeout, "timeout", "t", defaultTimeout, "Operation timeout") subCmd.PersistentFlags().BoolVarP(&util.commonFileParams.SkipTLSVerify, "skipVerify", "S", true, "Skip server certificate verify") subCmd.MarkPersistentFlagRequired("host") subCmd.MarkFlagsRequiredTogether("user", "pass") vi := viper.New() vi.SetEnvPrefix("mstore") vi.BindEnv("user") vi.BindEnv("pass") util.commonFileParams.Username = vi.GetString("user") util.commonFileParams.Password = vi.GetString("pass") // PutFile var putFileCmd = &cobra.Command{ Use: "put filepath [user:pass@]hostname[:port]/collection/name", Args: cobra.ExactArgs(2), Aliases: []string{"push"}, Short: "Put file to storage", Run: util.PutFile, } putFileCmd.Flags().BoolVarP(&util.putFileParams.Chart, "chart", "C", false, "Upload as helm chart archive") subCmd.AddCommand(putFileCmd) // GetFile var getFileCmd = &cobra.Command{ Use: "get [user:pass@]hostname[:port]/collection/name filepath", Aliases: []string{"pull"}, Args: cobra.ExactArgs(2), Short: "Get file from storage", Run: util.GetFile, } subCmd.AddCommand(getFileCmd) // FileInfo var fileInfoCmd = &cobra.Command{ Use: "info [user:pass@]hostname[:port]/collection/name", Args: cobra.ExactArgs(1), Short: "Show file information", Run: util.FileInfo, } subCmd.AddCommand(fileInfoCmd) // DeleteFile var deleteFileCmd = &cobra.Command{ Use: "delete [user:pass@]hostname[:port]/collection/name", Args: cobra.ExactArgs(1), Aliases: []string{"remove"}, Short: "Delete file in storage", Run: util.DeleteFile, } subCmd.AddCommand(deleteFileCmd) // ListFiles var listFilesCmd = &cobra.Command{ Use: "list [user:pass@]hostname[:port]/catalog", Args: cobra.ExactArgs(1), Short: "List files in storage", Run: util.ListFiles, } listFilesCmd.Flags().BoolVarP(&util.listFilesParams.Detail, "detail", "D", false, "Show detail file information") listFilesCmd.Flags().BoolVarP(&util.listFilesParams.Prefix, "prefix", "P", true, "Use path as collection path prefix") listFilesCmd.Flags().BoolVarP(&util.listFilesParams.Regexp, "regex", "R", false, "Use path as collection path prefix") subCmd.AddCommand(listFilesCmd) // ImportFiles var importFilesCmd = &cobra.Command{ Use: "import directory [user:pass@]hostname[:port]/collection", Args: cobra.ExactArgs(2), Short: "Send file tree to storage as is", Run: util.ImportFiles, } importFilesCmd.Flags().BoolVarP(&util.importFilesParams.Chart, "chart", "C", false, "Upload as helm chart archives") subCmd.AddCommand(importFilesCmd) // ExportFiles var exportFilesCmd = &cobra.Command{ Use: "export directory [user:pass@]hostname[:port]/collection dir", Args: cobra.ExactArgs(2), Short: "Download file tree to storage as is", Run: util.ExportFiles, } exportFilesCmd.Flags().BoolVarP(&util.exportFilesParams.Detail, "detail", "D", false, "Show detail file information") exportFilesCmd.Flags().BoolVarP(&util.exportFilesParams.Prefix, "prefix", "P", true, "Use path as collection path prefix") exportFilesCmd.Flags().BoolVarP(&util.exportFilesParams.Regexp, "regex", "R", false, "Use path as collection path prefix") subCmd.AddCommand(exportFilesCmd) return subCmd } func (util *FileUtil) MakeCollectionCmds() *cobra.Command { var subCmd = &cobra.Command{ Use: "collections", Short: "Colletion operations", Aliases: []string{"col", "cols", "dir", "dirs"}, } const defaultTimeout uint64 = 10 subCmd.PersistentFlags().StringVarP(&util.commonFileParams.Username, "user", "u", "", "Username") subCmd.PersistentFlags().StringVarP(&util.commonFileParams.Password, "pass", "p", "", "Password") subCmd.PersistentFlags().Uint64VarP(&util.commonFileParams.Timeout, "timeout", "t", defaultTimeout, "Operation timeout") subCmd.MarkPersistentFlagRequired("host") subCmd.MarkFlagsRequiredTogether("user", "pass") // ListCollections var listCollectionsCmd = &cobra.Command{ Use: "list [user:pass@]hostname[:port]/catalog", Args: cobra.ExactArgs(1), Short: "List collections in storage", Run: util.ListCollections, } listCollectionsCmd.Flags().BoolVarP(&util.listCollectionsParams.Prefix, "prefix", "P", true, "Use path as collection path prefix") subCmd.AddCommand(listCollectionsCmd) // DeleteCollection var deleteCollectionCmd = &cobra.Command{ Use: "delete [user:pass@]hostname[:port]/catalog", Args: cobra.ExactArgs(1), Short: "Delete all files in collection", Run: util.DeleteCollection, } deleteCollectionCmd.Flags().BoolVarP(&util.deleteCollectionParams.Detail, "detail", "D", false, "Show detail file information") deleteCollectionCmd.Flags().BoolVarP(&util.deleteCollectionParams.Prefix, "prefix", "P", false, "Use path as collection path prefix") deleteCollectionCmd.Flags().BoolVarP(&util.deleteCollectionParams.Regexp, "regex", "R", false, "Use path as collection path prefix") deleteCollectionCmd.Flags().BoolVarP(&util.deleteCollectionParams.DryRun, "dryrun", "Y", false, "Simulate process, don't delete files") subCmd.AddCommand(deleteCollectionCmd) return subCmd } type CommonFileParams struct { Username string Password string Timeout uint64 SkipTLSVerify bool } func printResponse(res any, err error) { type Response struct { Error bool `json:"error" json:"error"` Message string `json:"message,omitempty" json:"message,omitempty"` Result any `json:"result,omitempty" json:"result,omitempty"` } resp := Response{} if err != nil { resp.Error = true resp.Message = err.Error() } else { resp.Result = res } respBytes, _ := yaml.Marshal(resp) fmt.Printf("---\n%s\n", string(respBytes)) }