func (suite) TestBootstrapConfig(c *C) { defer makeFakeHome(c, "bladaam").restore() cfg, err := config.New(map[string]interface{}{ "name": "bladaam", "type": "dummy", "state-server": false, "admin-secret": "highly", "secret": "um", "authorized-keys": "i-am-a-key", "ca-cert": testing.CACert, "ca-private-key": testing.CAKey, }) c.Assert(err, IsNil) provider, err := environs.Provider(cfg.Type()) c.Assert(err, IsNil) tools := &state.Tools{ URL: "http://x", Binary: version.MustParseBinary("1.2.3-foo-bar"), } cfg1, err := environs.BootstrapConfig(provider, cfg, tools) c.Assert(err, IsNil) expect := cfg.AllAttrs() delete(expect, "secret") expect["admin-secret"] = "" expect["ca-private-key"] = "" expect["agent-version"] = "1.2.3" c.Assert(cfg1.AllAttrs(), DeepEquals, expect) }
func (e *environ) Bootstrap(cons constraints.Value) error { defer delay() if err := e.checkBroken("Bootstrap"); err != nil { return err } password := e.Config().AdminSecret() if password == "" { return fmt.Errorf("admin-secret is required for bootstrap") } if _, ok := e.Config().CACert(); !ok { return fmt.Errorf("no CA certificate in environment configuration") } possibleTools, err := environs.FindBootstrapTools(e, cons) if err != nil { return err } log.Infof("environs/dummy: would pick tools from %s", possibleTools) cfg, err := environs.BootstrapConfig(e.Config()) if err != nil { return fmt.Errorf("cannot make bootstrap config: %v", err) } e.state.mu.Lock() defer e.state.mu.Unlock() if e.state.bootstrapped { return fmt.Errorf("environment is already bootstrapped") } if e.ecfg().stateServer() { // TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go // so that we can call it here. info := stateInfo() st, err := state.Initialize(info, cfg, state.DefaultDialOpts()) if err != nil { panic(err) } if err := st.SetEnvironConstraints(cons); err != nil { panic(err) } if err := st.SetAdminMongoPassword(utils.PasswordHash(password)); err != nil { panic(err) } _, err = st.AddUser("admin", password) if err != nil { panic(err) } e.state.apiServer, err = apiserver.NewServer(st, "localhost:0", []byte(testing.ServerCert), []byte(testing.ServerKey)) if err != nil { panic(err) } e.state.apiState = st } e.state.bootstrapped = true e.state.ops <- OpBootstrap{Env: e.state.name, Constraints: cons} return nil }
func (e *environ) Bootstrap(uploadTools bool, cert, key []byte) error { defer delay() if err := e.checkBroken("Bootstrap"); err != nil { return err } password := e.Config().AdminSecret() if password == "" { return fmt.Errorf("admin-secret is required for bootstrap") } if _, ok := e.Config().CACert(); !ok { return fmt.Errorf("no CA certificate in environment configuration") } var tools *state.Tools var err error if uploadTools { tools, err = environs.PutTools(e.Storage(), nil) if err != nil { return err } } else { flags := environs.HighestVersion | environs.CompatVersion tools, err = environs.FindTools(e, version.Current, flags) if err != nil { return err } } e.state.mu.Lock() defer e.state.mu.Unlock() e.state.ops <- OpBootstrap{Env: e.state.name} if e.state.bootstrapped { return fmt.Errorf("environment is already bootstrapped") } if e.ecfg().stateServer() { info := stateInfo() cfg, err := environs.BootstrapConfig(&providerInstance, e.ecfg().Config, tools) if err != nil { return fmt.Errorf("cannot make bootstrap config: %v", err) } st, err := state.Initialize(info, cfg) if err != nil { panic(err) } if err := st.SetAdminMongoPassword(trivial.PasswordHash(password)); err != nil { return err } if err := st.Close(); err != nil { panic(err) } } e.state.bootstrapped = true return nil }
func (env *localEnviron) initialStateConfiguration(addr string, cons constraints.Value) (*state.State, error) { // We don't check the existance of the CACert here as if it wasn't set, we // wouldn't get this far. cfg := env.config.Config caCert, _ := cfg.CACert() addr = fmt.Sprintf("%s:%d", addr, cfg.StatePort()) info := &state.Info{ Addrs: []string{addr}, CACert: caCert, } timeout := state.DialOpts{60 * time.Second} bootstrap, err := environs.BootstrapConfig(cfg) if err != nil { return nil, err } st, err := state.Initialize(info, bootstrap, timeout) if err != nil { logger.Errorf("failed to initialize state: %v", err) return nil, err } logger.Debugf("state initialized") passwordHash := utils.PasswordHash(cfg.AdminSecret()) if err := environs.BootstrapUsers(st, cfg, passwordHash); err != nil { st.Close() return nil, err } jobs := []state.MachineJob{state.JobManageEnviron, state.JobManageState} if err := environs.ConfigureBootstrapMachine( st, cons, env.config.rootDir(), jobs, instance.Id(boostrapInstanceId), instance.HardwareCharacteristics{}); err != nil { st.Close() return nil, err } // Return an open state reference. return st, nil }
func (suite) TestBootstrapConfig(c *C) { defer testing.MakeFakeHomeNoEnvironments(c, "bladaam").Restore() cfg, err := config.New(map[string]interface{}{ "name": "bladaam", "type": "dummy", "state-server": false, "admin-secret": "highly", "secret": "um", "authorized-keys": "i-am-a-key", "ca-cert": testing.CACert, "ca-private-key": testing.CAKey, "agent-version": "1.2.3", }) c.Assert(err, IsNil) cfg1, err := environs.BootstrapConfig(cfg) c.Assert(err, IsNil) expect := cfg.AllAttrs() delete(expect, "secret") expect["admin-secret"] = "" expect["ca-private-key"] = "" c.Assert(cfg1.AllAttrs(), DeepEquals, expect) }
func (e *environ) Bootstrap(uploadTools bool, cert, key []byte) error { password := e.Config().AdminSecret() if password == "" { return fmt.Errorf("admin-secret is required for bootstrap") } log.Printf("environs/ec2: bootstrapping environment %q", e.name) // If the state file exists, it might actually have just been // removed by Destroy, and eventual consistency has not caught // up yet, so we retry to verify if that is happening. var err error for a := shortAttempt.Start(); a.Next(); { _, err = e.loadState() if err != nil { break } } if err == nil { return fmt.Errorf("environment is already bootstrapped") } if _, notFound := err.(*environs.NotFoundError); !notFound { return fmt.Errorf("cannot query old bootstrap state: %v", err) } var tools *state.Tools if uploadTools { tools, err = environs.PutTools(e.Storage(), nil) if err != nil { return fmt.Errorf("cannot upload tools: %v", err) } } else { flags := environs.HighestVersion | environs.CompatVersion v := version.Current v.Series = e.Config().DefaultSeries() tools, err = environs.FindTools(e, v, flags) if err != nil { return fmt.Errorf("cannot find tools: %v", err) } } config, err := environs.BootstrapConfig(providerInstance, e.Config(), tools) if err != nil { return fmt.Errorf("unable to determine inital configuration: %v", err) } caCert, hasCert := e.Config().CACert() if !hasCert { return fmt.Errorf("no CA certificate in environment configuration") } info := &state.Info{ Password: trivial.PasswordHash(password), CACert: caCert, } inst, err := e.startInstance(&startInstanceParams{ machineId: "0", info: info, tools: tools, stateServer: true, config: config, stateServerCert: cert, stateServerKey: key, }) if err != nil { return fmt.Errorf("cannot start bootstrap instance: %v", err) } err = e.saveState(&bootstrapState{ StateInstances: []state.InstanceId{inst.Id()}, }) if err != nil { // ignore error on StopInstance because the previous error is // more important. e.StopInstances([]environs.Instance{inst}) return fmt.Errorf("cannot save state: %v", err) } // TODO make safe in the case of racing Bootstraps // If two Bootstraps are called concurrently, there's // no way to use S3 to make sure that only one succeeds. // Perhaps consider using SimpleDB for state storage // which would enable that possibility. return nil }