github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/backups/upload.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package backups 5 6 import ( 7 "fmt" 8 9 "github.com/juju/cmd" 10 "github.com/juju/errors" 11 12 "github.com/juju/juju/apiserver/params" 13 jujucmd "github.com/juju/juju/cmd" 14 "github.com/juju/juju/cmd/modelcmd" 15 ) 16 17 const uploadDoc = ` 18 upload-backup sends a backup archive file to remote storage. 19 ` 20 21 // NewUploadCommand returns a command used to send a backup 22 // achieve file to remote storage. 23 func NewUploadCommand() cmd.Command { 24 return modelcmd.Wrap(&uploadCommand{}) 25 } 26 27 // uploadCommand is the sub-command for uploading a backup archive. 28 type uploadCommand struct { 29 CommandBase 30 // Filename is where to find the archive to upload. 31 Filename string 32 } 33 34 // Info implements Command.Info. 35 func (c *uploadCommand) Info() *cmd.Info { 36 return jujucmd.Info(&cmd.Info{ 37 Name: "upload-backup", 38 Args: "<filename>", 39 Purpose: "Store a backup archive file remotely in Juju.", 40 Doc: uploadDoc, 41 }) 42 } 43 44 // Init implements Command.Init. 45 func (c *uploadCommand) Init(args []string) error { 46 if len(args) == 0 { 47 return errors.New("backup filename not specified") 48 } 49 filename, args := args[0], args[1:] 50 if err := cmd.CheckEmpty(args); err != nil { 51 return errors.Trace(err) 52 } 53 c.Filename = filename 54 return nil 55 } 56 57 // Run implements Command.Run. 58 func (c *uploadCommand) Run(ctx *cmd.Context) error { 59 if c.Log != nil { 60 if err := c.Log.Start(ctx); err != nil { 61 return err 62 } 63 } 64 client, err := c.NewAPIClient() 65 if err != nil { 66 return errors.Trace(err) 67 } 68 defer client.Close() 69 70 archive, meta, err := getArchive(c.Filename) 71 if err != nil { 72 return errors.Trace(err) 73 } 74 defer archive.Close() 75 76 if c.Log != nil && c.Log.Verbose { 77 fmt.Fprintln(ctx.Stdout, "Uploaded metadata:") 78 c.dumpMetadata(ctx, meta) 79 fmt.Fprintln(ctx.Stdout) 80 } 81 82 // Upload the archive. 83 id, err := client.Upload(archive, *meta) 84 if err != nil { 85 return errors.Trace(err) 86 } 87 88 if c.Log != nil && c.Log.Quiet { 89 fmt.Fprintln(ctx.Stdout, id) 90 return nil 91 } 92 93 // Pull the stored metadata. 94 stored, err := c.getStoredMetadata(id) 95 if err != nil { 96 return errors.Trace(err) 97 } 98 99 c.dumpMetadata(ctx, stored) 100 return nil 101 } 102 103 func (c *uploadCommand) getStoredMetadata(id string) (*params.BackupsMetadataResult, error) { 104 // TODO(ericsnow) lp-1399722 This should be addressed. 105 // There is at least anecdotal evidence that we cannot use an API 106 // client for more than a single request. So we use a new client 107 // for download. 108 client, err := c.NewAPIClient() 109 if err != nil { 110 return nil, errors.Trace(err) 111 } 112 defer client.Close() 113 114 stored, err := client.Info(id) 115 return stored, errors.Trace(err) 116 }