func (s *bootstrapSuite) setupBootstrapSpecificVersion(c *gc.C, clientMajor, clientMinor int, toolsVersion *version.Number) (error, int, version.Number) { currentVersion := version.Current currentVersion.Major = clientMajor currentVersion.Minor = clientMinor currentVersion.Tag = "" s.PatchValue(&version.Current, currentVersion) s.PatchValue(&series.HostSeries, func() string { return "trusty" }) s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 }) env := newEnviron("foo", useDefaultKeys, nil) s.setDummyStorage(c, env) envtools.RegisterToolsDataSourceFunc("local storage", func(environs.Environ) (simplestreams.DataSource, error) { return storage.NewStorageSimpleStreamsDataSource("test datasource", env.storage, "tools", simplestreams.CUSTOM_CLOUD_DATA, false), nil }) defer envtools.UnregisterToolsDataSourceFunc("local storage") toolsBinaries := []version.Binary{ version.MustParseBinary("10.11.12-trusty-amd64"), version.MustParseBinary("10.11.13-trusty-amd64"), version.MustParseBinary("10.11-beta1-trusty-amd64"), } stream := "released" if toolsVersion != nil && toolsVersion.Tag != "" { stream = "devel" currentVersion.Tag = toolsVersion.Tag } _, err := envtesting.UploadFakeToolsVersions(env.storage, stream, stream, toolsBinaries...) c.Assert(err, jc.ErrorIsNil) err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{ AgentVersion: toolsVersion, }) vers, _ := env.cfg.AgentVersion() return err, env.bootstrapCount, vers }
func (s *simplestreamsSuite) TestWriteMetadataMergeWithExisting(c *gc.C) { dir := c.MkDir() existingToolsList := coretools.List{ { Version: version.MustParseBinary("1.2.3-precise-amd64"), Size: 123, SHA256: "abc", }, { Version: version.MustParseBinary("2.0.1-raring-amd64"), Size: 456, SHA256: "xyz", }, } writer, err := filestorage.NewFileStorageWriter(dir) c.Assert(err, gc.IsNil) err = tools.MergeAndWriteMetadata(writer, existingToolsList, tools.DoNotWriteMirrors) c.Assert(err, gc.IsNil) newToolsList := coretools.List{ existingToolsList[0], { Version: version.MustParseBinary("2.1.0-raring-amd64"), Size: 789, SHA256: "def", }, } err = tools.MergeAndWriteMetadata(writer, newToolsList, tools.DoNotWriteMirrors) c.Assert(err, gc.IsNil) requiredToolsList := append(existingToolsList, newToolsList[1]) metadata := toolstesting.ParseMetadataFromDir(c, dir, false) assertMetadataMatches(c, dir, requiredToolsList, metadata) }
func (s *BootstrapSuite) TestAutoUploadAfterFailedSync(c *gc.C) { s.PatchValue(&version.Current.Series, config.LatestLtsSeries()) otherSeries := "quantal" env := s.setupAutoUploadTest(c, "1.7.3", otherSeries) // Run command and check for that upload has been run for tools matching the current juju version. opc, errc := runCommand(nullContext(c), envcmd.Wrap(new(BootstrapCommand))) c.Assert(<-errc, gc.IsNil) c.Assert((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham") list, err := envtools.FindTools(env, version.Current.Major, version.Current.Minor, coretools.Filter{}, false) c.Assert(err, gc.IsNil) c.Logf("found: " + list.String()) urls := list.URLs() // We expect: // supported LTS series precise, trusty, // the specified series (quantal), // and the environment's default series (raring). expectedVers := []version.Binary{ version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "quantal", version.Current.Arch)), version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "raring", version.Current.Arch)), version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "precise", version.Current.Arch)), version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "trusty", version.Current.Arch)), } c.Assert(urls, gc.HasLen, len(expectedVers)) for _, vers := range expectedVers { c.Logf("seeking: " + vers.String()) _, found := urls[vers] c.Check(found, gc.Equals, true) } }
func (s *simplestreamsSuite) TestWriteMetadataNoFetch(c *gc.C) { toolsList := coretools.List{ { Version: version.MustParseBinary("1.2.3-precise-amd64"), Size: 123, SHA256: "abcd", }, { Version: version.MustParseBinary("2.0.1-raring-amd64"), Size: 456, SHA256: "xyz", }, } expected := toolsList // Add tools with an unknown series. Do not add an entry in the // expected list as these tools should be ignored. vers, err := version.ParseBinary("3.2.1-xuanhuaceratops-amd64") c.Assert(err, jc.Satisfies, series.IsUnknownOSForSeriesError) toolsList = append(toolsList, &coretools.Tools{ Version: vers, Size: 456, SHA256: "wqe", }) dir := c.MkDir() writer, err := filestorage.NewFileStorageWriter(dir) c.Assert(err, jc.ErrorIsNil) err = tools.MergeAndWriteMetadata(writer, "proposed", "proposed", toolsList, tools.DoNotWriteMirrors) c.Assert(err, jc.ErrorIsNil) metadata := toolstesting.ParseMetadataFromDir(c, dir, "proposed", false) assertMetadataMatches(c, dir, "proposed", expected, metadata) }
func (*metadataHelperSuite) TestMetadataFromTools(c *gc.C) { metadata := tools.MetadataFromTools(nil, "proposed") c.Assert(metadata, gc.HasLen, 0) toolsList := coretools.List{{ Version: version.MustParseBinary("1.2.3-precise-amd64"), Size: 123, SHA256: "abc", }, { Version: version.MustParseBinary("2.0.1-raring-amd64"), URL: "file:///tmp/proposed/juju-2.0.1-raring-amd64.tgz", Size: 456, SHA256: "xyz", }} metadata = tools.MetadataFromTools(toolsList, "proposed") c.Assert(metadata, gc.HasLen, len(toolsList)) for i, t := range toolsList { md := metadata[i] c.Assert(md.Release, gc.Equals, t.Version.Series) c.Assert(md.Version, gc.Equals, t.Version.Number.String()) c.Assert(md.Arch, gc.Equals, t.Version.Arch) // FullPath is only filled out when reading tools using simplestreams. // It's not needed elsewhere and requires a URL() call. c.Assert(md.FullPath, gc.Equals, "") c.Assert(md.Path, gc.Equals, tools.StorageName(t.Version, "proposed")[len("tools/"):]) c.Assert(md.FileType, gc.Equals, "tar.gz") c.Assert(md.Size, gc.Equals, t.Size) c.Assert(md.SHA256, gc.Equals, t.SHA256) } }
func (s *simplestreamsSuite) assertWriteMetadata(c *gc.C, withMirrors bool) { var versionStrings = []string{ "1.2.3-precise-amd64", "2.0.1-raring-amd64", } dir := c.MkDir() toolstesting.MakeTools(c, dir, "proposed", versionStrings) toolsList := coretools.List{ { // If sha256/size is already known, do not recalculate Version: version.MustParseBinary("1.2.3-precise-amd64"), Size: 123, SHA256: "abcd", }, { Version: version.MustParseBinary("2.0.1-raring-amd64"), // The URL is not used for generating metadata. URL: "bogus://", }, } writer, err := filestorage.NewFileStorageWriter(dir) c.Assert(err, jc.ErrorIsNil) writeMirrors := tools.DoNotWriteMirrors if withMirrors { writeMirrors = tools.WriteMirrors } err = tools.MergeAndWriteMetadata(writer, "proposed", "proposed", toolsList, writeMirrors) c.Assert(err, jc.ErrorIsNil) metadata := toolstesting.ParseMetadataFromDir(c, dir, "proposed", withMirrors) assertMetadataMatches(c, dir, "proposed", toolsList, metadata) // No release stream generated so there will not be a legacy index file created. _, err = writer.Get("tools/streams/v1/index.json") c.Assert(err, gc.NotNil) }
func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) { stor := s.Environ.Storage() oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, gc.IsNil) // Make the download take a while so that we verify that // the download happens before the upgrader checks if // it's been stopped. dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader() err = u.Stop() envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: oldTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version) c.Assert(err, gc.IsNil) envtesting.CheckTools(c, foundTools, newTools) }
func (s *UpgraderSuite) TestUpgraderAllowsDowngradeToOrigVersionIfUpgradeInProgress(c *gc.C) { // note: otherwise illegal version jump downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64") s.confVersion = downgradeVersion.Number s.upgradeRunning = true stor := s.Environ.Storage() origTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, origTools.Version) downgradeTools := envtesting.AssertUploadFakeToolsVersions(c, stor, downgradeVersion)[0] err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number) c.Assert(err, gc.IsNil) dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader(c) err = u.Stop() envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: origTools.Version, NewTools: downgradeVersion, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version) c.Assert(err, gc.IsNil) downgradeTools.URL = fmt.Sprintf("https://%s/environment/90168e4c-2f10-4e9c-83c2-feedfacee5a9/tools/5.3.0-precise-amd64", s.APIState.Addr()) envtesting.CheckTools(c, foundTools, downgradeTools) }
func (s *uploadSuite) TestMockBuildTools(c *gc.C) { s.PatchValue(&version.Current, version.MustParseBinary("1.9.1-trusty-amd64")) buildToolsFunc := toolstesting.GetMockBuildTools(c) builtTools, err := buildToolsFunc(nil) c.Assert(err, gc.IsNil) builtTools.Dir = "" expectedBuiltTools := &sync.BuiltTools{ StorageName: "name", Version: version.Current, Size: 127, Sha256Hash: "6a19d08ca4913382ca86508aa38eb8ee5b9ae2d74333fe8d862c0f9e29b82c39", } c.Assert(builtTools, gc.DeepEquals, expectedBuiltTools) vers := version.MustParseBinary("1.5.3-trusty-amd64") builtTools, err = buildToolsFunc(&vers.Number) c.Assert(err, gc.IsNil) builtTools.Dir = "" expectedBuiltTools = &sync.BuiltTools{ StorageName: "name", Version: vers, Size: 127, Sha256Hash: "cad8ccedab8f26807ff379ddc2f2f78d9a7cac1276e001154cee5e39b9ddcc38", } c.Assert(builtTools, gc.DeepEquals, expectedBuiltTools) }
func (s *uploadSuite) TestMockBuildTools(c *gc.C) { current := version.MustParseBinary("1.9.1-trusty-amd64") s.PatchValue(&version.Current, current.Number) s.PatchValue(&arch.HostArch, func() string { return current.Arch }) s.PatchValue(&series.HostSeries, func() string { return current.Series }) buildToolsFunc := toolstesting.GetMockBuildTools(c) builtTools, err := buildToolsFunc(nil, "released") c.Assert(err, jc.ErrorIsNil) builtTools.Dir = "" expectedBuiltTools := &sync.BuiltTools{ StorageName: "name", Version: current, Size: 127, Sha256Hash: "6a19d08ca4913382ca86508aa38eb8ee5b9ae2d74333fe8d862c0f9e29b82c39", } c.Assert(builtTools, gc.DeepEquals, expectedBuiltTools) vers := version.MustParseBinary("1.5.3-trusty-amd64") builtTools, err = buildToolsFunc(&vers.Number, "released") c.Assert(err, jc.ErrorIsNil) builtTools.Dir = "" expectedBuiltTools = &sync.BuiltTools{ StorageName: "name", Version: vers, Size: 127, Sha256Hash: "cad8ccedab8f26807ff379ddc2f2f78d9a7cac1276e001154cee5e39b9ddcc38", } c.Assert(builtTools, gc.DeepEquals, expectedBuiltTools) }
func (s *bootstrapSuite) setupBootstrapSpecificVersion( c *gc.C, clientMajor, clientMinor int, toolsVersion *version.Number, ) (error, int, version.Number) { currentVersion := version.Current currentVersion.Major = clientMajor currentVersion.Minor = clientMinor currentVersion.Series = "trusty" currentVersion.Arch = "amd64" s.PatchValue(&version.Current, currentVersion) env := newEnviron("foo", useDefaultKeys, nil) s.setDummyStorage(c, env) envtools.RegisterToolsDataSourceFunc("local storage", func(environs.Environ) (simplestreams.DataSource, error) { return storage.NewStorageSimpleStreamsDataSource("test datasource", env.storage, "tools"), nil }) defer envtools.UnregisterToolsDataSourceFunc("local storage") toolsBinaries := []version.Binary{ version.MustParseBinary("10.11.12-trusty-amd64"), version.MustParseBinary("10.11.13-trusty-amd64"), } _, err := envtesting.UploadFakeToolsVersions(env.storage, "released", "released", toolsBinaries...) c.Assert(err, jc.ErrorIsNil) err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{ AgentVersion: toolsVersion, }) vers, _ := env.cfg.AgentVersion() return err, env.bootstrapCount, vers }
func (s *UpgradeJujuSuite) TestUpgradeJuju(c *gc.C) { for i, test := range upgradeJujuTests { c.Logf("\ntest %d: %s", i, test.about) s.Reset(c) tools.DefaultBaseURL = "" // Set up apparent CLI version and initialize the command. s.PatchValue(&version.Current, version.MustParseBinary(test.currentVersion)) com := &UpgradeJujuCommand{} if err := coretesting.InitCommand(envcmd.Wrap(com), test.args); err != nil { if test.expectInitErr != "" { c.Check(err, gc.ErrorMatches, test.expectInitErr) } else { c.Check(err, jc.ErrorIsNil) } continue } // Set up state and environ, and run the command. toolsDir := c.MkDir() updateAttrs := map[string]interface{}{ "agent-version": test.agentVersion, "agent-metadata-url": "file://" + toolsDir + "/tools", } err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil) c.Assert(err, jc.ErrorIsNil) versions := make([]version.Binary, len(test.tools)) for i, v := range test.tools { versions[i] = version.MustParseBinary(v) } if len(versions) > 0 { stor, err := filestorage.NewFileStorageWriter(toolsDir) c.Assert(err, jc.ErrorIsNil) envtesting.MustUploadFakeToolsVersions(stor, s.Environ.Config().AgentStream(), versions...) } err = com.Run(coretesting.Context(c)) if test.expectErr != "" { c.Check(err, gc.ErrorMatches, test.expectErr) continue } else if !c.Check(err, jc.ErrorIsNil) { continue } // Check expected changes to environ/state. cfg, err := s.State.EnvironConfig() c.Check(err, jc.ErrorIsNil) agentVersion, ok := cfg.AgentVersion() c.Check(ok, jc.IsTrue) c.Check(agentVersion, gc.Equals, version.MustParse(test.expectVersion)) for _, uploaded := range test.expectUploaded { // Substitute latest LTS for placeholder in expected series for uploaded tools uploaded = strings.Replace(uploaded, "%LTS%", config.LatestLtsSeries(), 1) vers := version.MustParseBinary(uploaded) s.checkToolsUploaded(c, vers, agentVersion) } } }
func (s *bootstrapSuite) TestSetBootstrapTools(c *gc.C) { availableVersions := []version.Binary{ version.MustParseBinary("1.18.0-trusty-arm64"), version.MustParseBinary("1.18.1-trusty-arm64"), version.MustParseBinary("1.18.1.1-trusty-arm64"), version.MustParseBinary("1.18.1.2-trusty-arm64"), version.MustParseBinary("1.18.1.3-trusty-arm64"), } availableTools := make(tools.List, len(availableVersions)) for i, v := range availableVersions { availableTools[i] = &tools.Tools{Version: v} } type test struct { currentVersion version.Number expectedTools version.Number expectedAgentVersion version.Number } tests := []test{{ currentVersion: version.MustParse("1.18.0"), expectedTools: version.MustParse("1.18.0"), expectedAgentVersion: version.MustParse("1.18.1.3"), }, { currentVersion: version.MustParse("1.18.1.4"), expectedTools: version.MustParse("1.18.1.3"), expectedAgentVersion: version.MustParse("1.18.1.3"), }, { // build number is ignored unless major/minor don't // match the latest. currentVersion: version.MustParse("1.18.1.2"), expectedTools: version.MustParse("1.18.1.3"), expectedAgentVersion: version.MustParse("1.18.1.3"), }, { // If the current patch level exceeds whatever's in // the tools source (e.g. when bootstrapping from trunk) // then the latest available tools will be chosen. currentVersion: version.MustParse("1.18.2"), expectedTools: version.MustParse("1.18.1.3"), expectedAgentVersion: version.MustParse("1.18.1.3"), }} env := newEnviron("foo", useDefaultKeys, nil) for i, t := range tests { c.Logf("test %d: %+v", i, t) cfg, err := env.Config().Remove([]string{"agent-version"}) c.Assert(err, gc.IsNil) err = env.SetConfig(cfg) c.Assert(err, gc.IsNil) s.PatchValue(&version.Current.Number, t.currentVersion) bootstrapTools, err := bootstrap.SetBootstrapTools(env, availableTools) c.Assert(err, gc.IsNil) c.Assert(bootstrapTools, gc.HasLen, 1) c.Assert(bootstrapTools[0].Version.Number, gc.Equals, t.expectedTools) agentVersion, _ := env.Config().AgentVersion() c.Assert(agentVersion, gc.Equals, t.expectedAgentVersion) } }
func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) { stor := s.DefaultToolsStorage oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, jc.ErrorIsNil) retryc := make(chan time.Time) *upgrader.RetryAfter = func() <-chan time.Time { c.Logf("replacement retry after") return retryc } err = stor.Remove(envtools.StorageName(newTools.Version, "released")) c.Assert(err, jc.ErrorIsNil) u := s.makeUpgrader(c) defer u.Stop() s.expectUpgradeChannelNotClosed(c) for i := 0; i < 3; i++ { select { case retryc <- time.Now(): case <-time.After(coretesting.LongWait): c.Fatalf("upgrader did not retry (attempt %d)", i) } } // Make it upgrade to some newer tools that can be // downloaded ok; it should stop retrying, download // the newer tools and exit. newerTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.6-precise-amd64"))[0] err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number) c.Assert(err, jc.ErrorIsNil) s.BackingState.StartSync() done := make(chan error) go func() { done <- u.Wait() }() select { case err := <-done: envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: oldTools.Version, NewTools: newerTools.Version, DataDir: s.DataDir(), }) case <-time.After(coretesting.LongWait): c.Fatalf("upgrader did not quit after upgrading") } }
func (s *toolsSuite) TestFindToolsExactInStorage(c *gc.C) { mockToolsStorage := &mockToolsStorage{ metadata: []toolstorage.Metadata{ {Version: version.MustParseBinary("1.22-beta1-trusty-amd64")}, {Version: version.MustParseBinary("1.22.0-trusty-amd64")}, }, } s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 }) s.PatchValue(&version.Current, version.MustParseBinary("1.22-beta1-trusty-amd64")) s.testFindToolsExact(c, mockToolsStorage, true, true) s.PatchValue(&version.Current, version.MustParseBinary("1.22.0-trusty-amd64")) s.testFindToolsExact(c, mockToolsStorage, true, false) }
func (*metadataHelperSuite) TestResolveMetadataLegacyPPC64(c *gc.C) { var versionStrings = []string{"1.2.3-precise-amd64", "1.2.3-precise-ppc64el"} dir := c.MkDir() toolstesting.MakeTools(c, dir, "released", versionStrings) toolsList := coretools.List{ { Version: version.MustParseBinary(versionStrings[0]), }, { Version: version.MustParseBinary(versionStrings[1]), }, { Version: version.MustParseBinary("1.2.3-precise-ppc64"), }, } toolsMetadata := tools.MetadataFromTools(toolsList, dir) stor, err := filestorage.NewFileStorageReader(dir) c.Assert(err, jc.ErrorIsNil) err = tools.ResolveMetadata(stor, "released", toolsMetadata) c.Assert(err, jc.ErrorIsNil) c.Assert(toolsMetadata, gc.DeepEquals, []*tools.ToolsMetadata{ { Release: "precise", Version: "1.2.3", Arch: "amd64", Size: 19, FileType: "tar.gz", SHA256: "dcdd65b962b804a3d63b108d670290ee95a867a97fe9b9f99b2b77b5c7173e59", Path: fmt.Sprintf("%s/juju-1.2.3-precise-amd64.tgz", dir), }, { Release: "precise", Version: "1.2.3", Arch: "ppc64el", Size: 21, FileType: "tar.gz", SHA256: "a3460ed45eb07a69adfcd541413a495f988c5842d715c6a40353075c3ad47af2", Path: fmt.Sprintf("%s/juju-1.2.3-precise-ppc64el.tgz", dir), }, { Release: "precise", Version: "1.2.3", Arch: "ppc64", Size: 21, FileType: "tar.gz", SHA256: "a3460ed45eb07a69adfcd541413a495f988c5842d715c6a40353075c3ad47af2", Path: fmt.Sprintf("%s/juju-1.2.3-precise-ppc64el.tgz", dir), }, }) }
func (s *clientSuite) TestUploadToolsOtherEnvironment(c *gc.C) { otherSt, otherAPISt := s.otherEnviron(c) defer otherSt.Close() defer otherAPISt.Close() client := otherAPISt.Client() newVersion := version.MustParseBinary("5.4.3-quantal-amd64") var called bool // build fake tools expectedTools, _ := coretesting.TarGz( coretesting.NewTarFile(jujunames.Jujud, 0777, "jujud contents "+newVersion.String())) // UploadTools does not use the facades, so instead of patching the // facade call, we set up a fake endpoint to test. defer fakeAPIEndpoint(c, client, envEndpoint(c, otherAPISt, "tools"), "POST", func(w http.ResponseWriter, r *http.Request) { called = true c.Assert(r.URL.Query(), gc.DeepEquals, url.Values{ "binaryVersion": []string{"5.4.3-quantal-amd64"}, "series": []string{""}, }) defer r.Body.Close() obtainedTools, err := ioutil.ReadAll(r.Body) c.Assert(err, jc.ErrorIsNil) c.Assert(obtainedTools, gc.DeepEquals, expectedTools) }, ).Close() // We don't test the error or tools results as we only wish to assert that // the API client POSTs the tools archive to the correct endpoint. client.UploadTools(bytes.NewReader(expectedTools), newVersion) c.Assert(called, jc.IsTrue) }
func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) { stor := s.DefaultToolsStorage oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, jc.ErrorIsNil) // Make the download take a while so that we verify that // the download happens before the upgrader checks if // it's been stopped. dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader(c) err = u.Stop() s.expectUpgradeChannelNotClosed(c) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: oldTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version) c.Assert(err, jc.ErrorIsNil) newTools.URL = fmt.Sprintf("https://%s/environment/%s/tools/5.4.5-precise-amd64", s.APIState.Addr(), coretesting.EnvironmentTag.Id()) envtesting.CheckTools(c, foundTools, newTools) }
func testAgentTools(c *gc.C, obj tooler, agent string) { // object starts with zero'd tools. t, err := obj.AgentTools() c.Assert(t, gc.IsNil) c.Assert(err, jc.Satisfies, errors.IsNotFound) err = obj.SetAgentVersion(version.Binary{}) c.Assert(err, gc.ErrorMatches, fmt.Sprintf("cannot set agent version for %s: empty series or arch", agent)) v2 := version.MustParseBinary("7.8.9-quantal-amd64") err = obj.SetAgentVersion(v2) c.Assert(err, gc.IsNil) t3, err := obj.AgentTools() c.Assert(err, gc.IsNil) c.Assert(t3.Version, gc.DeepEquals, v2) err = obj.Refresh() c.Assert(err, gc.IsNil) t3, err = obj.AgentTools() c.Assert(err, gc.IsNil) c.Assert(t3.Version, gc.DeepEquals, v2) testWhenDying(c, obj, noErr, deadErr, func() error { return obj.SetAgentVersion(v2) }) }
// makeMachineConfig produces a valid cloudinit machine config. func makeMachineConfig(c *gc.C) *cloudinit.MachineConfig { machineId := "0" machineTag := names.NewMachineTag(machineId) return &cloudinit.MachineConfig{ MachineId: machineId, MachineNonce: "gxshasqlnng", DataDir: environs.DataDir, LogDir: agent.DefaultLogDir, Jobs: []params.MachineJob{params.JobManageEnviron, params.JobHostUnits}, CloudInitOutputLog: cloudInitOutputLog, Tools: &tools.Tools{ Version: version.MustParseBinary("1.2.3-quantal-amd64"), URL: "http://testing.invalid/tools.tar.gz", }, Series: "quantal", MongoInfo: &mongo.MongoInfo{ Info: mongo.Info{ CACert: testing.CACert, Addrs: []string{"127.0.0.1:123"}, }, Tag: machineTag, Password: "******", }, APIInfo: &api.Info{ CACert: testing.CACert, Addrs: []string{"127.0.0.1:123"}, Tag: machineTag, }, MachineAgentServiceName: "jujud-machine-0", } }
func (s *toolsSuite) TestFindAvailableToolsAutoUpload(c *gc.C) { s.PatchValue(&arch.HostArch, func() string { return "amd64" }) s.PatchValue(&version.Current.Arch, "amd64") trustyTools := &tools.Tools{ Version: version.MustParseBinary("1.2.3-trusty-amd64"), URL: "http://testing.invalid/tools.tar.gz", } s.PatchValue(bootstrap.FindTools, func(_ environs.ConfigGetter, major, minor int, f tools.Filter, retry bool) (tools.List, error) { return tools.List{trustyTools}, nil }) env := newEnviron("foo", useDefaultKeys, nil) availableTools, err := bootstrap.FindAvailableTools(env, nil, false) c.Assert(err, gc.IsNil) c.Assert(len(availableTools), jc.GreaterThan, 1) c.Assert(env.supportedArchitecturesCount, gc.Equals, 1) var trustyToolsFound int expectedVersion := version.Current.Number expectedVersion.Build++ for _, tools := range availableTools { if tools == trustyTools { trustyToolsFound++ } else { c.Assert(tools.Version.Number, gc.Equals, expectedVersion) c.Assert(tools.Version.Series, gc.Not(gc.Equals), "trusty") c.Assert(tools.URL, gc.Equals, "") } } c.Assert(trustyToolsFound, gc.Equals, 1) }
func (s *apiEnvironmentSuite) TestUploadToolsOtherEnvironment(c *gc.C) { // setup other environment otherState := s.Factory.MakeEnvironment(c, nil) defer otherState.Close() info := s.APIInfo(c) info.EnvironTag = otherState.EnvironTag() otherAPIState, err := api.Open(info, api.DefaultDialOpts()) c.Assert(err, jc.ErrorIsNil) defer otherAPIState.Close() otherClient := otherAPIState.Client() defer otherClient.ClientFacade.Close() newVersion := version.MustParseBinary("5.4.3-quantal-amd64") // build fake tools tgz, checksum := coretesting.TarGz( coretesting.NewTarFile(jujunames.Jujud, 0777, "jujud contents "+newVersion.String())) tool, err := otherClient.UploadTools(bytes.NewReader(tgz), newVersion) c.Assert(err, jc.ErrorIsNil) c.Assert(tool.SHA256, gc.Equals, checksum) toolStrg, err := otherState.ToolsStorage() defer toolStrg.Close() c.Assert(err, jc.ErrorIsNil) meta, closer, err := toolStrg.Tools(newVersion) defer closer.Close() c.Assert(err, jc.ErrorIsNil) c.Assert(meta.SHA256, gc.Equals, checksum) c.Assert(meta.Version, gc.Equals, newVersion) }
func (*metadataHelperSuite) TestResolveMetadata(c *gc.C) { var versionStrings = []string{"1.2.3-precise-amd64"} dir := c.MkDir() toolstesting.MakeTools(c, dir, "released", versionStrings) toolsList := coretools.List{{ Version: version.MustParseBinary(versionStrings[0]), Size: 123, SHA256: "abc", }} stor, err := filestorage.NewFileStorageReader(dir) c.Assert(err, jc.ErrorIsNil) err = tools.ResolveMetadata(stor, "released", nil) c.Assert(err, jc.ErrorIsNil) // We already have size/sha256, so ensure that storage isn't consulted. countingStorage := &countingStorage{StorageReader: stor} metadata := tools.MetadataFromTools(toolsList, "released") err = tools.ResolveMetadata(countingStorage, "released", metadata) c.Assert(err, jc.ErrorIsNil) c.Assert(countingStorage.counter, gc.Equals, 0) // Now clear size/sha256, and check that it is called, and // the size/sha256 sum are updated. metadata[0].Size = 0 metadata[0].SHA256 = "" err = tools.ResolveMetadata(countingStorage, "released", metadata) c.Assert(err, jc.ErrorIsNil) c.Assert(countingStorage.counter, gc.Equals, 1) c.Assert(metadata[0].Size, gc.Not(gc.Equals), 0) c.Assert(metadata[0].SHA256, gc.Not(gc.Equals), "") }
// Check that we get a consistent error when asking for an instance without // a valid machine config. func (t *LiveTests) TestStartInstanceWithEmptyNonceFails(c *gc.C) { machineId := "4" stateInfo := jujutesting.FakeStateInfo(machineId) apiInfo := jujutesting.FakeAPIInfo(machineId) instanceConfig, err := instancecfg.NewInstanceConfig(machineId, "", "released", "quantal", "", true, nil, stateInfo, apiInfo) c.Assert(err, jc.ErrorIsNil) t.PrepareOnce(c) possibleTools := coretools.List(envtesting.AssertUploadFakeToolsVersions( c, t.toolsStorage, "released", "released", version.MustParseBinary("5.4.5-trusty-amd64"), )) params := environs.StartInstanceParams{ Tools: possibleTools, InstanceConfig: instanceConfig, } err = jujutesting.SetImageMetadata( t.Env, possibleTools.AllSeries(), possibleTools.Arches(), ¶ms.ImageMetadata, ) c.Check(err, jc.ErrorIsNil) result, err := t.Env.StartInstance(params) if result != nil && result.Instance != nil { err := t.Env.StopInstances(result.Instance.Id()) c.Check(err, jc.ErrorIsNil) } c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, ".*missing machine nonce") }
func (s *BootstrapSuite) runAllowRetriesTest(c *gc.C, test bootstrapRetryTest) { toolsVersions := envtesting.VAll if test.version != "" { useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1) testVersion := version.MustParseBinary(useVersion) s.PatchValue(&version.Current, testVersion) if test.addVersionToSource { toolsVersions = append([]version.Binary{}, toolsVersions...) toolsVersions = append(toolsVersions, testVersion) } } resetJujuHome(c) sourceDir := createToolsSource(c, toolsVersions) s.PatchValue(&envtools.DefaultBaseURL, sourceDir) var findToolsRetryValues []bool mockFindTools := func(cloudInst environs.ConfigGetter, majorVersion, minorVersion int, filter coretools.Filter, allowRetry bool) (list coretools.List, err error) { findToolsRetryValues = append(findToolsRetryValues, allowRetry) return nil, errors.NotFoundf("tools") } restore := envtools.TestingPatchBootstrapFindTools(mockFindTools) defer restore() _, errc := runCommand(nullContext(c), envcmd.Wrap(new(BootstrapCommand)), test.args...) err := <-errc c.Check(findToolsRetryValues, gc.DeepEquals, test.expectedAllowRetry) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, test.err) }
func makeTools(c *gc.C, metadataDir, subdir string, versionStrings []string, withCheckSum bool) coretools.List { toolsDir := filepath.Join(metadataDir, storage.BaseToolsPath) if subdir != "" { toolsDir = filepath.Join(toolsDir, subdir) } c.Assert(os.MkdirAll(toolsDir, 0755), gc.IsNil) var toolsList coretools.List for _, versionString := range versionStrings { binary := version.MustParseBinary(versionString) path := filepath.Join(toolsDir, fmt.Sprintf("juju-%s.tgz", binary)) data := binary.String() err := ioutil.WriteFile(path, []byte(data), 0644) c.Assert(err, gc.IsNil) tool := &coretools.Tools{ Version: binary, URL: path, } if withCheckSum { tool.Size, tool.SHA256 = SHA256sum(c, path) } toolsList = append(toolsList, tool) } // Write the tools metadata. stor, err := filestorage.NewFileStorageWriter(metadataDir) c.Assert(err, gc.IsNil) err = tools.MergeAndWriteMetadata(stor, toolsList, false) c.Assert(err, gc.IsNil) return toolsList }
func (s *UpgradeJujuSuite) setUpEnvAndTools(c *gc.C, currentVersion string, agentVersion string, tools []string) { current := version.MustParseBinary(currentVersion) s.PatchValue(&version.Current, current.Number) s.PatchValue(&arch.HostArch, func() string { return current.Arch }) s.PatchValue(&series.HostSeries, func() string { return current.Series }) toolsDir := c.MkDir() updateAttrs := map[string]interface{}{ "agent-version": agentVersion, "agent-metadata-url": "file://" + toolsDir + "/tools", } err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil) c.Assert(err, jc.ErrorIsNil) versions := make([]version.Binary, len(tools)) for i, v := range tools { versions[i], err = version.ParseBinary(v) if err != nil { c.Assert(err, jc.Satisfies, series.IsUnknownOSForSeriesError) } } if len(versions) > 0 { stor, err := filestorage.NewFileStorageWriter(toolsDir) c.Assert(err, jc.ErrorIsNil) envtesting.MustUploadFakeToolsVersions(stor, s.Environ.Config().AgentStream(), versions...) } }
func (s *UpgraderSuite) TestUpgraderAllowsDowngradingPatchVersions(c *gc.C) { stor := s.DefaultToolsStorage origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, origTools.Version) downgradeTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.2-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, downgradeTools.Version.Number) c.Assert(err, jc.ErrorIsNil) dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader(c) err = u.Stop() s.expectUpgradeChannelNotClosed(c) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: origTools.Version, NewTools: downgradeTools.Version, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version) c.Assert(err, jc.ErrorIsNil) downgradeTools.URL = fmt.Sprintf("https://%s/environment/%s/tools/5.4.2-precise-amd64", s.APIState.Addr(), coretesting.EnvironmentTag.Id()) envtesting.CheckTools(c, foundTools, downgradeTools) }
func (s *UpgraderSuite) TestUpgraderAllowsDowngradeToOrigVersionIfUpgradeInProgress(c *gc.C) { // note: otherwise illegal version jump downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64") s.confVersion = downgradeVersion.Number stor := s.DefaultToolsStorage origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.patchVersion(origTools.Version) downgradeTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), downgradeVersion)[0] err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number) c.Assert(err, jc.ErrorIsNil) u := s.makeUpgrader(c) err = u.Stop() s.expectInitialUpgradeCheckNotDone(c) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: origTools.Version, NewTools: downgradeVersion, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version) c.Assert(err, jc.ErrorIsNil) downgradeTools.URL = fmt.Sprintf("https://%s/model/%s/tools/5.3.0-precise-amd64", s.APIState.Addr(), coretesting.ModelTag.Id()) envtesting.CheckTools(c, foundTools, downgradeTools) }
func (s *toolsSuite) setupToolsForUpload(c *gc.C) (coretools.List, version.Binary, string) { localStorage := c.MkDir() vers := version.MustParseBinary("1.9.0-quantal-amd64") versionStrings := []string{vers.String()} expectedTools := toolstesting.MakeToolsWithCheckSum(c, localStorage, "releases", versionStrings) toolsFile := tools.StorageName(vers) return expectedTools, vers, path.Join(localStorage, toolsFile) }