~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/gui/gui.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.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
        accountDetails, err := c.ClientStore().AccountDetails(c.ControllerName())
 
138
        if err != nil {
 
139
                return errors.Annotate(err, "cannot retrieve credentials")
 
140
        }
 
141
        ctx.Infof("Username: %s\nPassword: %s", accountDetails.User, accountDetails.Password)
 
142
        return nil
 
143
}
 
144
 
 
145
// clientGet is defined for testing purposes.
 
146
var clientGet = func(client *httprequest.Client, rawURL string) error {
 
147
        return client.Get(rawURL, nil)
 
148
}
 
149
 
 
150
// webbrowserOpen is defined for testing purposes.
 
151
var webbrowserOpen = webbrowser.Open