1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
11
"github.com/juju/errors"
12
"github.com/juju/httprequest"
13
"github.com/juju/webbrowser"
14
"launchpad.net/gnuflag"
16
"github.com/juju/juju/api"
17
"github.com/juju/juju/cmd/modelcmd"
20
// NewGUICommand creates and returns a new gui command.
21
func NewGUICommand() cmd.Command {
22
return modelcmd.Wrap(&guiCommand{})
25
// guiCommand opens the Juju GUI in the default browser.
26
type guiCommand struct {
27
modelcmd.ModelCommandBase
34
Open the Juju GUI in the default browser:
38
Open the GUI and show admin credentials to use to log into it:
40
juju gui --show-credentials
42
Do not open the browser, just output the GUI URL:
46
An error is returned if the Juju GUI is not available in the controller.
49
// Info implements the cmd.Command interface.
50
func (c *guiCommand) Info() *cmd.Info {
53
Purpose: "Open the Juju GUI in the default browser.",
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")
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()
69
return errors.Annotate(err, "cannot establish API connection")
72
details, err := c.ClientStore().ModelByName(c.ControllerName(), c.ModelName())
74
return errors.Annotate(err, "cannot retrieve model details")
76
rawURL := fmt.Sprintf("https://%s/gui/%s/", conn.Addr(), details.ModelUUID)
78
// Check that the Juju GUI is available.
79
if err = c.checkAvailable(rawURL, conn); err != nil {
80
return errors.Trace(err)
83
// Open the Juju GUI in the browser.
84
if err = c.openBrowser(ctx, rawURL); err != nil {
85
return errors.Trace(err)
88
// Print login credentials if requested.
89
if err = c.showCredentials(ctx); err != nil {
90
return errors.Trace(err)
95
// checkAvailable ensures the Juju GUI is available on the controller at the
97
func (c *guiCommand) checkAvailable(rawURL string, conn api.Connection) error {
98
client, err := conn.HTTPClient()
100
return errors.Annotate(err, "cannot retrieve HTTP client")
102
if err = clientGet(client, rawURL); err != nil {
103
return errors.Annotate(err, "Juju GUI is not available")
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)
112
return errors.Annotate(err, "cannot parse Juju GUI URL")
115
ctx.Infof(u.String())
118
err = webbrowserOpen(u)
120
ctx.Infof("Opening the Juju GUI in your browser.")
121
ctx.Infof("If it does not open, open this URL:\n%s", u)
124
if err == webbrowser.ErrNoBrowser {
125
ctx.Infof("Open this URL in your browser:\n%s", u)
128
return errors.Annotate(err, "cannot open web browser")
131
// showCredentials shows the admin username and password.
132
func (c *guiCommand) showCredentials(ctx *cmd.Context) error {
136
// TODO(wallyworld) - what to do if we are using a macaroon.
137
accountDetails, err := c.ClientStore().AccountDetails(c.ControllerName())
139
return errors.Annotate(err, "cannot retrieve credentials")
141
ctx.Infof("Username: %s\nPassword: %s", accountDetails.User, accountDetails.Password)
145
// clientGet is defined for testing purposes.
146
var clientGet = func(client *httprequest.Client, rawURL string) error {
147
return client.Get(rawURL, nil)
150
// webbrowserOpen is defined for testing purposes.
151
var webbrowserOpen = webbrowser.Open