Exemple #1
0
// Run updates the configuration of a service.
func (c *SetCommand) Run(ctx *cmd.Context) error {
	api, err := c.getAPI()
	if err != nil {
		return err
	}
	defer api.Close()

	if c.SettingsYAML.Path != "" {
		b, err := c.SettingsYAML.Read(ctx)
		if err != nil {
			return err
		}
		return block.ProcessBlockedError(api.ServiceSetYAML(c.ServiceName, string(b)), block.BlockChange)
	} else if len(c.SettingsStrings) == 0 {
		return nil
	}
	settings := map[string]string{}
	for k, v := range c.SettingsStrings {
		//empty string is also valid as a setting value
		if v == "" {
			settings[k] = v
			continue
		}

		if v[0] != '@' {
			if !utf8.ValidString(v) {
				return fmt.Errorf("value for option %q contains non-UTF-8 sequences", k)
			}
			settings[k] = v
			continue
		}
		nv, err := readValue(ctx, v[1:])
		if err != nil {
			return err
		}
		if !utf8.ValidString(nv) {
			return fmt.Errorf("value for option %q contains non-UTF-8 sequences", k)
		}
		settings[k] = nv
	}

	result, err := api.ServiceGet(c.ServiceName)
	if err != nil {
		return err
	}

	for k, v := range settings {
		configValue := result.Config[k]

		configValueMap, ok := configValue.(map[string]interface{})
		if ok {
			// convert the value to string and compare
			if fmt.Sprintf("%v", configValueMap["value"]) == v {
				logger.Warningf("the configuration setting %q already has the value %q", k, v)
			}
		}
	}

	return block.ProcessBlockedError(api.ServiceSet(c.ServiceName, settings), block.BlockChange)
}
Exemple #2
0
// Run connects to the specified environment and starts the charm
// upgrade process.
func (c *upgradeCharmCommand) Run(ctx *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()
	oldURL, err := client.ServiceGetCharmURL(c.ServiceName)
	if err != nil {
		return err
	}

	conf, err := service.GetClientConfig(client)
	if err != nil {
		return errors.Trace(err)
	}

	var newRef *charm.Reference
	if c.SwitchURL != "" {
		newRef, err = charm.ParseReference(c.SwitchURL)
		if err != nil {
			return err
		}
	} else {
		// No new URL specified, but revision might have been.
		newRef = oldURL.WithRevision(c.Revision).Reference()
	}

	httpClient, err := c.HTTPClient()
	if err != nil {
		return errors.Trace(err)
	}
	csClient := newCharmStoreClient(httpClient)
	newURL, repo, err := resolveCharmStoreEntityURL(newRef.String(), csClient.params, ctx.AbsPath(c.RepoPath), conf)
	if err != nil {
		return errors.Trace(err)
	}

	// If no explicit revision was set with either SwitchURL
	// or Revision flags, discover the latest.
	if *newURL == *oldURL {
		if newRef.Revision != -1 {
			return fmt.Errorf("already running specified charm %q", newURL)
		}
		if newURL.Schema == "cs" {
			// No point in trying to upgrade a charm store charm when
			// we just determined that's the latest revision
			// available.
			return fmt.Errorf("already running latest charm %q", newURL)
		}
	}

	addedURL, err := addCharmViaAPI(client, newURL, repo, csClient)
	if err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}
	ctx.Infof("Added charm %q to the environment.", addedURL)

	return block.ProcessBlockedError(client.ServiceSetCharm(c.ServiceName, addedURL.String(), c.Force), block.BlockChange)
}
Exemple #3
0
// Run connects to the specified environment and starts the charm
// upgrade process.
func (c *upgradeCharmCommand) Run(ctx *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()

	serviceClient, err := c.newServiceAPIClient()
	if err != nil {
		return err
	}

	oldURL, err := serviceClient.GetCharmURL(c.ServiceName)
	if err != nil {
		return err
	}

	newRef := c.SwitchURL
	if newRef == "" {
		newRef = c.CharmPath
	}
	if c.SwitchURL == "" && c.CharmPath == "" {
		// No new URL specified, but revision might have been.
		newRef = oldURL.WithRevision(c.Revision).String()
	}

	bakeryClient, err := c.BakeryClient()
	if err != nil {
		return errors.Trace(err)
	}
	csClient := newCharmStoreClient(bakeryClient).WithChannel(c.Channel)

	conf, err := getClientConfig(client)
	if err != nil {
		return errors.Trace(err)
	}
	resolver := newCharmURLResolver(conf, csClient, ctx.AbsPath(c.RepoPath))
	chID, csMac, err := c.addCharm(oldURL, newRef, client, resolver)
	if err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}
	ctx.Infof("Added charm %q to the model.", chID.URL)

	ids, err := c.upgradeResources(client, chID, csMac)
	if err != nil {
		return errors.Trace(err)
	}

	cfg := apiservice.SetCharmConfig{
		ServiceName: c.ServiceName,
		CharmID:     chID,
		ForceSeries: c.ForceSeries,
		ForceUnits:  c.ForceUnits,
		ResourceIDs: ids,
	}

	return block.ProcessBlockedError(serviceClient.SetCharm(cfg), block.BlockChange)
}
Exemple #4
0
func (s *BlockCommandSuite) processErrorTest(c *gc.C, tstError error, blockType block.Block, expectedError error, expectedWarning string) {
	if tstError != nil {
		c.Assert(errors.Cause(block.ProcessBlockedError(tstError, blockType)), gc.Equals, expectedError)
	} else {
		c.Assert(block.ProcessBlockedError(tstError, blockType), jc.ErrorIsNil)
	}
	// warning displayed
	logOutputText := strings.Replace(c.GetTestLog(), "\n", "", -1)
	c.Assert(logOutputText, gc.Matches, expectedWarning)
}
Exemple #5
0
// Run connects to the environment specified on the command line
// and calls EnsureAvailability.
func (c *ensureAvailabilityCommand) Run(ctx *cmd.Context) error {
	haClient, err := c.getHAClient()
	if err != nil {
		return err
	}

	defer haClient.Close()
	ensureAvailabilityResult, err := haClient.EnsureAvailability(
		c.NumStateServers,
		c.Constraints,
		c.Series,
		c.Placement,
	)
	if err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}

	result := availabilityInfo{
		Added:      machineTagsToIds(ensureAvailabilityResult.Added...),
		Removed:    machineTagsToIds(ensureAvailabilityResult.Removed...),
		Maintained: machineTagsToIds(ensureAvailabilityResult.Maintained...),
		Promoted:   machineTagsToIds(ensureAvailabilityResult.Promoted...),
		Demoted:    machineTagsToIds(ensureAvailabilityResult.Demoted...),
		Converted:  machineTagsToIds(ensureAvailabilityResult.Converted...),
	}
	return c.out.Write(ctx, result)
}
Exemple #6
0
// Run implements Command.Run.
func (c *addCommand) Run(ctx *cmd.Context) error {
	if c.api == nil {
		api, err := c.NewUserManagerAPIClient()
		if err != nil {
			return errors.Trace(err)
		}
		c.api = api
		defer c.api.Close()
	}

	password, err := utils.RandomPassword()
	if err != nil {
		return errors.Annotate(err, "failed to generate random password")
	}
	randomPasswordNotify(password)

	if _, err := c.api.AddUser(c.User, c.DisplayName, password); err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}

	displayName := c.User
	if c.DisplayName != "" {
		displayName = fmt.Sprintf("%s (%s)", c.DisplayName, c.User)
	}

	ctx.Infof("user %q added", displayName)

	return writeServerFile(c, ctx, c.User, password, c.OutPath)
}
Exemple #7
0
// Run connects to the environment specified on the command line
// and calls EnableHA.
func (c *enableHACommand) Run(ctx *cmd.Context) error {
	var err error
	c.Constraints, err = common.ParseConstraints(ctx, c.ConstraintsStr)
	if err != nil {
		return err
	}
	haClient, err := c.newHAClientFunc()
	if err != nil {
		return err
	}

	defer haClient.Close()
	enableHAResult, err := haClient.EnableHA(
		c.NumControllers,
		c.Constraints,
		c.Placement,
	)
	if err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}

	result := availabilityInfo{
		Added:      machineTagsToIds(enableHAResult.Added...),
		Removed:    machineTagsToIds(enableHAResult.Removed...),
		Maintained: machineTagsToIds(enableHAResult.Maintained...),
		Promoted:   machineTagsToIds(enableHAResult.Promoted...),
		Demoted:    machineTagsToIds(enableHAResult.Demoted...),
		Converted:  machineTagsToIds(enableHAResult.Converted...),
	}
	return c.out.Write(ctx, result)
}
Exemple #8
0
func (c *DeployCommand) Run(ctx *cmd.Context) error {
	var err error
	c.Constraints, err = common.ParseConstraints(ctx, c.ConstraintsStr)
	if err != nil {
		return err
	}
	apiRoot, err := c.NewAPIRoot()
	if err != nil {
		return errors.Trace(err)
	}
	defer apiRoot.Close()

	deploy, err := findDeployerFIFO(
		c.maybeReadLocalBundle,
		c.maybeReadLocalCharm,
		c.maybePredeployedLocalCharm,
		c.maybeReadCharmstoreBundleFn(apiRoot),
		c.charmStoreCharm, // This always returns a deployer
	)
	if err != nil {
		return errors.Trace(err)
	}

	return block.ProcessBlockedError(deploy(ctx, apiRoot), block.BlockChange)
}
Exemple #9
0
// setConfig is the run action when we are setting new attribute values as args
// or as a file passed in.
func (c *configCommand) setConfig(client configCommandAPI, ctx *cmd.Context) error {
	if c.useFile {
		return c.setConfigFromFile(client, ctx)
	}

	settings, err := c.validateValues(ctx)
	if err != nil {
		return errors.Trace(err)
	}

	result, err := client.Get(c.applicationName)
	if err != nil {
		return err
	}

	for k, v := range settings {
		configValue := result.Config[k]

		configValueMap, ok := configValue.(map[string]interface{})
		if ok {
			// convert the value to string and compare
			if fmt.Sprintf("%v", configValueMap["value"]) == v {
				logger.Warningf("the configuration setting %q already has the value %q", k, v)
			}
		}
	}

	return block.ProcessBlockedError(client.Set(c.applicationName, settings), block.BlockChange)
}
Exemple #10
0
// Run implements Command.Run.
func (c *removeCommand) Run(ctx *cmd.Context) error {
	api := c.api // This is for testing.

	if api == nil { // The real McCoy.
		var err error
		api, err = c.NewUserManagerAPIClient()
		if err != nil {
			return errors.Trace(err)
		}
		defer api.Close()
	}

	// Confirm deletion if the user didn't specify -y/--yes in the command.
	if !c.ConfirmDelete {
		if err := confirmDelete(ctx, c.ControllerName(), c.UserName); err != nil {
			return err
		}
	}

	err := api.RemoveUser(c.UserName)
	if err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}

	fmt.Fprintf(ctx.Stdout, "User %q removed\n", c.UserName)

	return nil
}
Exemple #11
0
// Run implements Command.Run.
func (c *changePasswordCommand) Run(ctx *cmd.Context) error {
	if c.api == nil {
		api, err := c.NewUserManagerAPIClient()
		if err != nil {
			return errors.Trace(err)
		}
		c.api = api
		defer c.api.Close()
	}

	password, err := c.generateOrReadPassword(ctx, c.Generate)
	if err != nil {
		return errors.Trace(err)
	}

	var writer EnvironInfoCredsWriter

	var creds configstore.APICredentials

	if c.User == "" {
		// We get the creds writer before changing the password just to
		// minimise the things that could go wrong after changing the password
		// in the server.
		if c.writer == nil {
			writer, err = c.ConnectionInfo()
			if err != nil {
				return errors.Trace(err)
			}
		} else {
			writer = c.writer
		}

		creds = writer.APICredentials()
	} else {
		creds.User = c.User
	}

	oldPassword := creds.Password
	creds.Password = password
	if err = c.api.SetPassword(creds.User, password); err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}

	if c.User != "" {
		return writeServerFile(c, ctx, c.User, password, c.OutPath)
	}

	writer.SetAPICredentials(creds)
	if err := writer.Write(); err != nil {
		logger.Errorf("updating the cached credentials failed, reverting to original password")
		setErr := c.api.SetPassword(creds.User, oldPassword)
		if setErr != nil {
			logger.Errorf("failed to set password back, you will need to edit your environments file by hand to specify the password: %q", password)
			return errors.Annotate(setErr, "failed to set password back")
		}
		return errors.Annotate(err, "failed to write new password to environments file")
	}
	ctx.Infof("Your password has been updated.")
	return nil
}
Exemple #12
0
// Run resets the configuration of a service.
func (c *UnsetCommand) Run(ctx *cmd.Context) error {
	apiclient, err := c.getAPI()
	if err != nil {
		return err
	}
	defer apiclient.Close()
	return block.ProcessBlockedError(apiclient.ServiceUnset(c.ServiceName, c.Options), block.BlockChange)
}
Exemple #13
0
// Run changes the juju-managed firewall to expose any
// ports that were also explicitly marked by units as open.
func (c *exposeCommand) Run(_ *cmd.Context) error {
	client, err := c.getAPI()
	if err != nil {
		return err
	}
	defer client.Close()
	return block.ProcessBlockedError(client.Expose(c.ApplicationName), block.BlockChange)
}
Exemple #14
0
// reset unsets the keys provided to the command.
func (c *configCommand) resetConfig(client configCommandAPI, ctx *cmd.Context) error {
	// ctx unused in this method
	if err := c.verifyKnownKeys(client); err != nil {
		return errors.Trace(err)
	}

	return block.ProcessBlockedError(client.ModelUnset(c.resetKeys...), block.BlockChange)
}
Exemple #15
0
func (c *resolvedCommand) Run(_ *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()
	return block.ProcessBlockedError(client.Resolved(c.UnitName, c.NoRetry), block.BlockChange)
}
Exemple #16
0
func (c *defaultsCommand) setDefaults(client defaultsCommandAPI, ctx *cmd.Context) error {
	// ctx unused in this method.
	if err := c.verifyKnownKeys(client); err != nil {
		return errors.Trace(err)
	}
	// TODO(wallyworld) - call with cloud and region when that bit is done
	return block.ProcessBlockedError(client.SetModelDefaults("", "", c.values), block.BlockChange)
}
Exemple #17
0
// Run changes the juju-managed firewall to hide any
// ports that were also explicitly marked by units as closed.
func (c *unexposeCommand) Run(_ *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()
	return block.ProcessBlockedError(client.ServiceUnexpose(c.ServiceName), block.BlockChange)
}
Exemple #18
0
func (c *removeServiceCommand) Run(_ *cmd.Context) error {
	client, err := c.getAPI()
	if err != nil {
		return err
	}
	defer client.Close()
	return block.ProcessBlockedError(client.ServiceDestroy(c.ServiceName), block.BlockRemove)
}
Exemple #19
0
// Run connects to the environment specified on the command line and destroys
// units therein.
func (c *RemoveUnitCommand) Run(_ *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()
	return block.ProcessBlockedError(client.DestroyServiceUnits(c.UnitNames...), block.BlockRemove)
}
Exemple #20
0
func (c *removeRelationCommand) Run(_ *cmd.Context) error {
	client, err := c.getAPI()
	if err != nil {
		return err
	}
	defer client.Close()
	return block.ProcessBlockedError(client.DestroyRelation(c.Endpoints...), block.BlockRemove)
}
Exemple #21
0
// Run implements Command.Run.
func (c *ChangePasswordCommand) Run(ctx *cmd.Context) error {
	var err error

	c.Password, err = c.generateOrReadPassword(ctx, c.Generate)
	if err != nil {
		return errors.Trace(err)
	}

	var credsWriter EnvironInfoCredsWriter
	var creds configstore.APICredentials

	if c.User == "" {
		// We get the creds writer before changing the password just to
		// minimise the things that could go wrong after changing the password
		// in the server.
		credsWriter, err = getEnvironInfoWriter(c)
		if err != nil {
			return errors.Trace(err)
		}

		creds, err = getConnectionCredentials(c)
		if err != nil {
			return errors.Trace(err)
		}
	} else {
		creds.User = c.User
	}

	client, err := getChangePasswordAPI(c)
	if err != nil {
		return err
	}
	defer client.Close()

	oldPassword := creds.Password
	creds.Password = c.Password
	err = client.SetPassword(creds.User, c.Password)
	if err != nil {
		return block.ProcessBlockedError(err, block.BlockChange)
	}

	if c.User != "" {
		return c.writeEnvironmentFile(ctx)
	}

	credsWriter.SetAPICredentials(creds)
	if err := credsWriter.Write(); err != nil {
		logger.Errorf("updating the environments file failed, reverting to original password")
		setErr := client.SetPassword(creds.User, oldPassword)
		if setErr != nil {
			logger.Errorf("failed to set password back, you will need to edit your environments file by hand to specify the password: %q", c.Password)
			return errors.Annotate(setErr, "failed to set password back")
		}
		return errors.Annotate(err, "failed to write new password to environments file")
	}
	ctx.Infof("Your password has been updated.")
	return nil
}
Exemple #22
0
func (c *AddRelationCommand) Run(_ *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()
	_, err = client.AddRelation(c.Endpoints...)
	return block.ProcessBlockedError(err, block.BlockChange)
}
Exemple #23
0
func (c *unshareCommand) Run(ctx *cmd.Context) error {
	client, err := c.getAPI()
	if err != nil {
		return err
	}
	defer client.Close()

	return block.ProcessBlockedError(client.UnshareModel(c.Users...), block.BlockChange)
}
Exemple #24
0
func (c *revokeCommand) runForController() error {
	client, err := c.getControllerAPI()
	if err != nil {
		return err
	}
	defer client.Close()

	return block.ProcessBlockedError(client.RevokeController(c.User, c.Access), block.BlockChange)
}
Exemple #25
0
// setDefaults sets defaults as provided in c.values.
func (c *defaultsCommand) setDefaults(client defaultsCommandAPI, ctx *cmd.Context) error {
	// ctx unused in this method.
	if err := c.verifyKnownKeys(client); err != nil {
		return errors.Trace(err)
	}
	return block.ProcessBlockedError(
		client.SetModelDefaults(
			c.cloudName, c.regionName, c.values), block.BlockChange)
}
Exemple #26
0
func (c *destroyCommand) handleError(err error, modelName string) error {
	if err == nil {
		return nil
	}
	if params.IsCodeOperationBlocked(err) {
		return block.ProcessBlockedError(err, block.BlockDestroy)
	}
	logger.Errorf(`failed to destroy model %q`, modelName)
	return err
}
Exemple #27
0
func (c *serviceSetConstraintsCommand) Run(_ *cmd.Context) (err error) {
	apiclient, err := c.getAPI()
	if err != nil {
		return err
	}
	defer apiclient.Close()

	err = apiclient.SetServiceConstraints(c.ServiceName, c.Constraints)
	return block.ProcessBlockedError(err, block.BlockChange)
}
Exemple #28
0
func (c *DeployCommand) Run(ctx *cmd.Context) error {
	client, err := c.NewAPIClient()
	if err != nil {
		return err
	}
	defer client.Close()

	err = c.deployCharmOrBundle(ctx, client)
	return block.ProcessBlockedError(err, block.BlockChange)
}
Exemple #29
0
func (c *destroyCommand) handleError(err error) error {
	if err == nil {
		return nil
	}
	if params.IsCodeOperationBlocked(err) {
		return block.ProcessBlockedError(err, block.BlockDestroy)
	}
	logger.Errorf(`failed to destroy environment %q`, c.envName)
	return err
}
// ensureUserFriendlyErrorLog ensures that error will be logged and displayed
// in a user-friendly manner with readable and digestable error message.
func (c *destroyEnvironmentCommand) ensureUserFriendlyErrorLog(err error) error {
	if err == nil {
		return nil
	}
	if params.IsCodeOperationBlocked(err) {
		return block.ProcessBlockedError(err, block.BlockDestroy)
	}
	logger.Errorf(stdFailureMsg, c.EnvName())
	return err
}