// EnsureAPIInfo makes sure we can connect as an agent to the API server 1.10 // did not set an API password for machine agents, 1.11 sets it the same as the // mongo password. 1.10 also does not set any API Info at all for Unit agents. // conf is the agent.conf for this machine/unit agent. agentConn is the direct // connection to the State database func EnsureAPIInfo(conf *agent.Conf, stConn *state.State, agentConn AgentState) error { // In 1.10 Machine Agents will have an API Info section, but will not // have properly configured the Password field, so when upgrading to // 1.11 we must set that field // In 1.10 Unit Agents will not have an API Info section at all, so we // must set everything from the StateInfo (correcting the Addrs for API // port vs Mongo port) // A new 1.11 Unit Agent will have an OldPassword but no Password set // (in StateInfo or APIInfo). Because we only change the password on // API connect, not on DB connect. We don't want to make extra // SetPassword calls when we already have a valid password set if conf.APIInfo != nil && (conf.APIInfo.Password != "" || conf.StateInfo.Password == "") { // We must have set it earlier return nil } setter, ok := agentConn.(passwordSetter) if !ok { panic("AgentState is missing a SetPassword method?") } if conf.APIInfo == nil { // Unit agents didn't get any APIInfo in 1.10 conf.APIInfo = apiInfoFromStateInfo(conf.StateInfo, stConn) validationLogger.Infof( "agent.conf APIInfo is not set. Setting to {Addrs: %s, Tag: %s}", conf.APIInfo.Addrs, conf.APIInfo.Tag, ) } else { validationLogger.Infof("agent.conf APIInfo password is not set. Setting to state password") conf.APIInfo.Password = conf.StateInfo.Password } password := conf.StateInfo.Password if password == "" { // In 1.11 we don't set a new password on connect (because it is // done in the API code, and we don't have any API workers). // We want to make sure the API user has the correct password // (OldPassword). We *don't* want to set APIInfo.Password // because then when we do connect via the API we wouldn't // change the password. So this is only used for SetPassword validationLogger.Infof( "agent.conf StateInfo password is \"\". Setting Agent password for %s to OldPassword", conf.APIInfo.Tag) password = conf.OldPassword } // We set the actual password before writing it to disk, because // otherwise we would not set it correctly in the future if err := setter.SetPassword(password); err != nil { return err } if err := conf.Write(); err != nil { return err } return nil }