// StartInstanceWithParams is a test helper function that starts an instance // with the given parameters, and a plausible but invalid configuration, and // returns the result of Environ.StartInstance. The provided params's // MachineConfig and Tools field values will be ignored. func StartInstanceWithParams( env environs.Environ, machineId string, params environs.StartInstanceParams, networks []string, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { series := config.PreferredSeries(env.Config()) agentVersion, ok := env.Config().AgentVersion() if !ok { return nil, nil, nil, fmt.Errorf("missing agent version in environment config") } possibleTools, err := tools.FindInstanceTools( env, agentVersion, series, params.Constraints.Arch, ) if err != nil { return nil, nil, nil, err } machineNonce := "fake_nonce" stateInfo := FakeStateInfo(machineId) apiInfo := FakeAPIInfo(machineId) machineConfig := environs.NewMachineConfig( machineId, machineNonce, networks, stateInfo, apiInfo) params.Tools = possibleTools params.MachineConfig = machineConfig return env.StartInstance(params) }
// In the case where we cannot examine an environment, we want the // error to propagate back up to the user. func (s *BootstrapSuite) TestBootstrapPropagatesEnvErrors(c *gc.C) { //TODO(bogdanteleaga): fix this for windows once permissions are fixed if runtime.GOOS == "windows" { c.Skip("bug 1403084: this is very platform specific. When/if we will support windows state machine, this will probably be rewritten.") } const envName = "devenv" env := resetJujuHome(c, envName) defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) s.PatchValue(&environType, func(string) (string, error) { return "", nil }) _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, jc.ErrorIsNil) // Change permissions on the jenv file to simulate some kind of // unexpected error when trying to read info from the environment jenvFile := gitjujutesting.HomePath(".juju", "environments", envName+".jenv") err = os.Chmod(jenvFile, os.FileMode(0200)) c.Assert(err, jc.ErrorIsNil) // The second bootstrap should fail b/c of the propogated error _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.ErrorMatches, "there was an issue examining the environment: .*") }
// ModelInfo returns information about the current model. func (c *Client) ModelInfo() (params.ModelInfo, error) { if err := c.checkCanWrite(); err != nil { return params.ModelInfo{}, err } state := c.api.stateAccessor conf, err := state.ModelConfig() if err != nil { return params.ModelInfo{}, err } model, err := state.Model() if err != nil { return params.ModelInfo{}, err } info := params.ModelInfo{ DefaultSeries: config.PreferredSeries(conf), CloudTag: names.NewCloudTag(model.Cloud()).String(), CloudRegion: model.CloudRegion(), ProviderType: conf.Type(), Name: conf.Name(), UUID: model.UUID(), OwnerTag: model.Owner().String(), Life: params.Life(model.Life().String()), } if tag, ok := model.CloudCredential(); ok { info.CloudCredentialTag = tag.String() } return info, nil }
func PreferredDefaultVersions(conf *config.Config, template version.Binary) []version.Binary { prefVersion := template prefVersion.Series = config.PreferredSeries(conf) defaultVersion := template defaultVersion.Series = testing.FakeDefaultSeries return []version.Binary{prefVersion, defaultVersion} }
// In the case where we cannot examine an environment, we want the // error to propagate back up to the user. func (s *BootstrapSuite) TestBootstrapPropagatesEnvErrors(c *gc.C) { env := resetJujuHome(c) defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) const envName = "peckham" _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.IsNil) // Change permissions on the jenv file to simulate some kind of // unexpected error when trying to read info from the environment jenvFile := gitjujutesting.HomePath(".juju", "environments", envName+".jenv") err = os.Chmod(jenvFile, os.FileMode(0200)) c.Assert(err, gc.IsNil) // The second bootstrap should fail b/c of the propogated error _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.ErrorMatches, "there was an issue examining the environment: .*") }
// DefaultVersions returns a slice of unique 'versions' for the current // environment's preferred series and host architecture, as well supported LTS // series for the host architecture. Additionally, it ensures that 'versions' // for amd64 are returned if that is not the current host's architecture. func DefaultVersions(conf *config.Config) []version.Binary { var versions []version.Binary supported := series.SupportedLts() defaultSeries := set.NewStrings(supported...) defaultSeries.Add(config.PreferredSeries(conf)) defaultSeries.Add(series.HostSeries()) agentVersion, set := conf.AgentVersion() if !set { agentVersion = jujuversion.Current } for _, s := range defaultSeries.Values() { versions = append(versions, version.Binary{ Number: agentVersion, Arch: arch.HostArch(), Series: s, }) if arch.HostArch() != "amd64" { versions = append(versions, version.Binary{ Number: agentVersion, Arch: "amd64", Series: s, }) } } return versions }
// Bootstrap is a common implementation of the Bootstrap method defined on // environs.Environ; we strongly recommend that this implementation be used // when writing a new provider. func Bootstrap(ctx environs.BootstrapContext, env environs.Environ, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, err error) { // TODO make safe in the case of racing Bootstraps // If two Bootstraps are called concurrently, there's // no way to make sure that only one succeeds. var inst instance.Instance defer func() { handleBootstrapError(err, ctx, inst, env) }() // First thing, ensure we have tools otherwise there's no point. series = config.PreferredSeries(env.Config()) availableTools, err := args.AvailableTools.Match(coretools.Filter{Series: series}) if err != nil { return "", "", nil, err } // Get the bootstrap SSH client. Do this early, so we know // not to bother with any of the below if we can't finish the job. client := ssh.DefaultClient if client == nil { // This should never happen: if we don't have OpenSSH, then // go.crypto/ssh should be used with an auto-generated key. return "", "", nil, fmt.Errorf("no SSH client available") } machineConfig, err := environs.NewBootstrapMachineConfig(args.Constraints, series) if err != nil { return "", "", nil, err } machineConfig.EnableOSRefreshUpdate = env.Config().EnableOSRefreshUpdate() machineConfig.EnableOSUpgrade = env.Config().EnableOSUpgrade() fmt.Fprintln(ctx.GetStderr(), "Launching instance") inst, hw, _, err := env.StartInstance(environs.StartInstanceParams{ Constraints: args.Constraints, Tools: availableTools, MachineConfig: machineConfig, Placement: args.Placement, }) if err != nil { return "", "", nil, fmt.Errorf("cannot start bootstrap instance: %v", err) } fmt.Fprintf(ctx.GetStderr(), " - %s\n", inst.Id()) err = SaveState(env.Storage(), &BootstrapState{ StateInstances: []instance.Id{inst.Id()}, }) if err != nil { return "", "", nil, fmt.Errorf("cannot save state: %v", err) } finalize := func(ctx environs.BootstrapContext, mcfg *cloudinit.MachineConfig) error { mcfg.InstanceId = inst.Id() mcfg.HardwareCharacteristics = hw if err := environs.FinishMachineConfig(mcfg, env.Config()); err != nil { return err } return FinishBootstrap(ctx, client, inst, mcfg) } return *hw.Arch, series, finalize, nil }
// StartInstanceWithParams is a test helper function that starts an instance // with the given parameters, and a plausible but invalid configuration, and // returns the result of Environ.StartInstance. The provided params's // InstanceConfig and Tools field values will be ignored. func StartInstanceWithParams( env environs.Environ, machineId string, params environs.StartInstanceParams, networks []string, ) ( *environs.StartInstanceResult, error, ) { preferredSeries := config.PreferredSeries(env.Config()) agentVersion, ok := env.Config().AgentVersion() if !ok { return nil, errors.New("missing agent version in model config") } filter := coretools.Filter{ Number: agentVersion, Series: preferredSeries, } if params.Constraints.Arch != nil { filter.Arch = *params.Constraints.Arch } stream := tools.PreferredStream(&agentVersion, env.Config().Development(), env.Config().AgentStream()) possibleTools, err := tools.FindTools(env, -1, -1, stream, filter) if err != nil { return nil, errors.Trace(err) } if params.ImageMetadata == nil { if err := SetImageMetadata( env, possibleTools.AllSeries(), possibleTools.Arches(), ¶ms.ImageMetadata, ); err != nil { return nil, errors.Trace(err) } } machineNonce := "fake_nonce" stateInfo := FakeStateInfo(machineId) apiInfo := FakeAPIInfo(machineId) instanceConfig, err := instancecfg.NewInstanceConfig( machineId, machineNonce, imagemetadata.ReleasedStream, preferredSeries, "", true, networks, stateInfo, apiInfo, ) if err != nil { return nil, errors.Trace(err) } eUUID, _ := env.Config().UUID() instanceConfig.Tags[tags.JujuModel] = eUUID params.Tools = possibleTools params.InstanceConfig = instanceConfig return env.StartInstance(params) }
// setParams sets parameters based on the environment configuration // for those which have not been explicitly specified. func (c *imageMetadataCommand) setParams(context *cmd.Context) error { c.privateStorage = "<private storage name>" var environ environs.Environ if environ, err := c.prepare(context); err == nil { logger.Infof("creating image metadata for model %q", environ.Config().Name()) // If the user has not specified region and endpoint, try and get it from the environment. if c.Region == "" || c.Endpoint == "" { var cloudSpec simplestreams.CloudSpec if inst, ok := environ.(simplestreams.HasRegion); ok { if cloudSpec, err = inst.Region(); err != nil { return err } } else { return errors.Errorf("model %q cannot provide region and endpoint", environ.Config().Name()) } // If only one of region or endpoint is provided, that is a problem. if cloudSpec.Region != cloudSpec.Endpoint && (cloudSpec.Region == "" || cloudSpec.Endpoint == "") { return errors.Errorf("cannot generate metadata without a complete cloud configuration") } if c.Region == "" { c.Region = cloudSpec.Region } if c.Endpoint == "" { c.Endpoint = cloudSpec.Endpoint } } cfg := environ.Config() if c.Series == "" { c.Series = config.PreferredSeries(cfg) } } else { logger.Warningf("model could not be opened: %v", err) } if environ == nil { logger.Infof("no model found, creating image metadata using user supplied data") } if c.Series == "" { c.Series = series.LatestLts() } if c.ImageId == "" { return errors.Errorf("image id must be specified") } if c.Region == "" { return errors.Errorf("image region must be specified") } if c.Endpoint == "" { return errors.Errorf("cloud endpoint URL must be specified") } if c.Dir == "" { logger.Infof("no destination directory specified, using current directory") var err error if c.Dir, err = os.Getwd(); err != nil { return err } } return nil }
func (env *environ) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) { env.lock.Lock() defer env.lock.Unlock() return &simplestreams.MetadataLookupParams{ Region: region, Endpoint: gosigma.ResolveEndpoint(region), Series: config.PreferredSeries(env.ecfg), }, nil }
// MetadataLookupParams returns parameters which are used to query simplestreams metadata. func (env *joyentEnviron) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) { if region == "" { region = env.cloud.Region } return &simplestreams.MetadataLookupParams{ Series: config.PreferredSeries(env.Ecfg()), Region: region, Endpoint: env.cloud.Endpoint, }, nil }
// Bootstrap is a common implementation of the Bootstrap method defined on // environs.Environ; we strongly recommend that this implementation be used // when writing a new provider. func Bootstrap(ctx environs.BootstrapContext, env environs.Environ, args environs.BootstrapParams) (err error) { // TODO make safe in the case of racing Bootstraps // If two Bootstraps are called concurrently, there's // no way to make sure that only one succeeds. var inst instance.Instance defer func() { handleBootstrapError(err, ctx, inst, env) }() network.InitializeFromConfig(env.Config()) // First thing, ensure we have tools otherwise there's no point. selectedTools, err := EnsureBootstrapTools(ctx, env, config.PreferredSeries(env.Config()), args.Constraints.Arch) if err != nil { return err } // Get the bootstrap SSH client. Do this early, so we know // not to bother with any of the below if we can't finish the job. client := ssh.DefaultClient if client == nil { // This should never happen: if we don't have OpenSSH, then // go.crypto/ssh should be used with an auto-generated key. return fmt.Errorf("no SSH client available") } privateKey, err := GenerateSystemSSHKey(env) if err != nil { return err } machineConfig := environs.NewBootstrapMachineConfig(privateKey) fmt.Fprintln(ctx.GetStderr(), "Launching instance") inst, hw, _, err := env.StartInstance(environs.StartInstanceParams{ Constraints: args.Constraints, Tools: selectedTools, MachineConfig: machineConfig, Placement: args.Placement, }) if err != nil { return fmt.Errorf("cannot start bootstrap instance: %v", err) } fmt.Fprintf(ctx.GetStderr(), " - %s\n", inst.Id()) machineConfig.InstanceId = inst.Id() machineConfig.HardwareCharacteristics = hw err = bootstrap.SaveState( env.Storage(), &bootstrap.BootstrapState{ StateInstances: []instance.Id{inst.Id()}, }) if err != nil { return fmt.Errorf("cannot save state: %v", err) } return FinishBootstrap(ctx, client, inst, machineConfig) }
// MetadataLookupParams returns parameters which are used to query simplestreams metadata. func (env *joyentEnviron) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) { if region == "" { region = env.Ecfg().Region() } return &simplestreams.MetadataLookupParams{ Series: config.PreferredSeries(env.Ecfg()), Region: region, Endpoint: env.Ecfg().sdcUrl(), Architectures: []string{"amd64", "armhf"}, }, nil }
func (s *bootstrapSuite) TestEnsureToolsAvailabilityAgentVersionAlreadySet(c *gc.C) { // Can't upload tools if agent version already set. env := newEnviron("foo", useDefaultKeys, map[string]interface{}{"agent-version": "1.16.0"}) s.setDummyStorage(c, env) envtesting.RemoveFakeTools(c, env.Storage()) _, err := bootstrap.EnsureToolsAvailability(coretesting.Context(c), env, config.PreferredSeries(env.Config()), nil) c.Assert(err, gc.NotNil) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Assert(stripped, gc.Matches, "cannot upload bootstrap tools: Juju cannot bootstrap because no tools are available for your environment.*") }
func (s *bootstrapSuite) TestEnsureToolsAvailabilityNonDevVersion(c *gc.C) { // Can't automatically upload tools for released versions. s.PatchValue(&version.Current, version.MustParseBinary("1.18.0-trusty-arm64")) env := newEnviron("foo", useDefaultKeys, nil) s.setDummyStorage(c, env) envtesting.RemoveFakeTools(c, env.Storage()) _, err := bootstrap.EnsureToolsAvailability(coretesting.Context(c), env, config.PreferredSeries(env.Config()), nil) c.Assert(err, gc.NotNil) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Assert(stripped, gc.Matches, "cannot upload bootstrap tools: Juju cannot bootstrap because no tools are available for your environment.*") }
func (env *environ) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) { if region == "" { region = gosigma.DefaultRegion } env.lock.Lock() defer env.lock.Unlock() return &simplestreams.MetadataLookupParams{ Region: region, Endpoint: gosigma.ResolveEndpoint(region), Architectures: arch.AllSupportedArches, Series: config.PreferredSeries(env.ecfg), }, nil }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } inner := coretesting.Context(c) ctx := modelcmd.BootstrapContext(inner) result, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), }, }, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Assert(result.Series, gc.Equals, config.PreferredSeries(mocksConfig)) output := inner.Stderr.(*bytes.Buffer) lines := strings.Split(output.String(), "\n") c.Assert(len(lines), jc.GreaterThan, 1) c.Assert(lines[0], gc.Equals, "Some message") }
// MetadataLookupParams returns parameters which are used to query simplestreams metadata. func (e *Environ) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) { if region == "" { region = e.cloud.Region } cloudSpec, err := e.cloudSpec(region) if err != nil { return nil, err } return &simplestreams.MetadataLookupParams{ Series: config.PreferredSeries(e.ecfg()), Region: cloudSpec.Region, Endpoint: cloudSpec.Endpoint, }, nil }
func (s *bootstrapSuite) TestEnsureToolsAvailability(c *gc.C) { existingToolsVersion := version.MustParseBinary("1.19.0-trusty-amd64") s.PatchValue(&version.Current, existingToolsVersion) env := newEnviron("foo", useDefaultKeys, nil) s.setDummyStorage(c, env) // 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" agentTools, err := bootstrap.EnsureToolsAvailability(coretesting.Context(c), env, config.PreferredSeries(env.Config()), &arch) c.Assert(err, gc.IsNil) c.Assert(agentTools, gc.HasLen, 1) expectedVers := version.Current expectedVers.Number.Build++ expectedVers.Series = config.PreferredSeries(env.Config()) c.Assert(agentTools[0].Version, gc.DeepEquals, expectedVers) }
func (s *BootstrapSuite) TestBootstrapTwice(c *gc.C) { env := resetJujuHome(c, "devenv") defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", "devenv") c.Assert(err, jc.ErrorIsNil) _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", "devenv") c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") }
func (env *environ) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) { if region == "" { region = gosigma.DefaultRegion } cloudSpec, err := env.cloudSpec(region) if err != nil { return nil, err } return &simplestreams.MetadataLookupParams{ Region: cloudSpec.Region, Endpoint: cloudSpec.Endpoint, Architectures: arch.AllSupportedArches, Series: config.PreferredSeries(env.ecfg), }, nil }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { s.PatchValue(&version.Current, coretesting.FakeVersionNumber) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } ctx := envtesting.BootstrapContext(c) arch, series, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: version.Current, Arch: arch.HostArch(), Series: series.HostSeries(), }, }, }, }) c.Assert(err, jc.ErrorIsNil) c.Assert(arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Assert(series, gc.Equals, config.PreferredSeries(mocksConfig)) }
func (s *serverSuite) TestModelInfo(c *gc.C) { model, err := s.State.Model() c.Assert(err, jc.ErrorIsNil) conf, _ := s.State.ModelConfig() info, err := s.client.ModelInfo() c.Assert(err, jc.ErrorIsNil) c.Assert(info.DefaultSeries, gc.Equals, config.PreferredSeries(conf)) c.Assert(info.CloudRegion, gc.Equals, model.CloudRegion()) c.Assert(info.ProviderType, gc.Equals, conf.Type()) c.Assert(info.Name, gc.Equals, conf.Name()) c.Assert(info.UUID, gc.Equals, model.UUID()) c.Assert(info.OwnerTag, gc.Equals, model.Owner().String()) c.Assert(info.Life, gc.Equals, params.Alive) // The controller UUID is not returned by the ModelInfo endpoint on the // Client facade. c.Assert(info.ControllerUUID, gc.Equals, "") }
func (s *SetEnvironmentSuite) TestChangeDefaultSeries(c *gc.C) { // default-series not set stateConfig, err := s.State.EnvironConfig() c.Assert(err, gc.IsNil) series, ok := stateConfig.DefaultSeries() c.Assert(ok, gc.Equals, true) c.Assert(series, gc.Equals, "precise") // default-series set in RepoSuite.SetUpTest _, err = testing.RunCommand(c, envcmd.Wrap(&SetEnvironmentCommand{}), "default-series=raring") c.Assert(err, gc.IsNil) stateConfig, err = s.State.EnvironConfig() c.Assert(err, gc.IsNil) series, ok = stateConfig.DefaultSeries() c.Assert(ok, gc.Equals, true) c.Assert(series, gc.Equals, "raring") c.Assert(config.PreferredSeries(stateConfig), gc.Equals, "raring") }
// StartInstanceWithParams is a test helper function that starts an instance // with the given parameters, and a plausible but invalid configuration, and // returns the result of Environ.StartInstance. The provided params's // MachineConfig and Tools field values will be ignored. func StartInstanceWithParams( env environs.Environ, machineId string, params environs.StartInstanceParams, networks []string, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { series := config.PreferredSeries(env.Config()) agentVersion, ok := env.Config().AgentVersion() if !ok { return nil, nil, nil, fmt.Errorf("missing agent version in environment config") } filter := coretools.Filter{ Number: agentVersion, Series: series, } if params.Constraints.Arch != nil { filter.Arch = *params.Constraints.Arch } possibleTools, err := tools.FindTools( env, -1, -1, filter, tools.DoNotAllowRetry, ) if err != nil { return nil, nil, nil, err } machineNonce := "fake_nonce" stateInfo := FakeStateInfo(machineId) apiInfo := FakeAPIInfo(machineId) machineConfig, err := environs.NewMachineConfig( machineId, machineNonce, imagemetadata.ReleasedStream, series, networks, stateInfo, apiInfo, ) if err != nil { return nil, nil, nil, err } params.Tools = possibleTools params.MachineConfig = machineConfig return env.StartInstance(params) }
// EnvironmentInfo returns information about the current environment (default // series and type). func (c *Client) EnvironmentInfo() (api.EnvironmentInfo, error) { state := c.api.state conf, err := state.EnvironConfig() if err != nil { return api.EnvironmentInfo{}, err } env, err := state.Environment() if err != nil { return api.EnvironmentInfo{}, err } info := api.EnvironmentInfo{ DefaultSeries: config.PreferredSeries(conf), ProviderType: conf.Type(), Name: conf.Name(), UUID: env.UUID(), } return info, nil }
// StartInstanceWithParams is a test helper function that starts an instance // with the given parameters, and a plausible but invalid configuration, and // returns the result of Environ.StartInstance. The provided params's // InstanceConfig and Tools field values will be ignored. func StartInstanceWithParams( env environs.Environ, machineId string, params environs.StartInstanceParams, networks []string, ) ( *environs.StartInstanceResult, error, ) { series := config.PreferredSeries(env.Config()) agentVersion, ok := env.Config().AgentVersion() if !ok { return nil, errors.New("missing agent version in environment config") } filter := coretools.Filter{ Number: agentVersion, Series: series, } if params.Constraints.Arch != nil { filter.Arch = *params.Constraints.Arch } possibleTools, err := tools.FindTools(env, -1, -1, filter) if err != nil { return nil, errors.Trace(err) } machineNonce := "fake_nonce" stateInfo := FakeStateInfo(machineId) apiInfo := FakeAPIInfo(machineId) instanceConfig, err := instancecfg.NewInstanceConfig( machineId, machineNonce, imagemetadata.ReleasedStream, series, true, networks, stateInfo, apiInfo, ) if err != nil { return nil, errors.Trace(err) } params.Tools = possibleTools params.InstanceConfig = instanceConfig return env.StartInstance(params) }
func (api *API) parseMetadataFromParams(p params.CloudImageMetadata, env environs.Environ) (cloudimagemetadata.Metadata, error) { result := cloudimagemetadata.Metadata{ cloudimagemetadata.MetadataAttributes{ Stream: p.Stream, Region: p.Region, Version: p.Version, Series: p.Series, Arch: p.Arch, VirtType: p.VirtType, RootStorageType: p.RootStorageType, RootStorageSize: p.RootStorageSize, Source: p.Source, }, p.Priority, p.ImageId, } // Fill in any required default values. if p.Stream == "" { result.Stream = env.Config().ImageStream() } if p.Source == "" { result.Source = "custom" } if result.Arch == "" { result.Arch = "amd64" } if result.Series == "" { result.Series = config.PreferredSeries(env.Config()) } if result.Region == "" { // If the env supports regions, use the env default. if r, ok := env.(simplestreams.HasRegion); ok { spec, err := r.Region() if err != nil { return cloudimagemetadata.Metadata{}, errors.Annotatef(err, "getting cloud region") } result.Region = spec.Region } } return result, nil }
// ModelInfo returns information about the current model (default // series and type). func (c *Client) ModelInfo() (params.ModelInfo, error) { state := c.api.stateAccessor conf, err := state.ModelConfig() if err != nil { return params.ModelInfo{}, err } env, err := state.Model() if err != nil { return params.ModelInfo{}, err } info := params.ModelInfo{ DefaultSeries: config.PreferredSeries(conf), ProviderType: conf.Type(), Name: conf.Name(), UUID: env.UUID(), ControllerUUID: env.ControllerUUID(), } return info, nil }
func (s *bootstrapSuite) TestSeriesToUpload(c *gc.C) { vers := version.Current vers.Series = "quantal" s.PatchValue(&version.Current, vers) env := newEnviron("foo", useDefaultKeys, nil) cfg := env.Config() prefSeries := config.PreferredSeries(cfg) expect := []string{"quantal", prefSeries} for _, series := range []string{"precise", "trusty"} { if prefSeries != series { expect = append(expect, series) } } c.Assert(bootstrap.SeriesToUpload(cfg, nil), jc.SameContents, expect) c.Assert(bootstrap.SeriesToUpload(cfg, []string{"quantal"}), jc.SameContents, []string{"quantal"}) env = newEnviron("foo", useDefaultKeys, map[string]interface{}{"default-series": "lucid"}) cfg = env.Config() c.Assert(bootstrap.SeriesToUpload(cfg, nil), jc.SameContents, []string{"quantal", "precise", "trusty", "lucid"}) }