github.com/saucelabs/saucectl@v0.175.1/internal/cmd/apit/downloadfile.go (about) 1 package apit 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "os" 9 10 "github.com/spf13/cobra" 11 "golang.org/x/text/cases" 12 "golang.org/x/text/language" 13 14 "github.com/saucelabs/saucectl/internal/apitest" 15 cmds "github.com/saucelabs/saucectl/internal/cmd" 16 "github.com/saucelabs/saucectl/internal/http" 17 "github.com/saucelabs/saucectl/internal/segment" 18 "github.com/saucelabs/saucectl/internal/usage" 19 ) 20 21 func DownloadFileCommand() *cobra.Command { 22 cmd := &cobra.Command{ 23 Use: "download-file FILENAME [--project PROJECT_NAME]", 24 Short: "Download a vault file", 25 Long: `Download a file from a project's vault. 26 27 Use [--project] to specify the project by its name or run without [--project] to choose from a list of projects. 28 `, 29 SilenceUsage: true, 30 Args: func(cmd *cobra.Command, args []string) error { 31 if len(args) == 0 || args[0] == "" { 32 return errors.New("no file name specified") 33 } 34 return nil 35 }, 36 PreRunE: func(cmd *cobra.Command, args []string) error { 37 err := http.CheckProxy() 38 if err != nil { 39 return fmt.Errorf("invalid HTTP_PROXY value") 40 } 41 42 tracker := segment.DefaultTracker 43 44 go func() { 45 tracker.Collect( 46 cases.Title(language.English).String(cmds.FullName(cmd)), 47 usage.Properties{}.SetFlags(cmd.Flags()), 48 ) 49 _ = tracker.Close() 50 }() 51 return nil 52 }, 53 RunE: func(cmd *cobra.Command, args []string) error { 54 name := args[0] 55 files, err := apitesterClient.ListVaultFiles(context.Background(), selectedProject.ID) 56 if err != nil { 57 return err 58 } 59 60 file, err := findMatchingFile(name, files) 61 if err != nil { 62 return fmt.Errorf("project %q has no vault drive file with name %q", selectedProject.ProjectMeta.Name, name) 63 } 64 65 bodyReader, err := apitesterClient.GetVaultFileContent(context.Background(), selectedProject.ID, file.ID) 66 if err != nil { 67 return err 68 } 69 70 err = saveFileToDisk(bodyReader, name) 71 if err != nil { 72 return err 73 } 74 fmt.Printf("File %q has been successfully retrieved.\n", name) 75 return nil 76 }, 77 } 78 return cmd 79 } 80 81 func saveFileToDisk(rc io.ReadCloser, fileName string) error { 82 defer rc.Close() 83 84 fd, err := os.Create(fileName) 85 if err != nil { 86 return err 87 } 88 defer fd.Close() 89 90 _, err = io.Copy(fd, rc) 91 return err 92 } 93 94 func findMatchingFile(fileName string, files []apitest.VaultFile) (apitest.VaultFile, error) { 95 for _, file := range files { 96 if file.Name == fileName { 97 return file, nil 98 } 99 } 100 return apitest.VaultFile{}, fmt.Errorf("no file named %s found", fileName) 101 }