// FinishMachineConfig sets fields on a MachineConfig that can be determined by // inspecting a plain config.Config and the machine constraints at the last // moment before bootstrapping. It assumes that the supplied Config comes from // an environment that has passed through all the validation checks in the // Bootstrap func, and that has set an agent-version (via FindBootstrapTools, // or otherwise). // TODO(fwereade) This function is not meant to be "good" in any serious way: // it is better that this functionality be collected in one place here than // that it be spread out across 3 or 4 providers, but this is its only // redeeming feature. func FinishMachineConfig(mcfg *cloudinit.MachineConfig, cfg *config.Config, cons constraints.Value) (err error) { defer utils.ErrorContextf(&err, "cannot complete machine configuration") // Everything needs the environment's authorized keys. authKeys := cfg.AuthorizedKeys() if authKeys == "" { return fmt.Errorf("environment configuration has no authorized-keys") } mcfg.AuthorizedKeys = authKeys if mcfg.MachineEnvironment == nil { mcfg.MachineEnvironment = make(map[string]string) } mcfg.MachineEnvironment[osenv.JujuProviderType] = cfg.Type() if !mcfg.StateServer { return nil } // These settings are only appropriate at bootstrap time. At the // moment, the only state server is the bootstrap node, but this // will probably change. if mcfg.APIInfo != nil || mcfg.StateInfo != nil { return fmt.Errorf("machine configuration already has api/state info") } caCert, hasCACert := cfg.CACert() if !hasCACert { return fmt.Errorf("environment configuration has no ca-cert") } password := cfg.AdminSecret() if password == "" { return fmt.Errorf("environment configuration has no admin-secret") } passwordHash := utils.PasswordHash(password) mcfg.APIInfo = &api.Info{Password: passwordHash, CACert: caCert} mcfg.StateInfo = &state.Info{Password: passwordHash, CACert: caCert} mcfg.StatePort = cfg.StatePort() mcfg.APIPort = cfg.APIPort() mcfg.Constraints = cons if mcfg.Config, err = BootstrapConfig(cfg); err != nil { return err } // These really are directly relevant to running a state server. cert, key, err := cfg.GenerateStateServerCertAndKey() if err != nil { return fmt.Errorf("cannot generate state server certificate: %v", err) } mcfg.StateServerCert = cert mcfg.StateServerKey = key return nil }