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 }