// cacheChangedAPIInfo updates the local environment settings (.jenv file) // with the provided API server addresses if they have changed. It will also // save the environment tag if it is available. func cacheChangedAPIInfo(info configstore.EnvironInfo, hostPorts [][]network.HostPort, addrConnectedTo network.HostPort, environUUID, serverUUID string) error { addrs, hosts, addrsChanged := PrepareEndpointsForCaching(info, hostPorts, addrConnectedTo) logger.Debugf("cacheChangedAPIInfo: serverUUID=%q", serverUUID) endpoint := info.APIEndpoint() needCaching := false if endpoint.EnvironUUID != environUUID && environUUID != "" { endpoint.EnvironUUID = environUUID needCaching = true } if endpoint.ServerUUID != serverUUID && serverUUID != "" { endpoint.ServerUUID = serverUUID needCaching = true } if addrsChanged { endpoint.Addresses = addrs endpoint.Hostnames = hosts needCaching = true } if !needCaching { return nil } info.SetAPIEndpoint(endpoint) if err := info.Write(); err != nil { return err } logger.Infof("updated API connection settings cache - endpoints %v", endpoint.Addresses) return nil }
// decorateAndWriteInfo decorates the info struct with information // from the given cfg, and the writes that out to the filesystem. func decorateAndWriteInfo(info configstore.EnvironInfo, cfg *config.Config) error { // Sanity check our config. var endpoint configstore.APIEndpoint if cert, ok := cfg.CACert(); !ok { return errors.Errorf("CACert is not set") } else if uuid, ok := cfg.UUID(); !ok { return errors.Errorf("UUID is not set") } else if adminSecret := cfg.AdminSecret(); adminSecret == "" { return errors.Errorf("admin-secret is not set") } else { endpoint = configstore.APIEndpoint{ CACert: cert, EnvironUUID: uuid, } } creds := configstore.APICredentials{ User: "******", // TODO(waigani) admin@local once we have that set Password: cfg.AdminSecret(), } info.SetAPICredentials(creds) info.SetAPIEndpoint(endpoint) info.SetBootstrapConfig(cfg.AllAttrs()) if err := info.Write(); err != nil { return errors.Annotatef(err, "cannot create environment info %q", cfg.Name()) } return nil }
// decorateAndWriteInfo decorates the info struct with information // from the given cfg, and the writes that out to the filesystem. func decorateAndWriteInfo(info configstore.EnvironInfo, cfg *config.Config) error { // Sanity check our config. var endpoint configstore.APIEndpoint if cert, ok := cfg.CACert(); !ok { return errors.Errorf("CACert is not set") } else if uuid, ok := cfg.UUID(); !ok { return errors.Errorf("UUID is not set") } else if adminSecret := cfg.AdminSecret(); adminSecret == "" { return errors.Errorf("admin-secret is not set") } else { endpoint = configstore.APIEndpoint{ CACert: cert, ModelUUID: uuid, } } creds := configstore.APICredentials{ User: configstore.DefaultAdminUsername, Password: cfg.AdminSecret(), } endpoint.ServerUUID = endpoint.ModelUUID info.SetAPICredentials(creds) info.SetAPIEndpoint(endpoint) info.SetBootstrapConfig(cfg.AllAttrs()) if err := info.Write(); err != nil { return errors.Annotatef(err, "cannot create model info %q", cfg.Name()) } return nil }
// cacheAPIInfo updates the local environment settings (.jenv file) // with the provided apiInfo, assuming we've just successfully // connected to the API server. func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) (err error) { defer errors.Contextf(&err, "failed to cache API credentials") environUUID := "" if apiInfo.EnvironTag != "" { tag, err := names.ParseEnvironTag(apiInfo.Tag) if err != nil { return err } environUUID = tag.Id() } info.SetAPIEndpoint(configstore.APIEndpoint{ Addresses: apiInfo.Addrs, CACert: string(apiInfo.CACert), EnvironUUID: environUUID, }) tag, err := names.ParseUserTag(apiInfo.Tag) if err != nil { return err } info.SetAPICredentials(configstore.APICredentials{ User: tag.Id(), Password: apiInfo.Password, }) return info.Write() }
func (c *UseEnvironmentCommand) updateCachedInfo(info configstore.EnvironInfo, envUUID string, creds configstore.APICredentials, endpoint configstore.APIEndpoint) error { info.SetAPICredentials(creds) // Specify the environment UUID. The server UUID will be the same as the // endpoint that we have just connected to, as will be the CACert, addresses // and hostnames. endpoint.EnvironUUID = envUUID info.SetAPIEndpoint(endpoint) return errors.Trace(info.Write()) }
// cacheAPIInfo updates the local environment settings (.jenv file) // with the provided apiInfo, assuming we've just successfully // connected to the API server. func cacheAPIInfo(st apiState, info configstore.EnvironInfo, apiInfo *api.Info) (err error) { defer errors.DeferredAnnotatef(&err, "failed to cache API credentials") var environUUID string if names.IsValidEnvironment(apiInfo.EnvironTag.Id()) { environUUID = apiInfo.EnvironTag.Id() } else { // For backwards-compatibility, we have to allow connections // with an empty UUID. Login will work for the same reasons. logger.Warningf("ignoring invalid cached API endpoint environment UUID %v", apiInfo.EnvironTag.Id()) } hostPorts, err := network.ParseHostPorts(apiInfo.Addrs...) if err != nil { return errors.Annotatef(err, "invalid API addresses %v", apiInfo.Addrs) } addrConnectedTo, err := network.ParseHostPorts(st.Addr()) if err != nil { // Should never happen, since we've just connected with it. return errors.Annotatef(err, "invalid API address %q", st.Addr()) } addrs, hostnames, addrsChanged := PrepareEndpointsForCaching( info, [][]network.HostPort{hostPorts}, addrConnectedTo[0], ) endpoint := configstore.APIEndpoint{ CACert: string(apiInfo.CACert), EnvironUUID: environUUID, } if addrsChanged { endpoint.Addresses = addrs endpoint.Hostnames = hostnames } info.SetAPIEndpoint(endpoint) tag, ok := apiInfo.Tag.(names.UserTag) if !ok { return errors.Errorf("apiInfo.Tag was of type %T, expecting names.UserTag", apiInfo.Tag) } info.SetAPICredentials(configstore.APICredentials{ // This looks questionable. We have a tag, say "user-admin", but then only // the Id portion of the tag is recorded, "admin", so this is really a // username, not a tag, and cannot be reconstructed accurately. User: tag.Id(), Password: apiInfo.Password, }) return info.Write() }
// cacheChangedAPIInfo updates the local environment settings (.jenv file) // with the provided API server addresses if they have changed. It will also // save the environment tag if it is available. func cacheChangedAPIInfo(info configstore.EnvironInfo, hostPorts [][]network.HostPort, newEnvironTag string) error { var addrs []string for _, serverHostPorts := range hostPorts { for _, hostPort := range serverHostPorts { // Only cache addresses that are likely to be usable, // exclude localhost style ones. if hostPort.Scope != network.ScopeMachineLocal && hostPort.Scope != network.ScopeLinkLocal { addrs = append(addrs, hostPort.NetAddr()) } } } endpoint := info.APIEndpoint() changed := false if newEnvironTag != "" { tag, err := names.ParseEnvironTag(newEnvironTag) if err == nil { if environUUID := tag.Id(); endpoint.EnvironUUID != environUUID { changed = true endpoint.EnvironUUID = environUUID } } else { logger.Debugf("cannot parse environ tag: %v", err) } } if len(addrs) != 0 && addrsChanged(endpoint.Addresses, addrs) { logger.Debugf("API addresses changed from %q to %q", endpoint.Addresses, addrs) changed = true endpoint.Addresses = addrs } if !changed { return nil } info.SetAPIEndpoint(endpoint) if err := info.Write(); err != nil { return err } logger.Infof("updated API connection settings cache") return nil }
func (c *LoginCommand) updatePassword(ctx *cmd.Context, conn api.Connection, userTag names.UserTag, serverInfo configstore.EnvironInfo) error { password, err := utils.RandomPassword() if err != nil { return errors.Annotate(err, "failed to generate random password") } userManager, err := c.getUserManager(conn) if err != nil { return errors.Trace(err) } if err := userManager.SetPassword(userTag.Name(), password); err != nil { errors.Trace(err) } ctx.Infof("password updated\n") creds := serverInfo.APICredentials() creds.Password = password serverInfo.SetAPICredentials(creds) if err = serverInfo.Write(); err != nil { return errors.Trace(err) } return nil }
// cacheAPIInfo updates the local environment settings (.jenv file) // with the provided apiInfo, assuming we've just successfully // connected to the API server. func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) (err error) { defer errors.Contextf(&err, "failed to cache API credentials") var environUUID string if apiInfo.EnvironTag != nil { environUUID = apiInfo.EnvironTag.Id() } info.SetAPIEndpoint(configstore.APIEndpoint{ Addresses: apiInfo.Addrs, CACert: string(apiInfo.CACert), EnvironUUID: environUUID, }) tag, ok := apiInfo.Tag.(names.UserTag) if !ok { return errors.Errorf("apiInfo.Tag was of type %T, expecting names.UserTag", apiInfo.Tag) } info.SetAPICredentials(configstore.APICredentials{ // This looks questionable. We have a tag, say "user-admin", but then only // the Id portion of the tag is recorded, "admin", so this is really a // username, not a tag, and cannot be reconstructed accurately. User: tag.Id(), Password: apiInfo.Password, }) return info.Write() }
func (c *createEnvironmentCommand) Run(ctx *cmd.Context) (return_err error) { client, err := c.getAPI() if err != nil { return err } defer client.Close() creds, err := c.ConnectionCredentials() if err != nil { return errors.Trace(err) } creatingForSelf := true envOwner := creds.User if c.Owner != "" { owner := names.NewUserTag(c.Owner) user := names.NewUserTag(creds.User) creatingForSelf = owner == user envOwner = c.Owner } var info configstore.EnvironInfo var endpoint configstore.APIEndpoint if creatingForSelf { logger.Debugf("create cache entry for %q", c.Name) // Create the configstore entry and write it to disk, as this will error // if one with the same name already exists. endpoint, err = c.ConnectionEndpoint() if err != nil { return errors.Trace(err) } store, err := configstore.Default() if err != nil { return errors.Trace(err) } info = store.CreateInfo(c.Name) info.SetAPICredentials(creds) endpoint.EnvironUUID = "" if err := info.Write(); err != nil { if errors.Cause(err) == configstore.ErrEnvironInfoAlreadyExists { newErr := errors.AlreadyExistsf("environment %q", c.Name) return errors.Wrap(err, newErr) } return errors.Trace(err) } defer func() { if return_err != nil { logger.Debugf("error found, remove cache entry") e := info.Destroy() if e != nil { logger.Errorf("could not remove environment file: %v", e) } } }() } else { logger.Debugf("skipping cache entry for %q as owned %q", c.Name, c.Owner) } serverSkeleton, err := client.ConfigSkeleton("", "") if err != nil { return errors.Trace(err) } attrs, err := c.getConfigValues(ctx, serverSkeleton) if err != nil { return errors.Trace(err) } // We pass nil through for the account details until we implement that bit. env, err := client.CreateEnvironment(envOwner, nil, attrs) if err != nil { // cleanup configstore return errors.Trace(err) } if creatingForSelf { // update the cached details with the environment uuid endpoint.EnvironUUID = env.UUID info.SetAPIEndpoint(endpoint) if err := info.Write(); err != nil { return errors.Trace(err) } ctx.Infof("created environment %q", c.Name) return envcmd.SetCurrentEnvironment(ctx, c.Name) } else { ctx.Infof("created environment %q for %q", c.Name, c.Owner) } return nil }