func (s *filesSuite) TestSetCurrentController(c *gc.C) { ctx := testing.Context(c) err := envcmd.SetCurrentController(ctx, "new-sys") c.Assert(err, jc.ErrorIsNil) s.assertCurrentController(c, "new-sys") c.Assert(testing.Stderr(ctx), gc.Equals, "-> new-sys (controller)\n") }
func (s *filesSuite) TestSetCurrentControllerExistingEnv(c *gc.C) { err := envcmd.WriteCurrentEnvironment("fubar") c.Assert(err, jc.ErrorIsNil) ctx := testing.Context(c) err = envcmd.SetCurrentController(ctx, "new-sys") c.Assert(err, jc.ErrorIsNil) s.assertCurrentController(c, "new-sys") c.Assert(testing.Stderr(ctx), gc.Equals, "fubar -> new-sys (controller)\n") }
func (c *switchCommand) Run(ctx *cmd.Context) error { // Switch is an alternative way of dealing with environments than using // the JUJU_ENV environment setting, and as such, doesn't play too well. // If JUJU_ENV is set we should report that as the current environment, // and not allow switching when it is set. // Passing through the empty string reads the default environments.yaml file. // If the environments.yaml file doesn't exist, just list environments in // the configstore. envFileExists := true names := set.NewStrings() environments, err := environs.ReadEnvirons("") if err != nil { if !environs.IsNoEnv(err) { return errors.Annotate(err, "couldn't read the environment") } envFileExists = false } else { for _, name := range environments.Names() { names.Add(name) } } configEnvirons, configControllers, err := getConfigstoreOptions() if err != nil { return err } names = names.Union(configEnvirons) names = names.Union(configControllers) if c.List { // List all environments and controllers. if c.EnvName != "" { return errors.New("cannot switch and list at the same time") } for _, name := range names.SortedValues() { if configControllers.Contains(name) && !configEnvirons.Contains(name) { name += controllerSuffix } fmt.Fprintf(ctx.Stdout, "%s\n", name) } return nil } jujuEnv := os.Getenv("JUJU_ENV") if jujuEnv != "" { if c.EnvName == "" { fmt.Fprintf(ctx.Stdout, "%s\n", jujuEnv) return nil } else { return errors.Errorf("cannot switch when JUJU_ENV is overriding the environment (set to %q)", jujuEnv) } } current, isController, err := envcmd.CurrentConnectionName() if err != nil { return errors.Trace(err) } if current == "" { if envFileExists { current = environments.Default } } else if isController { current += controllerSuffix } // Handle the different operation modes. switch { case c.EnvName == "" && current == "": // Nothing specified and nothing to switch to. return errors.New("no currently specified environment") case c.EnvName == "": // Simply print the current environment. fmt.Fprintf(ctx.Stdout, "%s\n", current) return nil default: // Switch the environment. if !names.Contains(c.EnvName) { return errors.Errorf("%q is not a name of an existing defined environment or controller", c.EnvName) } // If the name is not in the environment set, but is in the controller // set, then write the name into the current controller file. logger.Debugf("controllers: %v", configControllers) logger.Debugf("environs: %v", configEnvirons) newEnv := c.EnvName if configControllers.Contains(newEnv) && !configEnvirons.Contains(newEnv) { return envcmd.SetCurrentController(ctx, newEnv) } return envcmd.SetCurrentEnvironment(ctx, newEnv) } }
// Run implements Command.Run func (c *loginCommand) Run(ctx *cmd.Context) error { if c.loginAPIOpen == nil { c.loginAPIOpen = c.JujuCommandBase.APIOpen } // TODO(thumper): as we support the user and address // change this check here. if c.Server.Path == "" { return errors.New("no server file specified") } serverYAML, err := c.Server.Read(ctx) if err != nil { return errors.Trace(err) } var serverDetails envcmd.ServerFile if err := goyaml.Unmarshal(serverYAML, &serverDetails); err != nil { return errors.Trace(err) } info := api.Info{ Addrs: serverDetails.Addresses, CACert: serverDetails.CACert, } var userTag names.UserTag if serverDetails.Username != "" { // Construct the api.Info struct from the provided values // and attempt to connect to the remote server before we do anything else. if !names.IsValidUser(serverDetails.Username) { return errors.Errorf("%q is not a valid username", serverDetails.Username) } userTag = names.NewUserTag(serverDetails.Username) if !userTag.IsLocal() { // Remote users do not have their passwords stored in Juju // so we never attempt to change them. c.KeepPassword = true } info.Tag = userTag } if serverDetails.Password != "" { info.Password = serverDetails.Password } if serverDetails.Password == "" || serverDetails.Username == "" { info.UseMacaroons = true } if c == nil { panic("nil c") } if c.loginAPIOpen == nil { panic("no loginAPIOpen") } apiState, err := c.loginAPIOpen(&info, api.DefaultDialOpts()) if err != nil { return errors.Trace(err) } defer apiState.Close() // If we get to here, the credentials supplied were sufficient to connect // to the Juju Controller and login. Now we cache the details. controllerInfo, err := c.cacheConnectionInfo(serverDetails, apiState) if err != nil { return errors.Trace(err) } ctx.Infof("cached connection details as controller %q", c.Name) // If we get to here, we have been able to connect to the API server, and // also have been able to write the cached information. Now we can change // the user's password to a new randomly generated strong password, and // update the cached information knowing that the likelihood of failure is // minimal. if !c.KeepPassword { if err := c.updatePassword(ctx, apiState, userTag, controllerInfo); err != nil { return errors.Trace(err) } } return errors.Trace(envcmd.SetCurrentController(ctx, c.Name)) }