// Config returns the configuration for the environment; obtaining bootstrap // information from the API if necessary. If callers already have an active // client API connection, it will be used. Otherwise, a new API connection will // be used if necessary. func (c *ModelCommandBase) Config(store configstore.Storage, client ModelGetter) (*config.Config, error) { if c.modelName == "" { return nil, errors.Trace(ErrNoModelSpecified) } cfg, _, err := environs.ConfigForName(c.modelName, store) if err == nil { return cfg, nil } else if !environs.IsEmptyConfig(err) { return nil, errors.Trace(err) } if client == nil { client, err = c.NewModelGetter() if err != nil { return nil, errors.Trace(err) } defer client.Close() } bootstrapCfg, err := client.ModelGet() if err != nil { return nil, errors.Trace(err) } return config.New(config.NoDefaults, bootstrapCfg) }
func (*OpenSuite) TestConfigForNameDefault(c *gc.C) { testing.WriteEnvironments(c, testing.SingleEnvConfig) cfg, source, err := environs.ConfigForName("", configstore.NewMem()) c.Assert(err, gc.IsNil) c.Assert(cfg.Name(), gc.Equals, "erewhemos") c.Assert(source, gc.Equals, environs.ConfigFromEnvirons) }
func (c *EnvCommandBase) Config(store configstore.Storage) (*config.Config, error) { if c.envName == "" { return nil, errors.Trace(ErrNoEnvironmentSpecified) } cfg, _, err := environs.ConfigForName(c.envName, store) return cfg, err }
func (*OpenSuite) TestConfigForNameFromInfo(c *gc.C) { testing.WriteEnvironments(c, testing.SingleEnvConfig) store := configstore.NewMem() cfg, source, err := environs.ConfigForName("", store) c.Assert(err, gc.IsNil) c.Assert(source, gc.Equals, environs.ConfigFromEnvirons) info := store.CreateInfo("test-config") var attrs testing.Attrs = cfg.AllAttrs() attrs = attrs.Merge(testing.Attrs{ "name": "test-config", }) info.SetBootstrapConfig(attrs) err = info.Write() c.Assert(err, gc.IsNil) cfg, source, err = environs.ConfigForName("test-config", store) c.Assert(err, gc.IsNil) c.Assert(source, gc.Equals, environs.ConfigFromInfo) c.Assert(testing.Attrs(cfg.AllAttrs()), gc.DeepEquals, attrs) }
func (*OpenSuite) TestNewFromNameWithInvalidInfo(c *gc.C) { store := configstore.NewMem() cfg, _, err := environs.ConfigForName("erewhemos", store) c.Assert(err, gc.IsNil) info := store.CreateInfo("erewhemos") // The configuration from environments.yaml is invalid // because it doesn't contain the state-id attribute which // the dummy environment adds at Prepare time. info.SetBootstrapConfig(cfg.AllAttrs()) err = info.Write() c.Assert(err, gc.IsNil) e, err := environs.NewFromName("erewhemos", store) c.Assert(err, gc.ErrorMatches, "environment is not prepared") c.Assert(e, gc.IsNil) }
func (*OpenSuite) TestConfigForNameNoDefault(c *gc.C) { cfg, source, err := environs.ConfigForName("", configstore.NewMem()) c.Assert(err, gc.ErrorMatches, "no default environment found") c.Assert(cfg, gc.IsNil) c.Assert(source, gc.Equals, environs.ConfigFromEnvirons) }
func (*OpenSuite) TestConfigForName(c *gc.C) { cfg, source, err := environs.ConfigForName("erewhemos", configstore.NewMem()) c.Assert(err, gc.IsNil) c.Assert(source, gc.Equals, environs.ConfigFromEnvirons) c.Assert(cfg.Name(), gc.Equals, "erewhemos") }
} if strings.Contains(err.Error(), apiserver.UpgradeInProgressError.Error()) { ctx.Infof("Waiting for API to become available") continue } return err } return err } var environType = func(envName string) (string, error) { store, err := configstore.Default() if err != nil { return "", errors.Trace(err) } cfg, _, err := environs.ConfigForName(envName, store) if err != nil { return "", errors.Trace(err) } return cfg.Type(), nil } // checkProviderType ensures the provider type is okay. func checkProviderType(envName string) error { envType, err := environType(envName) if err != nil { return errors.Trace(err) } featureflag.SetFlagsFromEnvironment(osenv.JujuFeatureFlagEnvKey) flag, ok := provisionalProviders[envType]
func (c *EnvCommandBase) Config(store configstore.Storage) (*config.Config, error) { cfg, _, err := environs.ConfigForName(c.envName, store) return cfg, err }
func (c *restoreCommand) Run(ctx *cmd.Context) error { if c.showDescription { fmt.Fprintf(ctx.Stdout, "%s\n", c.Info().Purpose) return nil } if err := c.Log.Start(ctx); err != nil { return err } agentConf, err := extractConfig(c.backupFile) if err != nil { return fmt.Errorf("cannot extract configuration from backup file: %v", err) } progress("extracted credentials from backup file") store, err := configstore.Default() if err != nil { return err } cfg, _, err := environs.ConfigForName(c.EnvName, store) if err != nil { return err } env, err := rebootstrap(cfg, ctx, c.Constraints) if err != nil { return fmt.Errorf("cannot re-bootstrap environment: %v", err) } progress("connecting to newly bootstrapped instance") var conn *juju.APIConn // The state server backend may not be ready to accept logins so we retry. // We'll do up to 8 retries over 2 minutes to give the server time to come up. // Typically we expect only 1 retry will be needed. attempt := utils.AttemptStrategy{Delay: 15 * time.Second, Min: 8} for a := attempt.Start(); a.Next(); { conn, err = juju.NewAPIConn(env, api.DefaultDialOpts()) if err == nil || errors.Cause(err).Error() != "EOF" { break } progress("bootstrapped instance not ready - attempting to redial") } if err != nil { return fmt.Errorf("cannot connect to bootstrap instance: %v", err) } progress("restoring bootstrap machine") newInstId, machine0Addr, err := restoreBootstrapMachine(conn, c.backupFile, agentConf) if err != nil { return fmt.Errorf("cannot restore bootstrap machine: %v", err) } progress("restored bootstrap machine") // Update the environ state to point to the new instance. if err := bootstrap.SaveState(env.Storage(), &bootstrap.BootstrapState{ StateInstances: []instance.Id{newInstId}, }); err != nil { return fmt.Errorf("cannot update environ bootstrap state storage: %v", err) } // Construct our own state info rather than using juju.NewConn so // that we can avoid storage eventual-consistency issues // (and it's faster too). caCert, ok := cfg.CACert() if !ok { return fmt.Errorf("configuration has no CA certificate") } progress("opening state") // We need to retry here to allow mongo to come up on the restored state server. // The connection might succeed due to the mongo dial retries but there may still // be a problem issuing database commands. var st *state.State for a := attempt.Start(); a.Next(); { st, err = state.Open(&state.Info{ Info: mongo.Info{ Addrs: []string{fmt.Sprintf("%s:%d", machine0Addr, cfg.StatePort())}, CACert: caCert, }, Tag: agentConf.Credentials.Tag, Password: agentConf.Credentials.Password, }, mongo.DefaultDialOpts(), environs.NewStatePolicy()) if err == nil { break } progress("state server not ready - attempting to re-connect") } if err != nil { return fmt.Errorf("cannot open state: %v", err) } progress("updating all machines") if err := updateAllMachines(st, machine0Addr); err != nil { return fmt.Errorf("cannot update machines: %v", err) } return nil }
func (c *restoreCommand) Run(ctx *cmd.Context) error { if c.showDescription { fmt.Fprintf(ctx.Stdout, "%s\n", c.Info().Purpose) return nil } if err := c.Log.Start(ctx); err != nil { return err } agentConf, err := extractConfig(c.backupFile) if err != nil { return fmt.Errorf("cannot extract configuration from backup file: %v", err) } progress("extracted credentials from backup file") store, err := configstore.Default() if err != nil { return err } cfg, _, err := environs.ConfigForName(c.EnvName, store) if err != nil { return err } env, err := rebootstrap(cfg, ctx, c.Constraints) if err != nil { return fmt.Errorf("cannot re-bootstrap environment: %v", err) } progress("connecting to newly bootstrapped instance") conn, err := juju.NewAPIConn(env, api.DefaultDialOpts()) if err != nil { return fmt.Errorf("cannot connect to bootstrap instance: %v", err) } progress("restoring bootstrap machine") newInstId, machine0Addr, err := restoreBootstrapMachine(conn, c.backupFile, agentConf) if err != nil { return fmt.Errorf("cannot restore bootstrap machine: %v", err) } progress("restored bootstrap machine") // Update the environ state to point to the new instance. if err := bootstrap.SaveState(env.Storage(), &bootstrap.BootstrapState{ StateInstances: []instance.Id{newInstId}, }); err != nil { return fmt.Errorf("cannot update environ bootstrap state storage: %v", err) } // Construct our own state info rather than using juju.NewConn so // that we can avoid storage eventual-consistency issues // (and it's faster too). caCert, ok := cfg.CACert() if !ok { return fmt.Errorf("configuration has no CA certificate") } progress("opening state") st, err := state.Open(&state.Info{ Info: mongo.Info{ Addrs: []string{fmt.Sprintf("%s:%d", machine0Addr, cfg.StatePort())}, CACert: caCert, }, Tag: agentConf.Credentials.Tag, Password: agentConf.Credentials.Password, }, mongo.DefaultDialOpts(), environs.NewStatePolicy()) if err != nil { return fmt.Errorf("cannot open state: %v", err) } progress("updating all machines") if err := updateAllMachines(st, machine0Addr); err != nil { return fmt.Errorf("cannot update machines: %v", err) } return nil }