// EnsureToolsAvailability verifies the tools are available. If no tools are // found, it will automatically synchronize them. func EnsureToolsAvailability(ctx environs.BootstrapContext, env environs.Environ, series string, toolsArch *string) (coretools.List, error) { cfg := env.Config() var vers *version.Number if agentVersion, ok := cfg.AgentVersion(); ok { vers = &agentVersion } logger.Debugf( "looking for bootstrap tools: series=%q, arch=%v, version=%v", series, toolsArch, vers, ) params := envtools.BootstrapToolsParams{ Version: vers, Arch: toolsArch, Series: series, // If vers.Build>0, the tools may have been uploaded in this session. // Allow retries, so we wait until the storage has caught up. AllowRetry: vers != nil && vers.Build > 0, } toolsList, err := envtools.FindBootstrapTools(env, params) if err == nil { return toolsList, nil } else if !errors.IsNotFound(err) { return nil, err } // Only automatically upload tools for dev versions. if !version.Current.IsDev() { return nil, fmt.Errorf("cannot upload bootstrap tools: %v", noToolsNoUploadMessage) } // No tools available so our only hope is to build locally and upload. logger.Warningf("no prepackaged tools available") uploadSeries := SeriesToUpload(cfg, nil) if series != "" { uploadSeries = append(uploadSeries, series) } if err := UploadTools(ctx, env, toolsArch, false, uploadSeries...); err != nil { logger.Errorf("%s", noToolsMessage) return nil, fmt.Errorf("cannot upload bootstrap tools: %v", err) } // TODO(axw) have uploadTools return the list of tools in the target, and use that. params.AllowRetry = true if toolsList, err = envtools.FindBootstrapTools(env, params); err != nil { return nil, fmt.Errorf("cannot find bootstrap tools: %v", err) } return toolsList, nil }
func (s *bootstrapSuite) getArgs(c *gc.C) manual.BootstrapArgs { hostname, err := os.Hostname() c.Assert(err, gc.IsNil) toolsList, err := tools.FindBootstrapTools(s.Conn.Environ, tools.BootstrapToolsParams{}) c.Assert(err, gc.IsNil) arch := "amd64" return manual.BootstrapArgs{ Host: hostname, DataDir: "/var/lib/juju", Environ: s.env, PossibleTools: toolsList, Series: "precise", HardwareCharacteristics: &instance.HardwareCharacteristics{ Arch: &arch, }, Context: coretesting.Context(c), } }
func (s *bootstrapSuite) assertUploadTools(c *gc.C, vers version.Binary, forceVersion bool, extraConfig map[string]interface{}, errMessage string) { s.PatchValue(&version.Current, vers) // If we allow released tools to be uploaded, the build number is incremented so in that case // we need to ensure the environment is set up to allow dev tools to be used. env := newEnviron("foo", useDefaultKeys, extraConfig) s.setDummyStorage(c, env) envtesting.RemoveFakeTools(c, env.Storage()) // At this point, as a result of setDummyStorage, env has tools for amd64 uploaded. // Set version.Current to be arm64 to simulate a different CLI version. cliVersion := version.Current cliVersion.Arch = "arm64" version.Current = cliVersion s.PatchValue(&envtools.BundleTools, toolstesting.GetMockBundleTools(c)) // Host runs arm64, environment supports arm64. s.PatchValue(&arch.HostArch, func() string { return "arm64" }) arch := "arm64" err := bootstrap.UploadTools(coretesting.Context(c), env, &arch, forceVersion, "precise") if errMessage != "" { c.Assert(err, gc.NotNil) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Assert(stripped, gc.Matches, errMessage) return } c.Assert(err, gc.IsNil) params := envtools.BootstrapToolsParams{ Arch: &arch, Series: version.Current.Series, } agentTools, err := envtools.FindBootstrapTools(env, params) c.Assert(err, gc.IsNil) c.Assert(agentTools, gc.HasLen, 1) expectedVers := vers expectedVers.Number.Build++ expectedVers.Series = version.Current.Series c.Assert(agentTools[0].Version, gc.DeepEquals, expectedVers) }
func (s *SimpleStreamsToolsSuite) TestFindBootstrapTools(c *gc.C) { // Remove the default tools URL from the search path, just look in cloud storage. s.PatchValue(&envtools.DefaultBaseURL, "") for i, test := range envtesting.BootstrapToolsTests { c.Logf("\ntest %d: %s", i, test.Info) attrs := map[string]interface{}{ "development": test.Development, } var agentVersion *version.Number if test.AgentVersion != version.Zero { attrs["agent-version"] = test.AgentVersion.String() agentVersion = &test.AgentVersion } s.reset(c, attrs) version.Current = test.CliVersion available := s.uploadCustom(c, test.Available...) params := envtools.BootstrapToolsParams{ Version: agentVersion, Series: test.DefaultSeries, Arch: &test.Arch, } actual, err := envtools.FindBootstrapTools(s.env, params) if test.Err != "" { if len(actual) > 0 { c.Logf(actual.String()) } c.Check(err, jc.Satisfies, errors.IsNotFound) continue } expect := map[version.Binary]string{} for _, expected := range test.Expect { expect[expected] = available[expected] } c.Check(actual.URLs(), gc.DeepEquals, expect) } }