Merge lp:~axwalk/juju-core/lp1247232-bootstrap-majorminorpatch into lp:~go-bot/juju-core/trunk

Proposed by Andrew Wilkins
Status: Merged
Approved by: Andrew Wilkins
Approved revision: no longer in the source branch.
Merged at revision: 2644
Proposed branch: lp:~axwalk/juju-core/lp1247232-bootstrap-majorminorpatch
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 148 lines (+97/-2)
3 files modified
environs/bootstrap/bootstrap.go (+38/-1)
environs/bootstrap/bootstrap_test.go (+59/-0)
tools/list.go (+0/-1)
To merge this branch: bzr merge lp:~axwalk/juju-core/lp1247232-bootstrap-majorminorpatch
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+216278@code.launchpad.net

Commit message

environs/bootstrap: bootstrap major.minor.patch

Bootstrap tools selection is changed so that it
will select tools with the same major, minor and
patch level as the current (CLI) tools if possible.
If there are no such tools, the most recent tools
with matching major/minor are chosen as before and
a warning will be logged.

This change allows us to change bootstrap behaviour
even within a minor release series (except of course
for existing releases).

The most recent tools with matching major/minor will
be set in agent-version, which causes the machine
agent to immediately upgrade.

Fixes lp:1247232

https://codereview.appspot.com/88840043/

Description of the change

environs/bootstrap: bootstrap major.minor.patch

Bootstrap tools selection is changed so that it
will select tools with the same major, minor and
patch level as the current (CLI) tools if possible.
If there are no such tools, the most recent tools
with matching major/minor are chosen as before and
a warning will be logged.

This change allows us to change bootstrap behaviour
even within a minor release series (except of course
for existing releases).

The most recent tools with matching major/minor will
be set in agent-version, which causes the machine
agent to immediately upgrade.

Fixes lp:1247232

https://codereview.appspot.com/88840043/

To post a comment you must log in.
Revision history for this message
Andrew Wilkins (axwalk) wrote :
Download full text (6.1 KiB)

Reviewers: mp+216278_code.launchpad.net,

Message:
Please take a look.

Description:
environs/bootstrap: bootstrap major.minor.patch

Bootstrap tools selection is changed so that it
will select tools with the same major, minor and
patch level as the current (CLI) tools if possible.
If there are no such tools, the most recent tools
with matching major/minor are chosen as before and
a warning will be logged.

This change allows us to change bootstrap behaviour
even within a minor release series (except of course
for existing releases).

The most recent tools with matching major/minor will
be set in agent-version, which causes the machine
agent to immediately upgrade.

Fixes lp:1247232

https://code.launchpad.net/~axwalk/juju-core/lp1247232-bootstrap-majorminorpatch/+merge/216278

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/88840043/

Affected files (+85, -2 lines):
   A [revision details]
   M environs/bootstrap/bootstrap.go
   M environs/bootstrap/bootstrap_test.go
   M tools/list.go

Index: [revision details]
=== 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-20140417053051-il9peyrj37nd277q
+New revision: <email address hidden>

Index: tools/list.go
=== modified file 'tools/list.go'
--- tools/list.go 2014-02-16 23:35:10 +0000
+++ tools/list.go 2014-04-17 09:19:41 +0000
@@ -130,7 +130,6 @@
    }
   }
   if len(result) == 0 {
- logger.Errorf("cannot match %#v", f)
    return nil, ErrNoMatches
   }
   return result, nil

Index: environs/bootstrap/bootstrap.go
=== modified file 'environs/bootstrap/bootstrap.go'
--- environs/bootstrap/bootstrap.go 2014-03-28 13:27:45 +0000
+++ environs/bootstrap/bootstrap.go 2014-04-17 09:19:41 +0000
@@ -56,7 +56,7 @@
   }
   var newVersion version.Number
   newVersion, toolsList := possibleTools.Newest()
- logger.Infof("picked newest version: %s", newVersion)
+ logger.Infof("newest version: %s", newVersion)
   cfg := environ.Config()
   if agentVersion, _ := cfg.AgentVersion(); agentVersion != newVersion {
    cfg, err := cfg.Apply(map[string]interface{}{
@@ -69,9 +69,39 @@
     return nil, fmt.Errorf("failed to update environment
configuration: %v", err)
    }
   }
+ // We should only ever bootstrap the exact same version as the client,
+ // or we risk bootstrap incompatibility. We still set agent-version to
+ // the newest version, so the agent will immediately upgrade itself.
+ //
+ // Build number is not important to match; uploaded tools will have
+ // incremented build number, and we want to match them.
+ bootstrapVersion := newVersion
+ if !sameVersionIgnoringBuild(newVersion, version.Current.Number) {
+ var sameTools coretools.List
+ for _, tools := range possibleTools {
+ if sameVersionIgnoringBuild(tools.Version.Number,
version.Current.Number) {
+ sameTools = append(sameTools, tools)
+ }
+ }
+ if len(sameTools) == 0 {
+ logger.Warningf(
+ "failed to find %s tools, will attempt to use %s",
+ version.Current.Number, newVersion,
+ )
+ } else {
+ bootstrapVersion...

Read more...

Revision history for this message
John A Meinel (jameinel) wrote :

I'd really like to see this tested live, though I'm not sure it will be
easy to set up the test (you'll have to populate a couple versions of
the tools, and then bootstrap with an old version of them).

We'll also certainly want to let CI know about it right away, since it
will change how they do some of their testing.

Mostly, though, LGTM.

https://codereview.appspot.com/88840043/diff/1/environs/bootstrap/bootstrap.go
File environs/bootstrap/bootstrap.go (right):

https://codereview.appspot.com/88840043/diff/1/environs/bootstrap/bootstrap.go#newcode72
environs/bootstrap/bootstrap.go:72: // We should only ever bootstrap the
exact same version as the client,
This whole chunk of code seems quite localized, is it possible to just
pull it into a helper function to keep the units of work focused?

https://codereview.appspot.com/88840043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :
Revision history for this message
Andrew Wilkins (axwalk) wrote :

On 2014/04/17 09:45:47, jameinel wrote:
> I'd really like to see this tested live, though I'm not sure it will
be easy to
> set up the test (you'll have to populate a couple versions of the
tools, and
> then bootstrap with an old version of them).

I did test it live by applying the patch to 1.17.6. It successfully
bootstrapped with 1.17.6, and then immediately upgraded to 1.17.7.

> We'll also certainly want to let CI know about it right away, since it
will
> change how they do some of their testing.

> Mostly, though, LGTM.

https://codereview.appspot.com/88840043/diff/1/environs/bootstrap/bootstrap.go
> File environs/bootstrap/bootstrap.go (right):

https://codereview.appspot.com/88840043/diff/1/environs/bootstrap/bootstrap.go#newcode72
> environs/bootstrap/bootstrap.go:72: // We should only ever bootstrap
the exact
> same version as the client,
> This whole chunk of code seems quite localized, is it possible to just
pull it
> into a helper function to keep the units of work focused?

I pulled out a little bit, but half of it is specific to the context.

https://codereview.appspot.com/88840043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'environs/bootstrap/bootstrap.go'
2--- environs/bootstrap/bootstrap.go 2014-03-28 13:27:45 +0000
3+++ environs/bootstrap/bootstrap.go 2014-04-17 10:10:59 +0000
4@@ -56,7 +56,7 @@
5 }
6 var newVersion version.Number
7 newVersion, toolsList := possibleTools.Newest()
8- logger.Infof("picked newest version: %s", newVersion)
9+ logger.Infof("newest version: %s", newVersion)
10 cfg := environ.Config()
11 if agentVersion, _ := cfg.AgentVersion(); agentVersion != newVersion {
12 cfg, err := cfg.Apply(map[string]interface{}{
13@@ -69,9 +69,46 @@
14 return nil, fmt.Errorf("failed to update environment configuration: %v", err)
15 }
16 }
17+ bootstrapVersion := newVersion
18+ // We should only ever bootstrap the exact same version as the client,
19+ // or we risk bootstrap incompatibility. We still set agent-version to
20+ // the newest version, so the agent will immediately upgrade itself.
21+ if !isCompatibleVersion(newVersion, version.Current.Number) {
22+ compatibleVersion, compatibleTools := findCompatibleTools(possibleTools, version.Current.Number)
23+ if len(compatibleTools) == 0 {
24+ logger.Warningf(
25+ "failed to find %s tools, will attempt to use %s",
26+ version.Current.Number, newVersion,
27+ )
28+ } else {
29+ bootstrapVersion, toolsList = compatibleVersion, compatibleTools
30+ }
31+ }
32+ logger.Infof("picked bootstrap tools version: %s", bootstrapVersion)
33 return toolsList, nil
34 }
35
36+// findCompatibleTools finds tools in the list that have the same major, minor
37+// and patch level as version.Current.
38+//
39+// Build number is not important to match; uploaded tools will have
40+// incremented build number, and we want to match them.
41+func findCompatibleTools(possibleTools coretools.List, version version.Number) (version.Number, coretools.List) {
42+ var compatibleTools coretools.List
43+ for _, tools := range possibleTools {
44+ if isCompatibleVersion(tools.Version.Number, version) {
45+ compatibleTools = append(compatibleTools, tools)
46+ }
47+ }
48+ return compatibleTools.Newest()
49+}
50+
51+func isCompatibleVersion(v1, v2 version.Number) bool {
52+ v1.Build = 0
53+ v2.Build = 0
54+ return v1.Compare(v2) == 0
55+}
56+
57 // EnsureNotBootstrapped returns nil if the environment is not
58 // bootstrapped, and an error if it is or if the function was not able
59 // to tell.
60
61=== modified file 'environs/bootstrap/bootstrap_test.go'
62--- environs/bootstrap/bootstrap_test.go 2014-04-09 16:36:12 +0000
63+++ environs/bootstrap/bootstrap_test.go 2014-04-17 10:10:59 +0000
64@@ -26,6 +26,7 @@
65 "launchpad.net/juju-core/provider/dummy"
66 coretesting "launchpad.net/juju-core/testing"
67 "launchpad.net/juju-core/testing/testbase"
68+ "launchpad.net/juju-core/tools"
69 "launchpad.net/juju-core/version"
70 )
71
72@@ -413,6 +414,64 @@
73 s.assertUploadTools(c, vers, true, extraCfg, "")
74 }
75
76+func (s *bootstrapSuite) TestSetBootstrapTools(c *gc.C) {
77+ availableVersions := []version.Binary{
78+ version.MustParseBinary("1.18.0-trusty-arm64"),
79+ version.MustParseBinary("1.18.1-trusty-arm64"),
80+ version.MustParseBinary("1.18.1.1-trusty-arm64"),
81+ version.MustParseBinary("1.18.1.2-trusty-arm64"),
82+ version.MustParseBinary("1.18.1.3-trusty-arm64"),
83+ }
84+ availableTools := make(tools.List, len(availableVersions))
85+ for i, v := range availableVersions {
86+ availableTools[i] = &tools.Tools{Version: v}
87+ }
88+
89+ type test struct {
90+ currentVersion version.Number
91+ expectedTools version.Number
92+ expectedAgentVersion version.Number
93+ }
94+ tests := []test{{
95+ currentVersion: version.MustParse("1.18.0"),
96+ expectedTools: version.MustParse("1.18.0"),
97+ expectedAgentVersion: version.MustParse("1.18.1.3"),
98+ }, {
99+ currentVersion: version.MustParse("1.18.1.4"),
100+ expectedTools: version.MustParse("1.18.1.3"),
101+ expectedAgentVersion: version.MustParse("1.18.1.3"),
102+ }, {
103+ // build number is ignored unless major/minor don't
104+ // match the latest.
105+ currentVersion: version.MustParse("1.18.1.2"),
106+ expectedTools: version.MustParse("1.18.1.3"),
107+ expectedAgentVersion: version.MustParse("1.18.1.3"),
108+ }, {
109+ // If the current patch level exceeds whatever's in
110+ // the tools source (e.g. when bootstrapping from trunk)
111+ // then the latest available tools will be chosen.
112+ currentVersion: version.MustParse("1.18.2"),
113+ expectedTools: version.MustParse("1.18.1.3"),
114+ expectedAgentVersion: version.MustParse("1.18.1.3"),
115+ }}
116+
117+ env := newEnviron("foo", useDefaultKeys, nil)
118+ for i, t := range tests {
119+ c.Logf("test %d: %+v", i, t)
120+ cfg, err := env.Config().Remove([]string{"agent-version"})
121+ c.Assert(err, gc.IsNil)
122+ err = env.SetConfig(cfg)
123+ c.Assert(err, gc.IsNil)
124+ s.PatchValue(&version.Current.Number, t.currentVersion)
125+ bootstrapTools, err := bootstrap.SetBootstrapTools(env, availableTools)
126+ c.Assert(err, gc.IsNil)
127+ c.Assert(bootstrapTools, gc.HasLen, 1)
128+ c.Assert(bootstrapTools[0].Version.Number, gc.Equals, t.expectedTools)
129+ agentVersion, _ := env.Config().AgentVersion()
130+ c.Assert(agentVersion, gc.Equals, t.expectedAgentVersion)
131+ }
132+}
133+
134 type bootstrapEnviron struct {
135 name string
136 cfg *config.Config
137
138=== modified file 'tools/list.go'
139--- tools/list.go 2014-02-16 23:35:10 +0000
140+++ tools/list.go 2014-04-17 10:10:59 +0000
141@@ -130,7 +130,6 @@
142 }
143 }
144 if len(result) == 0 {
145- logger.Errorf("cannot match %#v", f)
146 return nil, ErrNoMatches
147 }
148 return result, nil

Subscribers

People subscribed via source and target branches

to status/vote changes: