// Bootstrap bootstraps the given environment. The supplied constraints are // used to provision the instance, and are also set within the bootstrapped // environment. func Bootstrap(ctx environs.BootstrapContext, environ environs.Environ, args environs.BootstrapParams) error { cfg := environ.Config() network.InitializeFromConfig(cfg) if secret := cfg.AdminSecret(); secret == "" { return fmt.Errorf("environment configuration has no admin-secret") } if authKeys := ssh.SplitAuthorisedKeys(cfg.AuthorizedKeys()); len(authKeys) == 0 { // Apparently this can never happen, so it's not tested. But, one day, // Config will act differently (it's pretty crazy that, AFAICT, the // authorized-keys are optional config settings... but it's impossible // to actually *create* a config without them)... and when it does, // we'll be here to catch this problem early. return fmt.Errorf("environment configuration has no authorized-keys") } if _, hasCACert := cfg.CACert(); !hasCACert { return fmt.Errorf("environment configuration has no ca-cert") } if _, hasCAKey := cfg.CAPrivateKey(); !hasCAKey { return fmt.Errorf("environment configuration has no ca-private-key") } // Write out the bootstrap-init file, and confirm storage is writeable. if err := environs.VerifyStorage(environ.Storage()); err != nil { return err } logger.Debugf("environment %q supports service/machine networks: %v", environ.Name(), environ.SupportNetworks()) logger.Infof("bootstrapping environment %q", environ.Name()) return environ.Bootstrap(ctx, args) }
func assertEnvironDestroyed(c *gc.C, env environs.Environ, store configstore.Storage) { _, err := store.ReadInfo(env.Name()) c.Assert(err, jc.Satisfies, errors.IsNotFound) _, err = env.Instances([]instance.Id{"invalid"}) c.Assert(err, gc.ErrorMatches, "environment has been destroyed") }
// validateUploadAllowed returns an error if an attempt to upload tools should // not be allowed. func validateUploadAllowed(env environs.Environ, toolsArch *string, forceVersion bool) error { if !forceVersion { // First, check that there isn't already an agent version specified. if _, hasAgentVersion := env.Config().AgentVersion(); hasAgentVersion { return fmt.Errorf(noToolsNoUploadMessage) } } // Now check that the architecture for which we are setting up an // environment matches that from which we are bootstrapping. hostArch := arch.HostArch() // We can't build tools for a different architecture if one is specified. if toolsArch != nil && *toolsArch != hostArch { return fmt.Errorf("cannot build tools for %q using a machine running on %q", *toolsArch, hostArch) } // If no architecture is specified, ensure the target provider supports instances matching our architecture. supportedArchitectures, err := env.SupportedArchitectures() if err != nil { return fmt.Errorf( "no packaged tools available and cannot determine environment's supported architectures: %v", err) } archSupported := false for _, arch := range supportedArchitectures { if hostArch == arch { archSupported = true break } } if !archSupported { envType := env.Config().Type() return fmt.Errorf( "environment %q of type %s does not support instances running on %q", env.Name(), envType, hostArch) } return nil }
func assertEnvironNotDestroyed(c *gc.C, env environs.Environ, store configstore.Storage) { info, err := store.ReadInfo(env.Name()) c.Assert(err, gc.IsNil) c.Assert(info.Initialized(), jc.IsTrue) _, err = environs.NewFromName(env.Name(), store) c.Assert(err, gc.IsNil) }
// Destroy is a common implementation of the Destroy method defined on // environs.Environ; we strongly recommend that this implementation be // used when writing a new provider. func Destroy(env environs.Environ) error { logger.Infof("destroying environment %q", env.Name()) instances, err := env.AllInstances() switch err { case nil: ids := make([]instance.Id, len(instances)) for i, inst := range instances { ids[i] = inst.Id() } if err := env.StopInstances(ids...); err != nil { return err } fallthrough case environs.ErrNoInstances: return env.Storage().RemoveAll() } return err }
// 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 store, err := configstore.Default(); err == nil { if environ, err = c.prepare(context, store); err == nil { logger.Infof("creating image metadata for environment %q", environ.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 fmt.Errorf("environment %q cannot provide region and endpoint", environ.Name()) } // If only one of region or endpoint is provided, that is a problem. if cloudSpec.Region != cloudSpec.Endpoint && (cloudSpec.Region == "" || cloudSpec.Endpoint == "") { return fmt.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) } if v, ok := cfg.AllAttrs()["control-bucket"]; ok { c.privateStorage = v.(string) } } else { logger.Warningf("environment could not be opened: %v", err) } } if environ == nil { logger.Infof("no environment found, creating image metadata using user supplied data") } if c.Series == "" { c.Series = config.LatestLtsSeries() } if c.ImageId == "" { return fmt.Errorf("image id must be specified") } if c.Region == "" { return fmt.Errorf("image region must be specified") } if c.Endpoint == "" { return fmt.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 }