func (*suite) TestBootstrapConfig(c *gc.C) { attrs := dummySampleConfig().Merge(testing.Attrs{ "agent-version": "1.2.3", }) c.Assert(inMap(attrs, "secret"), jc.IsTrue) c.Assert(inMap(attrs, "ca-private-key"), jc.IsTrue) c.Assert(inMap(attrs, "admin-secret"), jc.IsTrue) cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, jc.ErrorIsNil) c.Assert(err, jc.ErrorIsNil) cfg1, err := environs.BootstrapConfig(cfg) c.Assert(err, jc.ErrorIsNil) expect := cfg.AllAttrs() expect["admin-secret"] = "" expect["ca-private-key"] = "" c.Assert(cfg1.AllAttrs(), gc.DeepEquals, expect) }
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) error { selectedTools, err := common.EnsureBootstrapTools(ctx, e, config.PreferredSeries(e.Config()), args.Constraints.Arch) if err != nil { return err } series := selectedTools.OneSeries() defer delay() if err := e.checkBroken("Bootstrap"); err != nil { return err } network.InitializeFromConfig(e.Config()) 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") } logger.Infof("would pick tools from %s", selectedTools) cfg, err := environs.BootstrapConfig(e.Config()) if err != nil { return fmt.Errorf("cannot make bootstrap config: %v", err) } estate, err := e.state() if err != nil { return err } estate.mu.Lock() defer estate.mu.Unlock() if estate.bootstrapped { return fmt.Errorf("environment is already bootstrapped") } estate.preferIPv6 = e.Config().PreferIPv6() // Write the bootstrap file just like a normal provider. However // we need to release the mutex for the save state to work, so regain // it after the call. estate.mu.Unlock() instIds := []instance.Id{BootstrapInstanceId} if err := bootstrap.SaveState(e.Storage(), &bootstrap.BootstrapState{StateInstances: instIds}); err != nil { logger.Errorf("failed to save state instances: %v", err) estate.mu.Lock() // otherwise defered unlock will fail return err } estate.mu.Lock() // back at it // Create an instance for the bootstrap node. logger.Infof("creating bootstrap instance") i := &dummyInstance{ id: BootstrapInstanceId, addresses: network.NewAddresses("localhost"), ports: make(map[network.Port]bool), machineId: agent.BootstrapMachineId, series: series, firewallMode: e.Config().FirewallMode(), state: estate, stateServer: true, } estate.insts[i.id] = i if e.ecfg().stateServer() { // TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go // so that we can call it here. info := stateInfo(estate.preferIPv6) st, err := state.Initialize(info, cfg, mongo.DefaultDialOpts(), estate.statePolicy) if err != nil { panic(err) } if err := st.SetEnvironConstraints(args.Constraints); err != nil { panic(err) } if err := st.SetAdminMongoPassword(utils.UserPasswordHash(password, utils.CompatSalt)); err != nil { panic(err) } _, err = st.AddAdminUser(password) if err != nil { panic(err) } estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{ Cert: []byte(testing.ServerCert), Key: []byte(testing.ServerKey), DataDir: DataDir, LogDir: LogDir, }) if err != nil { panic(err) } estate.apiState = st } estate.bootstrapped = true estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args} return nil }
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) { series = config.PreferredSeries(e.Config()) availableTools, err := args.AvailableTools.Match(coretools.Filter{Series: series}) if err != nil { return "", "", nil, err } arch = availableTools.Arches()[0] defer delay() if err := e.checkBroken("Bootstrap"); err != nil { return "", "", nil, err } network.InitializeFromConfig(e.Config()) password := e.Config().AdminSecret() if password == "" { return "", "", nil, fmt.Errorf("admin-secret is required for bootstrap") } if _, ok := e.Config().CACert(); !ok { return "", "", nil, fmt.Errorf("no CA certificate in environment configuration") } logger.Infof("would pick tools from %s", availableTools) cfg, err := environs.BootstrapConfig(e.Config()) if err != nil { return "", "", nil, fmt.Errorf("cannot make bootstrap config: %v", err) } estate, err := e.state() if err != nil { return "", "", nil, err } estate.mu.Lock() defer estate.mu.Unlock() if estate.bootstrapped { return "", "", nil, fmt.Errorf("environment is already bootstrapped") } estate.preferIPv6 = e.Config().PreferIPv6() // Create an instance for the bootstrap node. logger.Infof("creating bootstrap instance") i := &dummyInstance{ id: BootstrapInstanceId, addresses: network.NewAddresses("localhost"), ports: make(map[network.PortRange]bool), machineId: agent.BootstrapMachineId, series: series, firewallMode: e.Config().FirewallMode(), state: estate, stateServer: true, } estate.insts[i.id] = i if e.ecfg().stateServer() { // TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go // so that we can call it here. info := stateInfo(estate.preferIPv6) // Since the admin user isn't setup until after here, // the password in the info structure is empty, so the admin // user is constructed with an empty password here. // It is set just below. st, err := state.Initialize( AdminUserTag(), info, cfg, mongo.DefaultDialOpts(), estate.statePolicy) if err != nil { panic(err) } if err := st.SetEnvironConstraints(args.Constraints); err != nil { panic(err) } if err := st.SetAdminMongoPassword(password); err != nil { panic(err) } if err := st.MongoSession().DB("admin").Login("admin", password); err != nil { panic(err) } env, err := st.Environment() if err != nil { panic(err) } owner, err := st.User(env.Owner()) if err != nil { panic(err) } // We log this out for test purposes only. No one in real life can use // a dummy provider for anything other than testing, so logging the password // here is fine. logger.Debugf("setting password for %q to %q", owner.Name(), password) owner.SetPassword(password) estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{ Cert: []byte(testing.ServerCert), Key: []byte(testing.ServerKey), Tag: names.NewMachineTag("0"), DataDir: DataDir, LogDir: LogDir, }) if err != nil { panic(err) } estate.apiState = st } estate.bootstrapped = true estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args} finalize := func(ctx environs.BootstrapContext, icfg *instancecfg.InstanceConfig) error { estate.ops <- OpFinalizeBootstrap{Context: ctx, Env: e.name, InstanceConfig: icfg} return nil } return arch, series, finalize, nil }
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) { series = config.PreferredSeries(e.Config()) availableTools, err := args.AvailableTools.Match(coretools.Filter{Series: series}) if err != nil { return "", "", nil, err } arch = availableTools.Arches()[0] defer delay() if err := e.checkBroken("Bootstrap"); err != nil { return "", "", nil, err } network.InitializeFromConfig(e.Config()) password := e.Config().AdminSecret() if password == "" { return "", "", nil, fmt.Errorf("admin-secret is required for bootstrap") } if _, ok := e.Config().CACert(); !ok { return "", "", nil, fmt.Errorf("no CA certificate in environment configuration") } logger.Infof("would pick tools from %s", availableTools) cfg, err := environs.BootstrapConfig(e.Config()) if err != nil { return "", "", nil, fmt.Errorf("cannot make bootstrap config: %v", err) } estate, err := e.state() if err != nil { return "", "", nil, err } estate.mu.Lock() defer estate.mu.Unlock() if estate.bootstrapped { return "", "", nil, fmt.Errorf("environment is already bootstrapped") } estate.preferIPv6 = e.Config().PreferIPv6() // Create an instance for the bootstrap node. logger.Infof("creating bootstrap instance") i := &dummyInstance{ id: BootstrapInstanceId, addresses: network.NewAddresses("localhost"), ports: make(map[network.PortRange]bool), machineId: agent.BootstrapMachineId, series: series, firewallMode: e.Config().FirewallMode(), state: estate, stateServer: true, } estate.insts[i.id] = i if e.ecfg().stateServer() { // TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go // so that we can call it here. info := stateInfo(estate.preferIPv6) st, err := state.Initialize(info, cfg, mongo.DefaultDialOpts(), estate.statePolicy) if err != nil { panic(err) } if err := st.SetEnvironConstraints(args.Constraints); err != nil { panic(err) } if err := st.SetAdminMongoPassword(password); err != nil { panic(err) } if err := st.MongoSession().DB("admin").Login("admin", password); err != nil { panic(err) } _, err = st.AddAdminUser(password) if err != nil { panic(err) } estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{ Cert: []byte(testing.ServerCert), Key: []byte(testing.ServerKey), DataDir: DataDir, LogDir: LogDir, }) if err != nil { panic(err) } estate.apiState = st } estate.bootstrapped = true estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args} finalize := func(ctx environs.BootstrapContext, mcfg *cloudinit.MachineConfig) error { estate.ops <- OpFinalizeBootstrap{Context: ctx, Env: e.name, MachineConfig: mcfg} return nil } return arch, series, finalize, nil }