github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/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  	"launchpad.net/gnuflag"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  )
    15  
    16  const uploadDoc = `
    17  "upload" sends a backup archive file to remote storage.
    18  `
    19  
    20  // UploadCommand is the sub-command for uploading a backup archive.
    21  type UploadCommand struct {
    22  	CommandBase
    23  	// Filename is where to find the archive to upload.
    24  	Filename string
    25  	// ShowMeta indicates that the uploaded metadata should be printed.
    26  	ShowMeta bool
    27  	// Quiet indicates that the new backup ID should not be printed.
    28  	Quiet bool
    29  }
    30  
    31  // SetFlags implements Command.SetFlags.
    32  func (c *UploadCommand) SetFlags(f *gnuflag.FlagSet) {
    33  	f.BoolVar(&c.ShowMeta, "verbose", false, "show the uploaded metadata")
    34  	f.BoolVar(&c.Quiet, "quiet", false, "do not print the new backup ID")
    35  }
    36  
    37  // Info implements Command.Info.
    38  func (c *UploadCommand) Info() *cmd.Info {
    39  	return &cmd.Info{
    40  		Name:    "upload",
    41  		Args:    "<filename>",
    42  		Purpose: "store a backup archive file remotely in juju",
    43  		Doc:     uploadDoc,
    44  	}
    45  }
    46  
    47  // Init implements Command.Init.
    48  func (c *UploadCommand) Init(args []string) error {
    49  	if len(args) == 0 {
    50  		return errors.New("backup filename not specified")
    51  	}
    52  	filename, args := args[0], args[1:]
    53  	if err := cmd.CheckEmpty(args); err != nil {
    54  		return errors.Trace(err)
    55  	}
    56  	c.Filename = filename
    57  	return nil
    58  }
    59  
    60  // Run implements Command.Run.
    61  func (c *UploadCommand) Run(ctx *cmd.Context) error {
    62  	client, err := c.NewAPIClient()
    63  	if err != nil {
    64  		return errors.Trace(err)
    65  	}
    66  	defer client.Close()
    67  
    68  	archive, meta, err := getArchive(c.Filename)
    69  	if err != nil {
    70  		return errors.Trace(err)
    71  	}
    72  	defer archive.Close()
    73  
    74  	if c.ShowMeta {
    75  		fmt.Fprintln(ctx.Stdout, "Uploaded metadata:")
    76  		c.dumpMetadata(ctx, meta)
    77  		fmt.Fprintln(ctx.Stdout)
    78  	}
    79  
    80  	// Upload the archive.
    81  	id, err := client.Upload(archive, *meta)
    82  	if err != nil {
    83  		return errors.Trace(err)
    84  	}
    85  
    86  	if c.Quiet {
    87  		fmt.Fprintln(ctx.Stdout, id)
    88  		return nil
    89  	}
    90  
    91  	// Pull the stored metadata.
    92  	stored, err := c.getStoredMetadata(id)
    93  	if err != nil {
    94  		return errors.Trace(err)
    95  	}
    96  
    97  	c.dumpMetadata(ctx, stored)
    98  	return nil
    99  }
   100  
   101  func (c *UploadCommand) getStoredMetadata(id string) (*params.BackupsMetadataResult, error) {
   102  	// TODO(ericsnow) lp-1399722 This should be addressed.
   103  	// There is at least anecdotal evidence that we cannot use an API
   104  	// client for more than a single request. So we use a new client
   105  	// for download.
   106  	client, err := c.NewAPIClient()
   107  	if err != nil {
   108  		return nil, errors.Trace(err)
   109  	}
   110  	defer client.Close()
   111  
   112  	stored, err := client.Info(id)
   113  	return stored, errors.Trace(err)
   114  }