func (*diskStoreSuite) TestWriteSmallerFile(c *gc.C) { dir := c.MkDir() store, err := configstore.NewDisk(dir) c.Assert(err, gc.IsNil) info := store.CreateInfo("someenv") endpoint := configstore.APIEndpoint{ Addresses: []string{"this", "is", "never", "validated", "here"}, EnvironUUID: "90168e4c-2f10-4e9c-83c2-feedfacee5a9", } info.SetAPIEndpoint(endpoint) err = info.Write() c.Assert(err, gc.IsNil) newInfo, err := store.ReadInfo("someenv") c.Assert(err, gc.IsNil) // Now change the number of addresses to be shorter. endpoint.Addresses = []string{"just one"} newInfo.SetAPIEndpoint(endpoint) err = newInfo.Write() c.Assert(err, gc.IsNil) // We should be able to read in in fine. yaInfo, err := store.ReadInfo("someenv") c.Assert(err, gc.IsNil) c.Assert(yaInfo.APIEndpoint().Addresses, gc.DeepEquals, []string{"just one"}) }
func (*diskStoreSuite) TestWriteSmallerFile(c *gc.C) { dir := c.MkDir() store, err := configstore.NewDisk(dir) c.Assert(err, jc.ErrorIsNil) info := store.CreateInfo("somemodel") endpoint := configstore.APIEndpoint{ Addresses: []string{"this", "is", "never", "validated", "here"}, Hostnames: []string{"neither", "is", "this"}, ModelUUID: testing.ModelTag.Id(), } info.SetAPIEndpoint(endpoint) err = info.Write() c.Assert(err, jc.ErrorIsNil) newInfo, err := store.ReadInfo("somemodel") c.Assert(err, jc.ErrorIsNil) // Now change the number of addresses to be shorter. endpoint.Addresses = []string{"just one"} endpoint.Hostnames = []string{"just this"} newInfo.SetAPIEndpoint(endpoint) err = newInfo.Write() c.Assert(err, jc.ErrorIsNil) // We should be able to read in in fine. yaInfo, err := store.ReadInfo("somemodel") c.Assert(err, jc.ErrorIsNil) c.Assert(yaInfo.APIEndpoint().Addresses, gc.DeepEquals, []string{"just one"}) c.Assert(yaInfo.APIEndpoint().Hostnames, gc.DeepEquals, []string{"just this"}) }
// 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: configstore.DefaultAdminUsername, Password: cfg.AdminSecret(), } endpoint.ServerUUID = endpoint.EnvironUUID 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 }
// 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() }
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()) }
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 }