github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/gui/gui.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package gui 5 6 import ( 7 "fmt" 8 "net/url" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "github.com/juju/httprequest" 13 "github.com/juju/webbrowser" 14 "launchpad.net/gnuflag" 15 16 "github.com/juju/juju/api" 17 "github.com/juju/juju/cmd/modelcmd" 18 ) 19 20 // NewGUICommand creates and returns a new gui command. 21 func NewGUICommand() cmd.Command { 22 return modelcmd.Wrap(&guiCommand{}) 23 } 24 25 // guiCommand opens the Juju GUI in the default browser. 26 type guiCommand struct { 27 modelcmd.ModelCommandBase 28 29 showCreds bool 30 noBrowser bool 31 } 32 33 const guiDoc = ` 34 Open the Juju GUI in the default browser: 35 36 juju gui 37 38 Open the GUI and show admin credentials to use to log into it: 39 40 juju gui --show-credentials 41 42 Do not open the browser, just output the GUI URL: 43 44 juju gui --no-browser 45 46 An error is returned if the Juju GUI is not available in the controller. 47 ` 48 49 // Info implements the cmd.Command interface. 50 func (c *guiCommand) Info() *cmd.Info { 51 return &cmd.Info{ 52 Name: "gui", 53 Purpose: "open the Juju GUI in the default browser", 54 Doc: guiDoc, 55 } 56 } 57 58 // SetFlags implements the cmd.Command interface. 59 func (c *guiCommand) SetFlags(f *gnuflag.FlagSet) { 60 f.BoolVar(&c.showCreds, "show-credentials", false, "show admin credentials to use for logging into the Juju GUI") 61 f.BoolVar(&c.noBrowser, "no-browser", false, "do not try to open the web browser, just print the Juju GUI URL") 62 } 63 64 // Run implements the cmd.Command interface. 65 func (c *guiCommand) Run(ctx *cmd.Context) error { 66 // Retrieve model details. 67 conn, err := c.NewAPIRoot() 68 if err != nil { 69 return errors.Annotate(err, "cannot establish API connection") 70 } 71 defer conn.Close() 72 details, err := c.ClientStore().ModelByName(c.ControllerName(), c.AccountName(), c.ModelName()) 73 if err != nil { 74 return errors.Annotate(err, "cannot retrieve model details") 75 } 76 rawURL := fmt.Sprintf("https://%s/gui/%s/", conn.Addr(), details.ModelUUID) 77 78 // Check that the Juju GUI is available. 79 if err = c.checkAvailable(rawURL, conn); err != nil { 80 return errors.Trace(err) 81 } 82 83 // Open the Juju GUI in the browser. 84 if err = c.openBrowser(ctx, rawURL); err != nil { 85 return errors.Trace(err) 86 } 87 88 // Print login credentials if requested. 89 if err = c.showCredentials(ctx); err != nil { 90 return errors.Trace(err) 91 } 92 return nil 93 } 94 95 // checkAvailable ensures the Juju GUI is available on the controller at the 96 // given URL. 97 func (c *guiCommand) checkAvailable(rawURL string, conn api.Connection) error { 98 client, err := conn.HTTPClient() 99 if err != nil { 100 return errors.Annotate(err, "cannot retrieve HTTP client") 101 } 102 if err = clientGet(client, rawURL); err != nil { 103 return errors.Annotate(err, "Juju GUI is not available") 104 } 105 return nil 106 } 107 108 // openBrowser opens the Juju GUI at the given URL. 109 func (c *guiCommand) openBrowser(ctx *cmd.Context, rawURL string) error { 110 u, err := url.Parse(rawURL) 111 if err != nil { 112 return errors.Annotate(err, "cannot parse Juju GUI URL") 113 } 114 if c.noBrowser { 115 ctx.Infof(u.String()) 116 return nil 117 } 118 err = webbrowserOpen(u) 119 if err == nil { 120 ctx.Infof("Opening the Juju GUI in your browser.") 121 ctx.Infof("If it does not open, open this URL:\n%s", u) 122 return nil 123 } 124 if err == webbrowser.ErrNoBrowser { 125 ctx.Infof("Open this URL in your browser:\n%s", u) 126 return nil 127 } 128 return errors.Annotate(err, "cannot open web browser") 129 } 130 131 // showCredentials shows the admin username and password. 132 func (c *guiCommand) showCredentials(ctx *cmd.Context) error { 133 if !c.showCreds { 134 return nil 135 } 136 // TODO(wallyworld) - what to do if we are using a macaroon. 137 if c.AccountName() == "" { 138 return errors.Errorf("no connection credentials available") 139 } 140 accountDetails, err := c.ClientStore().AccountByName( 141 c.ControllerName(), c.AccountName(), 142 ) 143 if err != nil { 144 return errors.Annotate(err, "cannot retrieve credentials") 145 } 146 ctx.Infof("Username: %s\nPassword: %s", accountDetails.User, accountDetails.Password) 147 return nil 148 } 149 150 // clientGet is defined for testing purposes. 151 var clientGet = func(client *httprequest.Client, rawURL string) error { 152 return client.Get(rawURL, nil) 153 } 154 155 // webbrowserOpen is defined for testing purposes. 156 var webbrowserOpen = webbrowser.Open