Merge lp:~menno.smits/juju-core/1302005-bootstrap_series into lp:~go-bot/juju-core/trunk
- 1302005-bootstrap_series
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Menno Finlay-Smits |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2706 |
Proposed branch: | lp:~menno.smits/juju-core/1302005-bootstrap_series |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
193 lines (+104/-5) 2 files modified
cmd/juju/bootstrap.go (+47/-4) cmd/juju/bootstrap_test.go (+57/-1) |
To merge this branch: | bzr merge lp:~menno.smits/juju-core/1302005-bootstrap_series |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+218152@code.launchpad.net |
Commit message
cmd/juju: deprecate --series, added --upload-series
Emit a deprecation warning to stderr when --series is used
To make testing easier an interface is now used to allow the calls
made by BootstrapComman
https:/
R=thumper
Description of the change
cmd/juju: refactor --series to use StringsValue
seriesVar is now called seriesValue and is implemented using
StringsValue. This reuses StringValue while preserving the series
validation logic.
Menno Finlay-Smits (menno.smits) wrote : | # |
John A Meinel (jameinel) wrote : | # |
Is there a specific advantage to using StringValue ? It looks like just code reshuffling without actually adding much. I'm happy to have it if there is an actual improvement in common handling (say StringsValue provides better parsing, etc).
So LGTM, though I'd like to understand what this actually helps with.
William Reade (fwereade) wrote : | # |
LGTM
https:/
File cmd/juju/
https:/
cmd/juju/
Quibble quibble whine: I'd rather validate before setting on the
StringsValue.
John A Meinel (jameinel) wrote : | # |
Don't you have to do the set first so that it parses the values into a
slice? Otherwise you just have the raw string and you are reimplementing
all the parsing anyway.
On Tue, May 6, 2014 at 11:39 AM, William Reade
<email address hidden>wrote:
> LGTM
>
>
> https:/
> File cmd/juju/
>
>
> https:/
> cmd/juju/
> Quibble quibble whine: I'd rather validate before setting on the
> StringsValue.
>
> https:/
>
> --
>
> https:/
> You are subscribed to branch lp:juju-core.
>
William Reade (fwereade) wrote : | # |
Dammit, ofc. Nil out the value on error?
Menno Finlay-Smits (menno.smits) wrote : | # |
> Dammit, ofc. Nil out the value on error?
Done!
Menno Finlay-Smits (menno.smits) wrote : | # |
Please take a look.
Menno Finlay-Smits (menno.smits) wrote : | # |
Please take a look.
Tim Penhey (thumper) wrote : | # |
On 2014/05/08 01:35:18, menn0 wrote:
> Please take a look.
Firstly, please don't reuse branches. It confuses things somewhat.
For new pieces of work, even related pieces, use a different branch.
Tim Penhey (thumper) wrote : | # |
LGTM with a few minor comments.
https:/
File cmd/juju/
https:/
cmd/juju/
"series", "upload tools for supplied comma-separated series list
(DEPRECATED, see --upload-series)")
Wondering if we should move the deprecated bit to the front of the help
string. Thoughts?
https:/
cmd/juju/
a small part of me recoils at this prefix, but I can't really think of a
better one that makes more sense, so ok with it.
https:/
File cmd/juju/
https:/
cmd/juju/
[]string{
A better call would be the testing.RunCommand:
RunCommand(c *gc.C, com cmd.Command, args []string) (*cmd.Context,
error)
ctx, err := testing.
[]string{
c.Assert(err, gc.IsNil)
Menno Finlay-Smits (menno.smits) wrote : | # |
https:/
File cmd/juju/
https:/
cmd/juju/
"series", "upload tools for supplied comma-separated series list
(DEPRECATED, see --upload-series)")
On 2014/05/08 01:53:05, thumper wrote:
> Wondering if we should move the deprecated bit to the front of the
help string.
> Thoughts?
I have no strong opinion on this. I was just following what was already
done for the -u flag on the juju deploy command.
https:/
cmd/juju/
On 2014/05/08 01:53:05, thumper wrote:
> a small part of me recoils at this prefix, but I can't really think of
a better
> one that makes more sense, so ok with it.
I didn't like this much either. Alternatives I also considered where:
* bootstrap (shadowing the module): potentially confusing for the casual
reader.
* bootstrapApi: but it's not really an official API of any sort
* bootstrapFuncs or similar: collides with the struct but could change
the struct name.
Do any of these appeal more than _bootstrap?
https:/
File cmd/juju/
https:/
cmd/juju/
[]string{
On 2014/05/08 01:53:05, thumper wrote:
> A better call would be the testing.RunCommand:
> RunCommand(c *gc.C, com cmd.Command, args []string) (*cmd.Context,
error)
> ctx, err := testing.
> []string{
> c.Assert(err, gc.IsNil)
I got cmd.Main pattern this from the other tests in the file. RunCommand
is much more sensible. I'll change the test.
Should I do the others in this file as well? (as a separate change)
Tim Penhey (thumper) wrote : | # |
https:/
File cmd/juju/
https:/
cmd/juju/
"series", "upload tools for supplied comma-separated series list
(DEPRECATED, see --upload-series)")
On 2014/05/08 02:35:48, menn0 wrote:
> On 2014/05/08 01:53:05, thumper wrote:
> > Wondering if we should move the deprecated bit to the front of the
help
> string.
> > Thoughts?
> I have no strong opinion on this. I was just following what was
already done for
> the -u flag on the juju deploy command.
I think it'll be OK... since we are emitting a deprecation warning
anyway.
If it was the ONLY deprecation warning there was then I'd say this would
be different.
https:/
cmd/juju/
On 2014/05/08 02:35:48, menn0 wrote:
> On 2014/05/08 01:53:05, thumper wrote:
> > a small part of me recoils at this prefix, but I can't really think
of a
> better
> > one that makes more sense, so ok with it.
> I didn't like this much either. Alternatives I also considered where:
> * bootstrap (shadowing the module): potentially confusing for the
casual reader.
> * bootstrapApi: but it's not really an official API of any sort
> * bootstrapFuncs or similar: collides with the struct but could change
the
> struct name.
> Do any of these appeal more than _bootstrap?
Shadowing the outer struct shouldn't be a big issue. I think of those
options, I'd prefer
bootstrapFuncs
I know others would prefer "bf" or similar, but not me.
https:/
File cmd/juju/
https:/
cmd/juju/
[]string{
On 2014/05/08 02:35:48, menn0 wrote:
> On 2014/05/08 01:53:05, thumper wrote:
> > A better call would be the testing.RunCommand:
> >
> > RunCommand(c *gc.C, com cmd.Command, args []string) (*cmd.Context,
error)
> >
> > ctx, err := testing.
> > []string{
> > c.Assert(err, gc.IsNil)
> I got cmd.Main pattern this from the other tests in the file.
RunCommand is much
> more sensible. I'll change the test.
> Should I do the others in this file as well? (as a separate change)
Sure, that would be good.
Menno Finlay-Smits (menno.smits) wrote : | # |
https:/
File cmd/juju/
https:/
cmd/juju/
On 2014/05/08 04:53:52, thumper wrote:
> On 2014/05/08 02:35:48, menn0 wrote:
> > On 2014/05/08 01:53:05, thumper wrote:
> > > a small part of me recoils at this prefix, but I can't really
think of a
> > better
> > > one that makes more sense, so ok with it.
> >
> > I didn't like this much either. Alternatives I also considered
where:
> >
> > * bootstrap (shadowing the module): potentially confusing for the
casual
> reader.
> > * bootstrapApi: but it's not really an official API of any sort
> > * bootstrapFuncs or similar: collides with the struct but could
change the
> > struct name.
> >
> > Do any of these appeal more than _bootstrap?
> Shadowing the outer struct shouldn't be a big issue. I think of those
options,
> I'd prefer
> bootstrapFuncs
> I know others would prefer "bf" or similar, but not me.
The only (minor) I have with bootstrapFuncs is that it's a type in the
outer scope and an instance of the type inside. Changing it anyway...
Preview Diff
1 | === modified file 'cmd/juju/bootstrap.go' |
2 | --- cmd/juju/bootstrap.go 2014-05-06 20:39:36 +0000 |
3 | +++ cmd/juju/bootstrap.go 2014-05-08 05:19:19 +0000 |
4 | @@ -64,6 +64,7 @@ |
5 | Constraints constraints.Value |
6 | UploadTools bool |
7 | Series []string |
8 | + seriesOld []string |
9 | MetadataSource string |
10 | Placement string |
11 | } |
12 | @@ -80,7 +81,8 @@ |
13 | c.EnvCommandBase.SetFlags(f) |
14 | f.Var(constraints.ConstraintsValue{Target: &c.Constraints}, "constraints", "set environment constraints") |
15 | f.BoolVar(&c.UploadTools, "upload-tools", false, "upload local version of tools before bootstrapping") |
16 | - f.Var(newSeriesValue(nil, &c.Series), "series", "upload tools for supplied comma-separated series list") |
17 | + f.Var(newSeriesValue(nil, &c.Series), "upload-series", "upload tools for supplied comma-separated series list") |
18 | + f.Var(newSeriesValue(nil, &c.seriesOld), "series", "upload tools for supplied comma-separated series list (DEPRECATED, see --upload-series)") |
19 | f.StringVar(&c.MetadataSource, "metadata-source", "", "local path to use as tools and/or metadata source") |
20 | f.StringVar(&c.Placement, "to", "", "a placement directive indicating an instance to bootstrap") |
21 | } |
22 | @@ -91,8 +93,18 @@ |
23 | return |
24 | } |
25 | if len(c.Series) > 0 && !c.UploadTools { |
26 | + return fmt.Errorf("--upload-series requires --upload-tools") |
27 | + } |
28 | + if len(c.seriesOld) > 0 && !c.UploadTools { |
29 | return fmt.Errorf("--series requires --upload-tools") |
30 | } |
31 | + if len(c.Series) > 0 && len(c.seriesOld) > 0 { |
32 | + return fmt.Errorf("--upload-series and --series can't be used together") |
33 | + } |
34 | + if len(c.seriesOld) > 0 { |
35 | + c.Series = c.seriesOld |
36 | + } |
37 | + |
38 | // Parse the placement directive. Bootstrap currently only |
39 | // supports provider-specific placement directives. |
40 | if c.Placement != "" { |
41 | @@ -130,10 +142,41 @@ |
42 | return nil |
43 | } |
44 | |
45 | +// bootstrap functionality that Run calls to support cleaner testing |
46 | +type BootstrapInterface interface { |
47 | + EnsureNotBootstrapped(env environs.Environ) error |
48 | + UploadTools(environs.BootstrapContext, environs.Environ, *string, bool, ...string) error |
49 | + Bootstrap(ctx environs.BootstrapContext, environ environs.Environ, args environs.BootstrapParams) error |
50 | +} |
51 | + |
52 | +type bootstrapFuncs struct{} |
53 | + |
54 | +func (b bootstrapFuncs) EnsureNotBootstrapped(env environs.Environ) error { |
55 | + return bootstrap.EnsureNotBootstrapped(env) |
56 | +} |
57 | + |
58 | +func (b bootstrapFuncs) UploadTools(ctx environs.BootstrapContext, env environs.Environ, toolsArch *string, forceVersion bool, bootstrapSeries ...string) error { |
59 | + return bootstrap.UploadTools(ctx, env, toolsArch, forceVersion, bootstrapSeries...) |
60 | +} |
61 | + |
62 | +func (b bootstrapFuncs) Bootstrap(ctx environs.BootstrapContext, env environs.Environ, args environs.BootstrapParams) error { |
63 | + return bootstrap.Bootstrap(ctx, env, args) |
64 | +} |
65 | + |
66 | +var getBootstrapFuncs = func() BootstrapInterface { |
67 | + return &bootstrapFuncs{} |
68 | +} |
69 | + |
70 | // Run connects to the environment specified on the command line and bootstraps |
71 | // a juju in that environment if none already exists. If there is as yet no environments.yaml file, |
72 | // the user is informed how to create one. |
73 | func (c *BootstrapCommand) Run(ctx *cmd.Context) (resultErr error) { |
74 | + bootstrapFuncs := getBootstrapFuncs() |
75 | + |
76 | + if len(c.seriesOld) > 0 { |
77 | + fmt.Fprintln(ctx.Stderr, "Use of --series is deprecated. Please use --upload-series instead.") |
78 | + } |
79 | + |
80 | environ, cleanup, err := environFromName(ctx, c.EnvName, &resultErr, "Bootstrap") |
81 | if err != nil { |
82 | return err |
83 | @@ -150,7 +193,7 @@ |
84 | } |
85 | |
86 | defer cleanup() |
87 | - if err := bootstrap.EnsureNotBootstrapped(environ); err != nil { |
88 | + if err := bootstrapFuncs.EnsureNotBootstrapped(environ); err != nil { |
89 | return err |
90 | } |
91 | |
92 | @@ -188,12 +231,12 @@ |
93 | c.UploadTools = true |
94 | } |
95 | if c.UploadTools { |
96 | - err = bootstrap.UploadTools(ctx, environ, c.Constraints.Arch, true, c.Series...) |
97 | + err = bootstrapFuncs.UploadTools(ctx, environ, c.Constraints.Arch, true, c.Series...) |
98 | if err != nil { |
99 | return err |
100 | } |
101 | } |
102 | - return bootstrap.Bootstrap(ctx, environ, environs.BootstrapParams{ |
103 | + return bootstrapFuncs.Bootstrap(ctx, environ, environs.BootstrapParams{ |
104 | Constraints: c.Constraints, |
105 | Placement: c.Placement, |
106 | }) |
107 | |
108 | === modified file 'cmd/juju/bootstrap_test.go' |
109 | --- cmd/juju/bootstrap_test.go 2014-04-30 22:05:31 +0000 |
110 | +++ cmd/juju/bootstrap_test.go 2014-05-08 05:19:19 +0000 |
111 | @@ -305,6 +305,14 @@ |
112 | args: []string{"--series", "fine"}, |
113 | err: `--series requires --upload-tools`, |
114 | }, { |
115 | + info: "lonely --upload-series", |
116 | + args: []string{"--upload-series", "fine"}, |
117 | + err: `--upload-series requires --upload-tools`, |
118 | +}, { |
119 | + info: "--upload-series with --series", |
120 | + args: []string{"--upload-tools", "--upload-series", "foo", "--series", "bar"}, |
121 | + err: `--upload-series and --series can't be used together`, |
122 | +}, { |
123 | info: "bad environment", |
124 | version: "1.2.3-%LTS%-amd64", |
125 | args: []string{"-e", "brokenenv"}, |
126 | @@ -351,7 +359,7 @@ |
127 | }, { |
128 | info: "--upload-tools rejects invalid series", |
129 | version: "1.2.3-saucy-amd64", |
130 | - args: []string{"--upload-tools", "--series", "ping,ping,pong"}, |
131 | + args: []string{"--upload-tools", "--upload-series", "ping,ping,pong"}, |
132 | err: `invalid series "ping"`, |
133 | }, { |
134 | info: "--upload-tools rejects mismatched arch", |
135 | @@ -407,6 +415,33 @@ |
136 | c.Check(coretesting.Stdout(ctx2), gc.Equals, "") |
137 | } |
138 | |
139 | +func (s *BootstrapSuite) TestSeriesDeprecation(c *gc.C) { |
140 | + ctx := s.checkSeriesArg(c, "--series") |
141 | + c.Check(coretesting.Stderr(ctx), gc.Equals, |
142 | + "Use of --series is deprecated. Please use --upload-series instead.\n") |
143 | +} |
144 | + |
145 | +func (s *BootstrapSuite) TestNoDeprecationWithUploadSeries(c *gc.C) { |
146 | + ctx := s.checkSeriesArg(c, "--upload-series") |
147 | + c.Check(coretesting.Stderr(ctx), gc.Equals, "") |
148 | +} |
149 | + |
150 | +func (s *BootstrapSuite) checkSeriesArg(c *gc.C, argVariant string) *cmd.Context { |
151 | + _bootstrap := &fakeBootstrapFuncs{} |
152 | + s.PatchValue(&getBootstrapFuncs, func() BootstrapInterface { |
153 | + return _bootstrap |
154 | + }) |
155 | + _, fake := makeEmptyFakeHome(c) |
156 | + defer fake.Restore() |
157 | + |
158 | + ctx, err := coretesting.RunCommand(c, &BootstrapCommand{}, |
159 | + []string{"--upload-tools", argVariant, "foo,bar"}) |
160 | + |
161 | + c.Assert(err, gc.IsNil) |
162 | + c.Check(_bootstrap.uploadToolsSeries, gc.DeepEquals, []string{"foo", "bar"}) |
163 | + return ctx |
164 | +} |
165 | + |
166 | func (s *BootstrapSuite) TestBootstrapJenvWarning(c *gc.C) { |
167 | env, fake := makeEmptyFakeHome(c) |
168 | defer fake.Restore() |
169 | @@ -704,3 +739,24 @@ |
170 | } |
171 | return all |
172 | } |
173 | + |
174 | +// TODO(menn0): This fake BootstrapInterface implementation is |
175 | +// currently quite minimal but could be easily extended to cover more |
176 | +// test scenarios. This could help improve some of the tests in this |
177 | +// file which execute large amounts of external functionality. |
178 | +type fakeBootstrapFuncs struct { |
179 | + uploadToolsSeries []string |
180 | +} |
181 | + |
182 | +func (fake *fakeBootstrapFuncs) EnsureNotBootstrapped(env environs.Environ) error { |
183 | + return nil |
184 | +} |
185 | + |
186 | +func (fake *fakeBootstrapFuncs) UploadTools(ctx environs.BootstrapContext, env environs.Environ, toolsArch *string, forceVersion bool, bootstrapSeries ...string) error { |
187 | + fake.uploadToolsSeries = bootstrapSeries |
188 | + return nil |
189 | +} |
190 | + |
191 | +func (fake fakeBootstrapFuncs) Bootstrap(ctx environs.BootstrapContext, env environs.Environ, args environs.BootstrapParams) error { |
192 | + return nil |
193 | +} |
Reviewers: mp+218152_ code.launchpad. net,
Message:
Please take a look.
Description:
cmd/juju: refactor --series to use StringsValue
seriesVar is now called seriesValue and is implemented using
StringsValue. This reuses StringValue while preserving the series
validation logic.
https:/ /code.launchpad .net/~menno. smits/juju- core/1302005- bootstrap_ series/ +merge/ 218152
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/94060044/
Affected files (+28, -22 lines): bootstrap. go upgradejuju. go
A [revision details]
M cmd/juju/
M cmd/juju/
Index: [revision details] 20140501192736- 36p3425ohtpy4np 7
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-
+New revision: <email address hidden>
Index: cmd/juju/ bootstrap. go bootstrap. go' bootstrap. go 2014-04-30 22:05:31 +0000 bootstrap. go 2014-05-02 19:25:05 +0000
=== modified file 'cmd/juju/
--- cmd/juju/
+++ cmd/juju/
@@ -6,7 +6,6 @@
import (
"fmt"
"os"
- "strings"
"launchpad. net/gnuflag"
@@ -81,7 +80,7 @@ Base.SetFlags( f) constraints. ConstraintsValu e{Target: &c.UploadTools, "upload-tools", false, "upload local version of {&c.Series} , "series", "upload tools for supplied Value(nil, &c.Series), "series", "upload tools for &c.MetadataSour ce, "metadata-source", "", "local path to use &c.Placement, "to", "", "a placement directive indicating an args)
c.EnvCommand
f.Var(
&c.Constraints}, "constraints", "set environment constraints")
f.BoolVar(
tools before bootstrapping")
- f.Var(seriesVar
comma-separated series list")
+ f.Var(newSeries
supplied comma-separated series list")
f.StringVar(
as tools and/or metadata source")
f.StringVar(
instance to bootstrap")
}
@@ -106,6 +105,30 @@
return cmd.CheckEmpty(
}
+type seriesValue struct { defaultValue []string, target *[]string) *seriesValue { (*cmd.StringsVa lue)(target) } Set(s); err != nil { IsValidSeries( name) { Split(value, ",") IsValidSeries( name) {
+ *cmd.StringsValue
+}
+
+// newSeriesValue is used to create the type passed into the
gnuflag.FlagSet Var function.
+func newSeriesValue(
+ v := seriesValue{
+ *(v.StringsValue) = defaultValue
+ return &v
+}
+
+// Implements gnuflag.Value Set.
+func (v *seriesValue) Set(s string) error {
+ if err := v.StringsValue.
+ return err
+ }
+ for _, name := range *(v.StringsValue) {
+ if !charm.
+ return fmt.Errorf("invalid series name %q", name)
+ }
+ }
+ return nil
+}
+
// Run connects to the environment specified on the command line and
bootstraps
// a juju in that environment if none already exists. If there is as yet
no environments.yaml file,
// the user is informed how to create one.
@@ -174,22 +197,3 @@
Placement: c.Placement,
})
}
-
-type seriesVar struct {
- target *[]string
-}
-
-func (v seriesVar) Set(value string) error {
- names := strings.
- for _, name := range names {
- if !charm.
- return fmt.Errorf("invalid series name %q", name)
- }
- }
- *v.target = names
- return nil
-}
-
-func (v seriesVar) String() string {
- return strings.Join(*v....