Пример #1
0
Файл: switch.go Проект: bac/juju
func (c *switchCommand) Run(ctx *cmd.Context) (resultErr error) {
	store := modelcmd.QualifyingClientStore{c.Store}

	// Get the current name for logging the transition or printing
	// the current controller/model.
	currentControllerName, err := store.CurrentController()
	if errors.IsNotFound(err) {
		currentControllerName = ""
	} else if err != nil {
		return errors.Trace(err)
	}
	if c.Target == "" {
		currentName, err := c.name(store, currentControllerName, true)
		if err != nil {
			return errors.Trace(err)
		}
		if currentName == "" {
			return errors.New("no currently specified model")
		}
		fmt.Fprintf(ctx.Stdout, "%s\n", currentName)
		return nil
	}
	currentName, err := c.name(store, currentControllerName, false)
	if err != nil {
		return errors.Trace(err)
	}

	var newName string
	defer func() {
		if resultErr != nil {
			return
		}
		logSwitch(ctx, currentName, &newName)
	}()

	// Switch is an alternative way of dealing with environments than using
	// the JUJU_MODEL environment setting, and as such, doesn't play too well.
	// If JUJU_MODEL is set we should report that as the current environment,
	// and not allow switching when it is set.
	if model := os.Getenv(osenv.JujuModelEnvKey); model != "" {
		return errors.Errorf("cannot switch when JUJU_MODEL is overriding the model (set to %q)", model)
	}

	// If the target identifies a controller, then set that as the current controller.
	var newControllerName = c.Target
	if _, err = store.ControllerByName(c.Target); err == nil {
		if newControllerName == currentControllerName {
			newName = currentName
			return nil
		} else {
			newName, err = c.name(store, newControllerName, false)
			if err != nil {
				return errors.Trace(err)
			}
			return errors.Trace(store.SetCurrentController(newControllerName))
		}
	} else if !errors.IsNotFound(err) {
		return errors.Trace(err)
	}

	// The target is not a controller, so check for a model with
	// the given name. The name can be qualified with the controller
	// name (<controller>:<model>), or unqualified; in the latter
	// case, the model must exist in the current controller.
	newControllerName, modelName := modelcmd.SplitModelName(c.Target)
	if newControllerName != "" {
		if _, err = store.ControllerByName(newControllerName); err != nil {
			return errors.Trace(err)
		}
	} else {
		if currentControllerName == "" {
			return unknownSwitchTargetError(c.Target)
		}
		newControllerName = currentControllerName
	}
	modelName, err = store.QualifiedModelName(newControllerName, modelName)
	if err != nil {
		return errors.Trace(err)
	}
	newName = modelcmd.JoinModelName(newControllerName, modelName)

	err = store.SetCurrentModel(newControllerName, modelName)
	if errors.IsNotFound(err) {
		// The model isn't known locally, so we must query the controller.
		if err := c.RefreshModels(store, newControllerName); err != nil {
			return errors.Annotate(err, "refreshing models cache")
		}
		err := store.SetCurrentModel(newControllerName, modelName)
		if errors.IsNotFound(err) {
			return unknownSwitchTargetError(c.Target)
		} else if err != nil {
			return errors.Trace(err)
		}
	} else if err != nil {
		return errors.Trace(err)
	}
	if currentControllerName != newControllerName {
		if err := store.SetCurrentController(newControllerName); err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}