Merge lp:~jameinel/juju-core/1.18-dowgrade-patch-level into lp:juju-core/1.18

Proposed by John A Meinel
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 2267
Proposed branch: lp:~jameinel/juju-core/1.18-dowgrade-patch-level
Merge into: lp:juju-core/1.18
Diff against target: 183 lines (+95/-30)
3 files modified
worker/upgrader/export_test.go (+4/-1)
worker/upgrader/upgrader.go (+40/-28)
worker/upgrader/upgrader_test.go (+51/-1)
To merge this branch: bzr merge lp:~jameinel/juju-core/1.18-dowgrade-patch-level
Reviewer Review Type Date Requested Status
Ian Booth Approve
Review via email: mp+215282@code.launchpad.net

Commit message

This backs off a little bit on the "refuse to downgrade" to "refuse to downgrade across MAJOR or MINOR versions".

This allows the CI infrastructure to continue to test 'upgrades' when Juju will default to bootstrapping a version that is newer than the target of the test. (they *want* to bootstrap 1.18.0 and then upgrade it to 1.18.1, but bootstrap will go immediately to 1.18.1, so they have to bootstrap, downgrade, and then upgrade again. Not an ideal situation.)

If it was just CI, then I might push harder to fix it elsewhere, but I can see users getting a bugfix patch that actually breaks something and needing a way out.

We still refuse to go across MAJOR or MINOR versions, because we almost definitely are going to be changing things like agent.conf there and when they get to the target version, it will just be broken.

Description of the change

This backs off a little bit on the "refuse to downgrade" to "refuse to downgrade across MAJOR or MINOR versions".

This allows the CI infrastructure to continue to test 'upgrades' when Juju will default to bootstrapping a version that is newer than the target of the test. (they *want* to bootstrap 1.18.0 and then upgrade it to 1.18.1, but bootstrap will go immediately to 1.18.1, so they have to bootstrap, downgrade, and then upgrade again. Not an ideal situation.)

If it was just CI, then I might push harder to fix it elsewhere, but I can see users getting a bugfix patch that actually breaks something and needing a way out.

We still refuse to go across MAJOR or MINOR versions, because we almost definitely are going to be changing things like agent.conf there and when they get to the target version, it will just be broken.

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'worker/upgrader/export_test.go'
2--- worker/upgrader/export_test.go 2014-03-21 03:27:16 +0000
3+++ worker/upgrader/export_test.go 2014-04-10 18:59:35 +0000
4@@ -8,7 +8,10 @@
5 "launchpad.net/juju-core/utils"
6 )
7
8-var RetryAfter = &retryAfter
9+var (
10+ RetryAfter = &retryAfter
11+ AllowedTargetVersion = allowedTargetVersion
12+)
13
14 func EnsureTools(u *Upgrader, agentTools *tools.Tools, hostnameVerification utils.SSLHostnameVerification) error {
15 return u.ensureTools(agentTools, hostnameVerification)
16
17=== modified file 'worker/upgrader/upgrader.go'
18--- worker/upgrader/upgrader.go 2014-04-09 04:50:46 +0000
19+++ worker/upgrader/upgrader.go 2014-04-10 18:59:35 +0000
20@@ -73,6 +73,18 @@
21 return u.Wait()
22 }
23
24+// allowedTargetVersion checks if targetVersion is too different from
25+// curVersion to allow a downgrade.
26+func allowedTargetVersion(curVersion, targetVersion version.Number) bool {
27+ if targetVersion.Major < curVersion.Major {
28+ return false
29+ }
30+ if targetVersion.Major == curVersion.Major && targetVersion.Minor < curVersion.Minor {
31+ return false
32+ }
33+ return true
34+}
35+
36 func (u *Upgrader) loop() error {
37 currentTools := &coretools.Tools{Version: version.Current}
38 err := u.st.SetVersion(u.tag, currentTools.Version)
39@@ -112,7 +124,9 @@
40 case <-dying:
41 return nil
42 }
43- if wantVersion.Compare(version.Current.Number) < 0 {
44+ if wantVersion == currentTools.Version.Number {
45+ continue
46+ } else if !allowedTargetVersion(version.Current.Number, wantVersion) {
47 // See also bug #1299802 where when upgrading from
48 // 1.16 to 1.18 there is a race condition that can
49 // cause the unit agent to upgrade, and then want to
50@@ -122,33 +136,31 @@
51 wantVersion, version.Current)
52 continue
53 }
54- if wantVersion != currentTools.Version.Number {
55- logger.Infof("upgrade requested from %v to %v", currentTools.Version, wantVersion)
56- // TODO(dimitern) 2013-10-03 bug #1234715
57- // Add a testing HTTPS storage to verify the
58- // disableSSLHostnameVerification behavior here.
59- wantTools, hostnameVerification, err = u.st.Tools(u.tag)
60- if err != nil {
61- // Not being able to lookup Tools is considered fatal
62- return err
63- }
64- // The worker cannot be stopped while we're downloading
65- // the tools - this means that even if the API is going down
66- // repeatedly (causing the agent to be stopped), as long
67- // as we have got as far as this, we will still be able to
68- // upgrade the agent.
69- err := u.ensureTools(wantTools, hostnameVerification)
70- if err == nil {
71- return &UpgradeReadyError{
72- OldTools: version.Current,
73- NewTools: wantTools.Version,
74- AgentName: u.tag,
75- DataDir: u.dataDir,
76- }
77- }
78- logger.Errorf("failed to fetch tools from %q: %v", wantTools.URL, err)
79- retry = retryAfter()
80- }
81+ logger.Infof("upgrade requested from %v to %v", currentTools.Version, wantVersion)
82+ // TODO(dimitern) 2013-10-03 bug #1234715
83+ // Add a testing HTTPS storage to verify the
84+ // disableSSLHostnameVerification behavior here.
85+ wantTools, hostnameVerification, err = u.st.Tools(u.tag)
86+ if err != nil {
87+ // Not being able to lookup Tools is considered fatal
88+ return err
89+ }
90+ // The worker cannot be stopped while we're downloading
91+ // the tools - this means that even if the API is going down
92+ // repeatedly (causing the agent to be stopped), as long
93+ // as we have got as far as this, we will still be able to
94+ // upgrade the agent.
95+ err := u.ensureTools(wantTools, hostnameVerification)
96+ if err == nil {
97+ return &UpgradeReadyError{
98+ OldTools: version.Current,
99+ NewTools: wantTools.Version,
100+ AgentName: u.tag,
101+ DataDir: u.dataDir,
102+ }
103+ }
104+ logger.Errorf("failed to fetch tools from %q: %v", wantTools.URL, err)
105+ retry = retryAfter()
106 }
107 }
108
109
110=== modified file 'worker/upgrader/upgrader_test.go'
111--- worker/upgrader/upgrader_test.go 2014-04-09 04:50:46 +0000
112+++ worker/upgrader/upgrader_test.go 2014-04-10 18:59:35 +0000
113@@ -42,7 +42,10 @@
114 oldRetryAfter func() <-chan time.Time
115 }
116
117+type AllowedTargetVersionSuite struct{}
118+
119 var _ = gc.Suite(&UpgraderSuite{})
120+var _ = gc.Suite(&AllowedTargetVersionSuite{})
121
122 func (s *UpgraderSuite) SetUpTest(c *gc.C) {
123 s.JujuConnSuite.SetUpTest(c)
124@@ -232,7 +235,7 @@
125 c.Assert(err, gc.IsNil)
126 }
127
128-func (s *UpgraderSuite) TestUpgraderRefusesToDowngrade(c *gc.C) {
129+func (s *UpgraderSuite) TestUpgraderRefusesToDowngradeMinorVersions(c *gc.C) {
130 stor := s.Conn.Environ.Storage()
131 origTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
132 s.PatchValue(&version.Current, origTools.Version)
133@@ -252,3 +255,50 @@
134 // c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
135 c.Check(err, gc.ErrorMatches, "cannot read tools metadata in tools directory.*no such file or directory")
136 }
137+
138+func (s *UpgraderSuite) TestUpgraderAllowsDowngradingPatchVersions(c *gc.C) {
139+ stor := s.Conn.Environ.Storage()
140+ origTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
141+ s.PatchValue(&version.Current, origTools.Version)
142+ downgradeTools := envtesting.AssertUploadFakeToolsVersions(
143+ c, stor, version.MustParseBinary("5.4.2-precise-amd64"))[0]
144+ err := statetesting.SetAgentVersion(s.State, downgradeTools.Version.Number)
145+ c.Assert(err, gc.IsNil)
146+
147+ dummy.SetStorageDelay(coretesting.ShortWait)
148+
149+ u := s.makeUpgrader()
150+ err = u.Stop()
151+ envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
152+ AgentName: s.machine.Tag(),
153+ OldTools: origTools.Version,
154+ NewTools: downgradeTools.Version,
155+ DataDir: s.DataDir(),
156+ })
157+ foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version)
158+ c.Assert(err, gc.IsNil)
159+ envtesting.CheckTools(c, foundTools, downgradeTools)
160+}
161+
162+type allowedTest struct {
163+ current string
164+ target string
165+ allowed bool
166+}
167+
168+func (s *AllowedTargetVersionSuite) TestAllowedTargetVersionSuite(c *gc.C) {
169+ cases := []allowedTest{
170+ {current: "1.2.3", target: "1.3.3", allowed: true},
171+ {current: "1.2.3", target: "1.2.3", allowed: true},
172+ {current: "1.2.3", target: "2.2.3", allowed: true},
173+ {current: "1.2.3", target: "1.1.3", allowed: false},
174+ {current: "1.2.3", target: "1.2.2", allowed: true},
175+ {current: "1.2.3", target: "0.2.3", allowed: false},
176+ }
177+ for i, test := range cases {
178+ c.Logf("test case %d, %#v", i, test)
179+ current := version.MustParse(test.current)
180+ target := version.MustParse(test.target)
181+ c.Check(upgrader.AllowedTargetVersion(current, target), gc.Equals, test.allowed)
182+ }
183+}

Subscribers

People subscribed via source and target branches

to all changes: