Skip to content

Commit e2b641a

Browse files
committed
Change introduction messages to react to --quiet.
1 parent d38c225 commit e2b641a

File tree

5 files changed

+131
-43
lines changed

5 files changed

+131
-43
lines changed

cmd/juju/cloud/updatepublicclouds.go

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,13 @@ var NewUpdatePublicCloudsCommand = func() cmd.Command {
6464

6565
func newUpdatePublicCloudsCommand() cmd.Command {
6666
store := jujuclient.NewFileClientStore()
67+
access := PublicCloudsAccess()
6768
c := &updatePublicCloudsCommand{
6869
OptionalControllerCommand: modelcmd.OptionalControllerCommand{
6970
Store: store,
7071
},
71-
publicSigningKey: keys.JujuPublicKey,
72-
publicCloudURL: "https://streams.canonical.com/juju/public-clouds.syaml",
72+
publicSigningKey: access.publicSigningKey,
73+
publicCloudURL: access.publicCloudURL,
7374
}
7475
c.addCloudAPIFunc = c.cloudAPI
7576
return modelcmd.WrapBase(c)
@@ -83,6 +84,17 @@ func (c *updatePublicCloudsCommand) Info() *cmd.Info {
8384
})
8485
}
8586

87+
type PublicCloudsAccessDetails struct {
88+
publicSigningKey string
89+
publicCloudURL string
90+
}
91+
92+
// PublicCloudsAccess contains information about
93+
// where to find published public clouds details.
94+
func PublicCloudsAccess() PublicCloudsAccessDetails {
95+
return PublicCloudsAccessDetails{keys.JujuPublicKey, "https://streams.canonical.com/juju/public-clouds.syaml"}
96+
}
97+
8698
// Init populates the command with the args from the command line.
8799
func (c *updatePublicCloudsCommand) Init(args []string) error {
88100
if err := c.OptionalControllerCommand.Init(args); err != nil {
@@ -125,16 +137,19 @@ func (c *updatePublicCloudsCommand) Run(ctxt *cmd.Context) error {
125137
return errors.Trace(err)
126138
}
127139
fmt.Fprint(ctxt.Stderr, "Fetching latest public cloud list...\n")
128-
publishedClouds, err := PublishedPublicClouds(c.publicCloudURL, c.publicSigningKey)
129-
if err != nil {
130-
return errors.Trace(err)
131-
}
132140
var returnedErr error
133-
if c.Client {
134-
if err := c.updateClientCopy(ctxt, publishedClouds); err != nil {
135-
ctxt.Infof("ERROR %v", err)
136-
returnedErr = cmd.ErrSilent
141+
publishedClouds, msg, err := FetchAndMaybeUpdatePublicClouds(
142+
PublicCloudsAccessDetails{c.publicSigningKey, c.publicCloudURL},
143+
c.Client)
144+
if err != nil {
145+
if len(publishedClouds) == 0 {
146+
return errors.Trace(err)
137147
}
148+
ctxt.Infof("ERROR %v", err)
149+
returnedErr = cmd.ErrSilent
150+
}
151+
if msg != "" {
152+
ctxt.Infof(msg)
138153
}
139154
if c.ControllerName != "" {
140155
if err := c.updateControllerCopy(ctxt, publishedClouds); err != nil {
@@ -145,26 +160,42 @@ func (c *updatePublicCloudsCommand) Run(ctxt *cmd.Context) error {
145160
return returnedErr
146161
}
147162

148-
func (c *updatePublicCloudsCommand) updateClientCopy(ctxt *cmd.Context, publishedClouds map[string]jujucloud.Cloud) error {
163+
// FetchAndMaybeUpdatePublicClouds gets published public clouds information
164+
// and updates client copy of public clouds if desired.
165+
// This call returns discovered public clouds and a user-facing message
166+
// whether they are different with what was known prior to the call.
167+
var FetchAndMaybeUpdatePublicClouds = func(access PublicCloudsAccessDetails, updateClient bool) (map[string]jujucloud.Cloud, string, error) {
168+
msg := ""
169+
publishedClouds, err := PublishedPublicClouds(access.publicCloudURL, access.publicSigningKey)
170+
if err != nil {
171+
return nil, msg, errors.Trace(err)
172+
}
173+
if updateClient {
174+
if msg, err = updateClientCopy(publishedClouds); err != nil {
175+
return publishedClouds, msg, err
176+
}
177+
}
178+
return publishedClouds, msg, nil
179+
}
180+
181+
func updateClientCopy(publishedClouds map[string]jujucloud.Cloud) (string, error) {
149182
currentPublicClouds, _, err := jujucloud.PublicCloudMetadata(jujucloud.JujuPublicCloudsPath())
150183
if err != nil {
151-
return errors.Annotate(err, "invalid local public cloud data")
184+
return "", errors.Annotate(err, "invalid local public cloud data")
152185
}
153186
sameCloudInfo, err := jujucloud.IsSameCloudMetadata(publishedClouds, currentPublicClouds)
154187
if err != nil {
155188
// Should never happen.
156-
return err
189+
return "", err
157190
}
158191
if sameCloudInfo {
159-
fmt.Fprintln(ctxt.Stderr, "List of public clouds on this client is up to date, see `juju clouds --client`.")
160-
return nil
192+
return "List of public clouds on this client is up to date, see `juju clouds --client`.\n", nil
161193
}
162194
if err := jujucloud.WritePublicCloudMetadata(publishedClouds); err != nil {
163-
return errors.Annotate(err, "error writing new local public cloud data")
195+
return "", errors.Annotate(err, "error writing new local public cloud data")
164196
}
165197
updateDetails := diffClouds(publishedClouds, currentPublicClouds)
166-
fmt.Fprintln(ctxt.Stderr, fmt.Sprintf("Updated list of public clouds on this client, %s", updateDetails))
167-
return nil
198+
return fmt.Sprintf("Updated list of public clouds on this client, %s\n", updateDetails), nil
168199
}
169200

170201
func (c *updatePublicCloudsCommand) updateControllerCopy(ctxt *cmd.Context, publishedClouds map[string]jujucloud.Cloud) error {

cmd/juju/commands/machine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var _ = gc.Suite(&MachineSuite{})
2525

2626
func (s *MachineSuite) RunCommand(c *gc.C, args ...string) (*cmd.Context, error) {
2727
context := cmdtesting.Context(c)
28-
juju := NewJujuCommand(context)
28+
juju := NewJujuCommand(context, "")
2929
if err := cmdtesting.InitCommand(juju, args); err != nil {
3030
return context, err
3131
}

cmd/juju/commands/main.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (m main) Run(args []string) int {
105105

106106
// note that this has to come before we init the juju home directory,
107107
// since it relies on detecting the lack of said directory.
108-
newInstall := m.maybeWarnJuju1x()
108+
newInstall, jujuMsg := m.maybeWarnJuju1x()
109109

110110
if err = juju.InitJujuXDGDataHome(); err != nil {
111111
cmd.WriteError(ctx.Stderr, err)
@@ -118,11 +118,13 @@ func (m main) Run(args []string) int {
118118
}
119119

120120
if newInstall {
121-
fmt.Fprintf(ctx.Stderr, "Since Juju %v is being run for the first time, downloading latest cloud information.\n", jujuversion.Current.Major)
122-
updateCmd := cloud.NewUpdatePublicCloudsCommand()
123-
if err := updateCmd.Run(ctx); err != nil {
121+
if _, _, err := cloud.FetchAndMaybeUpdatePublicClouds(cloud.PublicCloudsAccess(), true); err != nil {
124122
cmd.WriteError(ctx.Stderr, err)
125123
}
124+
if jujuMsg != "" {
125+
jujuMsg += "\n"
126+
}
127+
jujuMsg += fmt.Sprintf("Since Juju %v is being run for the first time, downloaded latest public cloud information.\n", jujuversion.Current.Major)
126128
}
127129

128130
for i := range x {
@@ -139,7 +141,7 @@ func (m main) Run(args []string) int {
139141
}
140142
}
141143

142-
jcmd := NewJujuCommand(ctx)
144+
jcmd := NewJujuCommand(ctx, jujuMsg)
143145
return cmd.Main(jcmd, ctx, args[1:])
144146
}
145147

@@ -155,15 +157,17 @@ func installProxy() error {
155157
return nil
156158
}
157159

158-
func (m main) maybeWarnJuju1x() (newInstall bool) {
160+
func (m main) maybeWarnJuju1x() (newInstall bool, jujuMsg string) {
161+
jujuMsg = ""
159162
newInstall = !juju2xConfigDataExists()
160163
if !shouldWarnJuju1x() {
161-
return newInstall
164+
return
162165
}
163166
ver, exists := m.juju1xVersion()
164167
if !exists {
165-
return newInstall
168+
return
166169
}
170+
167171
// TODO (anastasiamac 2016-10-21) Once manual page exists as per
168172
// https://github.com/juju/docs/issues/1487,
169173
// link it in the Note below to avoid propose here.
@@ -181,8 +185,8 @@ If you want to use Juju {{.OldJujuVersion}}, run 'juju' commands as '{{.OldJujuC
181185
"OldJujuVersion": ver,
182186
"OldJujuCommand": juju1xCmdName,
183187
})
184-
fmt.Fprintln(os.Stderr, buf.String())
185-
return newInstall
188+
jujuMsg = buf.String()
189+
return
186190
}
187191

188192
func (m main) juju1xVersion() (ver string, exists bool) {
@@ -217,7 +221,7 @@ func juju2xConfigDataExists() bool {
217221
}
218222

219223
// NewJujuCommand ...
220-
func NewJujuCommand(ctx *cmd.Context) cmd.Command {
224+
func NewJujuCommand(ctx *cmd.Context, jujuMsg string) cmd.Command {
221225
var jcmd *cmd.SuperCommand
222226
jcmd = jujucmd.NewSuperCommand(cmd.SuperCommandParams{
223227
Name: "juju",
@@ -233,6 +237,11 @@ func NewJujuCommand(ctx *cmd.Context) cmd.Command {
233237
}),
234238
UserAliasesFilename: osenv.JujuXDGDataHomePath("aliases"),
235239
FlagKnownAs: "option",
240+
NotifyRun: func(string) {
241+
if jujuMsg != "" {
242+
ctx.Infof(jujuMsg)
243+
}
244+
},
236245
})
237246
registerCommands(jcmd, ctx)
238247
return jcmd

cmd/juju/commands/main_test.go

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package commands
66
import (
77
"bytes"
88
"fmt"
9+
jujucloud "github.com/juju/juju/cloud"
910
"io/ioutil"
1011
"os"
1112
"path/filepath"
@@ -246,7 +247,7 @@ Welcome to Juju %s.
246247
If you want to use Juju 1.25.0, run 'juju' commands as 'juju-1'. For example, 'juju-1 bootstrap'.
247248
See https://jujucharms.com/docs/stable/juju-coexist for installation details.
248249
249-
Since Juju 2 is being run for the first time, downloading latest cloud information.`[1:]+"\n", jujuversion.Current))
250+
Since Juju 2 is being run for the first time, downloaded latest public cloud information.`[1:]+"\n", jujuversion.Current))
250251
checkVersionOutput(c, string(stdout))
251252
}
252253

@@ -285,7 +286,45 @@ func (s *MainSuite) TestFirstRun2xFrom1xNotUbuntu(c *gc.C) {
285286
assertNoArgs(c, argChan)
286287

287288
c.Check(string(stderr), gc.Equals, `
288-
Since Juju 2 is being run for the first time, downloading latest cloud information.`[1:]+"\n")
289+
Since Juju 2 is being run for the first time, downloaded latest public cloud information.`[1:]+"\n")
290+
checkVersionOutput(c, string(stdout))
291+
}
292+
293+
func (s *MainSuite) TestFirstRun2xFrom1xNotUbuntuQuiet(c *gc.C) {
294+
// Code should only run on ubuntu series, so pretend to be something else.
295+
s.PatchValue(&series.MustHostSeries, func() string { return "win8" })
296+
297+
argChan := make(chan []string, 1)
298+
299+
// we shouldn't actually be running anything, but if we do, this will
300+
// provide some consistent results.
301+
execCommand := s.GetExecCommand(gitjujutesting.PatchExecConfig{
302+
Stdout: "1.25.0-trusty-amd64",
303+
Args: argChan,
304+
})
305+
stub := &gitjujutesting.Stub{}
306+
s.PatchValue(&cloud.NewUpdatePublicCloudsCommand, func() cmd.Command {
307+
return &stubCommand{stub: stub}
308+
})
309+
310+
// remove the new juju-home and create a fake old juju home.
311+
err := os.RemoveAll(osenv.JujuXDGDataHomeDir())
312+
c.Assert(err, jc.ErrorIsNil)
313+
314+
makeValidOldHome(c)
315+
316+
var code int
317+
stdout, stderr := gitjujutesting.CaptureOutput(c, func() {
318+
code = main{
319+
execCommand: execCommand,
320+
}.Run([]string{"juju", "version", "--quiet"})
321+
})
322+
323+
c.Assert(code, gc.Equals, 0)
324+
325+
assertNoArgs(c, argChan)
326+
327+
c.Check(string(stderr), gc.Equals, "")
289328
checkVersionOutput(c, string(stdout))
290329
}
291330

@@ -358,41 +397,42 @@ func (s *MainSuite) TestNoWarnWithNo1xOr2xData(c *gc.C) {
358397

359398
assertNoArgs(c, argChan)
360399
c.Check(string(stderr), gc.Equals, `
361-
Since Juju 2 is being run for the first time, downloading latest cloud information.`[1:]+"\n")
400+
Since Juju 2 is being run for the first time, downloaded latest public cloud information.`[1:]+"\n")
362401
checkVersionOutput(c, string(stdout))
363402
}
364403

365-
func (s *MainSuite) assertRunCommandUpdateCloud(c *gc.C, expectedCall string) {
404+
func (s *MainSuite) assertRunUpdateCloud(c *gc.C, expectedCalled bool) {
366405
argChan := make(chan []string, 1)
367406
execCommand := s.GetExecCommand(gitjujutesting.PatchExecConfig{
368407
Stdout: "1.25.0-trusty-amd64",
369408
Args: argChan,
370409
})
371410

372-
stub := &gitjujutesting.Stub{}
373-
s.PatchValue(&cloud.NewUpdatePublicCloudsCommand, func() cmd.Command {
374-
return &stubCommand{stub: stub}
375-
376-
})
411+
called := false
412+
s.PatchValue(&cloud.FetchAndMaybeUpdatePublicClouds,
413+
func(access cloud.PublicCloudsAccessDetails, updateClient bool) (map[string]jujucloud.Cloud, string, error) {
414+
called = true
415+
return nil, "", nil
416+
})
377417
var code int
378418
gitjujutesting.CaptureOutput(c, func() {
379419
code = main{
380420
execCommand: execCommand,
381421
}.Run([]string{"juju", "version"})
382422
})
383423
c.Assert(code, gc.Equals, 0)
384-
c.Assert(stub.Calls()[0].FuncName, gc.Equals, expectedCall)
424+
c.Assert(called, gc.Equals, expectedCalled)
385425
}
386426

387427
func (s *MainSuite) TestFirstRunUpdateCloud(c *gc.C) {
388428
// remove the juju-home.
389429
err := os.RemoveAll(osenv.JujuXDGDataHomeDir())
390430
c.Assert(err, jc.ErrorIsNil)
391-
s.assertRunCommandUpdateCloud(c, "Run")
431+
s.assertRunUpdateCloud(c, true)
392432
}
393433

394434
func (s *MainSuite) TestRunNoUpdateCloud(c *gc.C) {
395-
s.assertRunCommandUpdateCloud(c, "Info")
435+
s.assertRunUpdateCloud(c, false)
396436
}
397437

398438
func makeValidOldHome(c *gc.C) {

cmd/supercommand.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,15 @@ func NewSuperCommand(p cmd.SuperCommandParams) *cmd.SuperCommand {
7474
// tests to assert that this string value is correct.
7575
p.Version = detail.Version
7676
p.VersionDetail = detail
77-
p.NotifyRun = runNotifier
77+
if p.NotifyRun != nil {
78+
messenger := p.NotifyRun
79+
p.NotifyRun = func(str string) {
80+
messenger(str)
81+
runNotifier(str)
82+
}
83+
} else {
84+
p.NotifyRun = runNotifier
85+
}
7886
p.FlagKnownAs = "option"
7987
return cmd.NewSuperCommand(p)
8088
}

0 commit comments

Comments
 (0)