github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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/gnuflag" 13 "github.com/juju/httprequest" 14 "github.com/juju/webbrowser" 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 c.ModelCommandBase.SetFlags(f) 61 f.BoolVar(&c.showCreds, "show-credentials", false, "Show admin credentials to use for logging into the Juju GUI") 62 f.BoolVar(&c.noBrowser, "no-browser", false, "Do not try to open the web browser, just print the Juju GUI URL") 63 } 64 65 // Run implements the cmd.Command interface. 66 func (c *guiCommand) Run(ctx *cmd.Context) error { 67 // Retrieve model details. 68 conn, err := c.NewAPIRoot() 69 if err != nil { 70 return errors.Annotate(err, "cannot establish API connection") 71 } 72 defer conn.Close() 73 details, err := c.ClientStore().ModelByName(c.ControllerName(), c.ModelName()) 74 if err != nil { 75 return errors.Annotate(err, "cannot retrieve model details") 76 } 77 rawURL := fmt.Sprintf("https://%s/gui/%s/", conn.Addr(), details.ModelUUID) 78 79 // Check that the Juju GUI is available. 80 if err = c.checkAvailable(rawURL, conn); err != nil { 81 return errors.Trace(err) 82 } 83 84 // Open the Juju GUI in the browser. 85 if err = c.openBrowser(ctx, rawURL); err != nil { 86 return errors.Trace(err) 87 } 88 89 // Print login credentials if requested. 90 if err = c.showCredentials(ctx); err != nil { 91 return errors.Trace(err) 92 } 93 return nil 94 } 95 96 // checkAvailable ensures the Juju GUI is available on the controller at the 97 // given URL. 98 func (c *guiCommand) checkAvailable(rawURL string, conn api.Connection) error { 99 client, err := conn.HTTPClient() 100 if err != nil { 101 return errors.Annotate(err, "cannot retrieve HTTP client") 102 } 103 if err = clientGet(client, rawURL); err != nil { 104 return errors.Annotate(err, "Juju GUI is not available") 105 } 106 return nil 107 } 108 109 // openBrowser opens the Juju GUI at the given URL. 110 func (c *guiCommand) openBrowser(ctx *cmd.Context, rawURL string) error { 111 u, err := url.Parse(rawURL) 112 if err != nil { 113 return errors.Annotate(err, "cannot parse Juju GUI URL") 114 } 115 if c.noBrowser { 116 ctx.Infof(u.String()) 117 return nil 118 } 119 err = webbrowserOpen(u) 120 if err == nil { 121 ctx.Infof("Opening the Juju GUI in your browser.") 122 ctx.Infof("If it does not open, open this URL:\n%s", u) 123 return nil 124 } 125 if err == webbrowser.ErrNoBrowser { 126 ctx.Infof("Open this URL in your browser:\n%s", u) 127 return nil 128 } 129 return errors.Annotate(err, "cannot open web browser") 130 } 131 132 // showCredentials shows the admin username and password. 133 func (c *guiCommand) showCredentials(ctx *cmd.Context) error { 134 if !c.showCreds { 135 return nil 136 } 137 // TODO(wallyworld) - what to do if we are using a macaroon. 138 accountDetails, err := c.ClientStore().AccountDetails(c.ControllerName()) 139 if err != nil { 140 return errors.Annotate(err, "cannot retrieve credentials") 141 } 142 ctx.Infof("Username: %s\nPassword: %s", accountDetails.User, accountDetails.Password) 143 return nil 144 } 145 146 // clientGet is defined for testing purposes. 147 var clientGet = func(client *httprequest.Client, rawURL string) error { 148 return client.Get(rawURL, nil) 149 } 150 151 // webbrowserOpen is defined for testing purposes. 152 var webbrowserOpen = webbrowser.Open