func makeCreds(init bool, c ...*stack.Credential) map[string]interface{} { creds := make(map[string]interface{}, len(c)) if init { // Using func-scope to defer unlocking in case user-provided // function panics. func() { providersMu.Lock() defer providersMu.Unlock() for _, c := range c { if c.Credential == nil { c.Credential = schema(c.Provider).newCredential() } if c.Bootstrap == nil { c.Bootstrap = schema(c.Provider).newBootstrap() } } }() } for _, c := range c { if c.Bootstrap == nil { creds[c.Identifier] = c.Credential } else { creds[c.Identifier] = object.Inline(c.Credential, c.Bootstrap) } } return creds }
func mergeIn(kfg, mixin *config.Konfig) error { p, err := json.Marshal(object.Inline(mixin, kfg)) if err != nil { return err } return json.Unmarshal(p, kfg) }
func (s *Stacker) FetchCredData(bm *BaseMachine) error { credentials := make(map[string]interface{}) if bm.Bootstrap != nil { credentials[bm.Machine.Credential] = object.Inline(bm.Credential, bm.Bootstrap) } else { credentials[bm.Machine.Credential] = object.ToAddr(bm.Credential) } return s.CredStore.Fetch(bm.Username(), credentials) }
func (bs *BaseStack) bootstrap(arg *stack.BootstrapRequest) (interface{}, error) { if arg.Destroy { bs.Log.Debug("Bootstrap destroy is called") } else { bs.Log.Debug("Bootstrap apply is called") } if err := bs.Builder.BuildCredentials(bs.Req.Method, bs.Req.Username, arg.GroupName, arg.Identifiers); err != nil { return nil, err } bs.Log.Debug("Connecting to terraformer kite") tfKite, err := terraformer.Connect(bs.Session.Terraformer) if err != nil { return nil, err } defer tfKite.Close() bs.Log.Debug("Iterating over credentials") updatedCreds := make(map[string]*stack.Credential) for _, cred := range bs.Builder.Credentials { if cred.Provider != bs.Planner.Provider { continue } var bootstrapMixin interface{} if bs.SSHKeyPairFunc != nil { keypair, err := stack.GenerateSSHKeyPair() if err != nil { return nil, fmt.Errorf("error generating SSH key-pair: %s", err) } if err := bs.SSHKeyPairFunc(keypair); err != nil { return nil, fmt.Errorf("error injecting SSH key-pair: %s", err) } bootstrapMixin = keypair } templates, err := bs.stack.BootstrapTemplates(cred) if err != nil { return nil, err } destroyUniq := make(map[string]struct{}) // protects from double-destroy for _, tmpl := range templates { if tmpl.Key == "" { tmpl.Key = bs.Planner.Provider + "-" + arg.GroupName + "-" + cred.Identifier } if arg.Destroy { if _, ok := destroyUniq[tmpl.Key]; !ok { bs.Log.Info("Destroying bootstrap resources belonging to identifier '%s'", cred.Identifier) _, err := tfKite.Destroy(&tf.TerraformRequest{ ContentID: tmpl.Key, TraceID: bs.TraceID, }) if err != nil { return nil, err } cred.Bootstrap = bs.Provider.newBootstrap() destroyUniq[tmpl.Key] = struct{}{} } } else { bs.Log.Debug("Bootstrap template for %s: %s", cred.Identifier, tmpl) // TODO(rjeczalik): use []byte for templates to avoid allocations if err := bs.Builder.BuildTemplate(string(tmpl.Content), tmpl.Key); err != nil { return nil, fmt.Errorf("error building template: %s", err) } content, err := bs.Builder.Template.JsonOutput() if err != nil { return nil, err } bs.Log.Debug("Final bootstrap template: %s", content) state, err := tfKite.Apply(&tf.TerraformRequest{ Content: content, ContentID: tmpl.Key, TraceID: bs.TraceID, }) if err != nil { return nil, err } bs.Log.Debug("[%s] state.RootModule().Outputs = %+v\n", cred.Identifier, state.RootModule().Outputs) if err := bs.Builder.Object.Decode(state.RootModule().Outputs, cred.Bootstrap); err != nil { return nil, err } bs.Log.Debug("[%s] resp = %+v\n", cred.Identifier, cred.Bootstrap) if v, ok := cred.Bootstrap.(stack.Validator); ok { if err := v.Valid(); err != nil { return nil, fmt.Errorf("invalid bootstrap metadata for %q: %s", cred.Identifier, err) } } } if bootstrapMixin != nil { cred.Bootstrap = object.Inline(cred.Bootstrap, bootstrapMixin) } updatedCreds[cred.Identifier] = cred bs.Log.Debug("[%s] Bootstrap response: %+v", cred.Identifier, cred.Bootstrap) } } creds := make([]*stack.Credential, 0, len(updatedCreds)) for _, cred := range updatedCreds { creds = append(creds, cred) } if err := bs.Builder.PutCredentials(bs.Req.Username, creds...); err != nil { return nil, err } return true, nil }