github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/romulus/setplan/set_plan.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // The setplan package contains the implementation of the juju set-plan
     5  // command.
     6  package setplan
     7  
     8  import (
     9  	"encoding/json"
    10  	"net/url"
    11  
    12  	"github.com/juju/cmd"
    13  	"github.com/juju/errors"
    14  	"github.com/juju/juju/api/application"
    15  	"github.com/juju/juju/cmd/modelcmd"
    16  	"gopkg.in/juju/names.v2"
    17  	"gopkg.in/macaroon.v1"
    18  
    19  	api "github.com/juju/romulus/api/plan"
    20  )
    21  
    22  // authorizationClient defines the interface of an api client that
    23  // the comand uses to create an authorization macaroon.
    24  type authorizationClient interface {
    25  	// Authorize returns the authorization macaroon for the specified environment,
    26  	// charm url, application name and plan.
    27  	Authorize(environmentUUID, charmURL, applicationName, plan string, visitWebPage func(*url.URL) error) (*macaroon.Macaroon, error)
    28  }
    29  
    30  var newAuthorizationClient = func(options ...api.ClientOption) (authorizationClient, error) {
    31  	return api.NewAuthorizationClient(options...)
    32  }
    33  
    34  // NewSetPlanCommand returns a new command that is used to set metric credentials for a
    35  // deployed application.
    36  func NewSetPlanCommand() cmd.Command {
    37  	return modelcmd.Wrap(&setPlanCommand{})
    38  }
    39  
    40  // setPlanCommand is a command-line tool for setting
    41  // Application.MetricCredential for development & demonstration purposes.
    42  type setPlanCommand struct {
    43  	modelcmd.ModelCommandBase
    44  
    45  	Application string
    46  	Plan        string
    47  }
    48  
    49  // Info implements cmd.Command.
    50  func (c *setPlanCommand) Info() *cmd.Info {
    51  	return &cmd.Info{
    52  		Name:    "set-plan",
    53  		Args:    "<application name> <plan>",
    54  		Purpose: "Set the plan for an application.",
    55  		Doc: `
    56  Set the plan for the deployed application, effective immediately.
    57  
    58  The specified plan name must be a valid plan that is offered for this
    59  particular charm. Use "juju list-plans <charm>" for more information.
    60  
    61  Examples:
    62      juju set-plan myapp example/uptime
    63  `,
    64  	}
    65  }
    66  
    67  // Init implements cmd.Command.
    68  func (c *setPlanCommand) Init(args []string) error {
    69  	if len(args) < 2 {
    70  		return errors.New("need to specify application name and plan url")
    71  	}
    72  
    73  	applicationName := args[0]
    74  	if !names.IsValidApplication(applicationName) {
    75  		return errors.Errorf("invalid application name %q", applicationName)
    76  	}
    77  
    78  	c.Plan = args[1]
    79  	c.Application = applicationName
    80  
    81  	return c.ModelCommandBase.Init(args[2:])
    82  }
    83  
    84  func (c *setPlanCommand) requestMetricCredentials(client *application.Client, ctx *cmd.Context) ([]byte, error) {
    85  	envUUID := client.ModelUUID()
    86  	charmURL, err := client.GetCharmURL(c.Application)
    87  	if err != nil {
    88  		return nil, errors.Trace(err)
    89  	}
    90  
    91  	hc, err := c.BakeryClient()
    92  	if err != nil {
    93  		return nil, errors.Trace(err)
    94  	}
    95  	authClient, err := newAuthorizationClient(api.HTTPClient(hc))
    96  	if err != nil {
    97  		return nil, errors.Trace(err)
    98  	}
    99  	m, err := authClient.Authorize(envUUID, charmURL.String(), c.Application, c.Plan, hc.VisitWebPage)
   100  	if err != nil {
   101  		return nil, errors.Trace(err)
   102  	}
   103  	ms := macaroon.Slice{m}
   104  	return json.Marshal(ms)
   105  }
   106  
   107  // Run implements cmd.Command.
   108  func (c *setPlanCommand) Run(ctx *cmd.Context) error {
   109  	root, err := c.NewAPIRoot()
   110  	if err != nil {
   111  		return errors.Trace(err)
   112  	}
   113  	client := application.NewClient(root)
   114  	credentials, err := c.requestMetricCredentials(client, ctx)
   115  	if err != nil {
   116  		return errors.Trace(err)
   117  	}
   118  	err = client.SetMetricCredentials(c.Application, credentials)
   119  	if err != nil {
   120  		return errors.Trace(err)
   121  	}
   122  	return nil
   123  }