github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/worker/upgrader/upgrader_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgrader_test 5 6 import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 stdtesting "testing" 11 "time" 12 13 gc "launchpad.net/gocheck" 14 15 "launchpad.net/juju-core/agent" 16 agenttools "launchpad.net/juju-core/agent/tools" 17 envtesting "launchpad.net/juju-core/environs/testing" 18 envtools "launchpad.net/juju-core/environs/tools" 19 "launchpad.net/juju-core/errors" 20 jujutesting "launchpad.net/juju-core/juju/testing" 21 "launchpad.net/juju-core/provider/dummy" 22 "launchpad.net/juju-core/state" 23 "launchpad.net/juju-core/state/api" 24 statetesting "launchpad.net/juju-core/state/testing" 25 coretesting "launchpad.net/juju-core/testing" 26 jc "launchpad.net/juju-core/testing/checkers" 27 coretools "launchpad.net/juju-core/tools" 28 "launchpad.net/juju-core/version" 29 "launchpad.net/juju-core/worker/upgrader" 30 ) 31 32 func TestPackage(t *stdtesting.T) { 33 coretesting.MgoTestPackage(t) 34 } 35 36 type UpgraderSuite struct { 37 jujutesting.JujuConnSuite 38 39 machine *state.Machine 40 state *api.State 41 oldRetryAfter func() <-chan time.Time 42 } 43 44 var _ = gc.Suite(&UpgraderSuite{}) 45 46 func (s *UpgraderSuite) SetUpTest(c *gc.C) { 47 s.JujuConnSuite.SetUpTest(c) 48 s.state, s.machine = s.OpenAPIAsNewMachine(c) 49 // Capture the value of RetryAfter, and use that captured 50 // value in the cleanup lambda. 51 oldRetryAfter := *upgrader.RetryAfter 52 s.AddCleanup(func(*gc.C) { 53 *upgrader.RetryAfter = oldRetryAfter 54 }) 55 } 56 57 type mockConfig struct { 58 agent.Config 59 tag string 60 datadir string 61 } 62 63 func (mock *mockConfig) Tag() string { 64 return mock.tag 65 } 66 67 func (mock *mockConfig) DataDir() string { 68 return mock.datadir 69 } 70 71 func agentConfig(tag, datadir string) agent.Config { 72 return &mockConfig{tag: tag, datadir: datadir} 73 } 74 75 func (s *UpgraderSuite) makeUpgrader() *upgrader.Upgrader { 76 config := agentConfig(s.machine.Tag(), s.DataDir()) 77 return upgrader.NewUpgrader(s.state.Upgrader(), config) 78 } 79 80 func (s *UpgraderSuite) TestUpgraderSetsTools(c *gc.C) { 81 vers := version.MustParseBinary("5.4.3-precise-amd64") 82 err := statetesting.SetAgentVersion(s.State, vers.Number) 83 c.Assert(err, gc.IsNil) 84 stor := s.Conn.Environ.Storage() 85 agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), vers) 86 s.PatchValue(&version.Current, agentTools.Version) 87 err = envtools.MergeAndWriteMetadata(stor, coretools.List{agentTools}, envtools.DoNotWriteMirrors) 88 _, err = s.machine.AgentTools() 89 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 90 91 u := s.makeUpgrader() 92 statetesting.AssertStop(c, u) 93 s.machine.Refresh() 94 gotTools, err := s.machine.AgentTools() 95 c.Assert(err, gc.IsNil) 96 envtesting.CheckTools(c, gotTools, agentTools) 97 } 98 99 func (s *UpgraderSuite) TestUpgraderSetVersion(c *gc.C) { 100 vers := version.MustParseBinary("5.4.3-precise-amd64") 101 agentTools := envtesting.PrimeTools(c, s.Conn.Environ.Storage(), s.DataDir(), vers) 102 s.PatchValue(&version.Current, agentTools.Version) 103 err := os.RemoveAll(filepath.Join(s.DataDir(), "tools")) 104 c.Assert(err, gc.IsNil) 105 106 _, err = s.machine.AgentTools() 107 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 108 err = statetesting.SetAgentVersion(s.State, vers.Number) 109 c.Assert(err, gc.IsNil) 110 111 u := s.makeUpgrader() 112 statetesting.AssertStop(c, u) 113 s.machine.Refresh() 114 gotTools, err := s.machine.AgentTools() 115 c.Assert(err, gc.IsNil) 116 c.Assert(gotTools, gc.DeepEquals, &coretools.Tools{Version: version.Current}) 117 } 118 119 func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) { 120 stor := s.Conn.Environ.Storage() 121 oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) 122 s.PatchValue(&version.Current, oldTools.Version) 123 newTools := envtesting.AssertUploadFakeToolsVersions( 124 c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0] 125 err := envtools.MergeAndWriteMetadata(stor, coretools.List{oldTools, newTools}, envtools.DoNotWriteMirrors) 126 c.Assert(err, gc.IsNil) 127 err = statetesting.SetAgentVersion(s.State, newTools.Version.Number) 128 c.Assert(err, gc.IsNil) 129 130 // Make the download take a while so that we verify that 131 // the download happens before the upgrader checks if 132 // it's been stopped. 133 dummy.SetStorageDelay(coretesting.ShortWait) 134 135 u := s.makeUpgrader() 136 err = u.Stop() 137 envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ 138 AgentName: s.machine.Tag(), 139 OldTools: oldTools.Version, 140 NewTools: newTools.Version, 141 DataDir: s.DataDir(), 142 }) 143 foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version) 144 c.Assert(err, gc.IsNil) 145 envtesting.CheckTools(c, foundTools, newTools) 146 } 147 148 func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) { 149 stor := s.Conn.Environ.Storage() 150 oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) 151 s.PatchValue(&version.Current, oldTools.Version) 152 newTools := envtesting.AssertUploadFakeToolsVersions( 153 c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0] 154 err := envtools.MergeAndWriteMetadata(stor, coretools.List{oldTools, newTools}, envtools.DoNotWriteMirrors) 155 c.Assert(err, gc.IsNil) 156 err = statetesting.SetAgentVersion(s.State, newTools.Version.Number) 157 c.Assert(err, gc.IsNil) 158 159 retryc := make(chan time.Time) 160 *upgrader.RetryAfter = func() <-chan time.Time { 161 c.Logf("replacement retry after") 162 return retryc 163 } 164 dummy.Poison(s.Conn.Environ.Storage(), envtools.StorageName(newTools.Version), fmt.Errorf("a non-fatal dose")) 165 u := s.makeUpgrader() 166 defer u.Stop() 167 168 for i := 0; i < 3; i++ { 169 select { 170 case retryc <- time.Now(): 171 case <-time.After(coretesting.LongWait): 172 c.Fatalf("upgrader did not retry (attempt %d)", i) 173 } 174 } 175 176 // Make it upgrade to some newer tools that can be 177 // downloaded ok; it should stop retrying, download 178 // the newer tools and exit. 179 newerTools := envtesting.AssertUploadFakeToolsVersions( 180 c, s.Conn.Environ.Storage(), version.MustParseBinary("5.4.6-precise-amd64"))[0] 181 182 err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number) 183 c.Assert(err, gc.IsNil) 184 185 s.BackingState.StartSync() 186 done := make(chan error) 187 go func() { 188 done <- u.Wait() 189 }() 190 select { 191 case err := <-done: 192 envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ 193 AgentName: s.machine.Tag(), 194 OldTools: oldTools.Version, 195 NewTools: newerTools.Version, 196 DataDir: s.DataDir(), 197 }) 198 case <-time.After(coretesting.LongWait): 199 c.Fatalf("upgrader did not quit after upgrading") 200 } 201 } 202 203 func (s *UpgraderSuite) TestChangeAgentTools(c *gc.C) { 204 oldTools := &coretools.Tools{ 205 Version: version.MustParseBinary("1.2.3-quantal-amd64"), 206 } 207 stor := s.Conn.Environ.Storage() 208 newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) 209 s.PatchValue(&version.Current, newTools.Version) 210 err := envtools.MergeAndWriteMetadata(stor, coretools.List{newTools}, envtools.DoNotWriteMirrors) 211 c.Assert(err, gc.IsNil) 212 ugErr := &upgrader.UpgradeReadyError{ 213 AgentName: "anAgent", 214 OldTools: oldTools.Version, 215 NewTools: newTools.Version, 216 DataDir: s.DataDir(), 217 } 218 err = ugErr.ChangeAgentTools() 219 c.Assert(err, gc.IsNil) 220 link, err := os.Readlink(agenttools.ToolsDir(s.DataDir(), "anAgent")) 221 c.Assert(err, gc.IsNil) 222 c.Assert(link, gc.Equals, newTools.Version.String()) 223 } 224 225 func (s *UpgraderSuite) TestEnsureToolsChecksBeforeDownloading(c *gc.C) { 226 stor := s.Conn.Environ.Storage() 227 newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) 228 s.PatchValue(&version.Current, newTools.Version) 229 // We've already downloaded the tools, so change the URL to be 230 // something invalid and ensure we don't actually get an error, because 231 // it doesn't actually do an HTTP request 232 u := s.makeUpgrader() 233 newTools.URL = "http://localhost:999999/invalid/path/tools.tgz" 234 err := upgrader.EnsureTools(u, newTools, true) 235 c.Assert(err, gc.IsNil) 236 }