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 }