Esempio n. 1
0
func (s *filesSuite) TestSetCurrentController(c *gc.C) {
	ctx := testing.Context(c)
	err := modelcmd.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")
}
Esempio n. 2
0
func (s *filesSuite) TestSetCurrentControllerExistingEnv(c *gc.C) {
	err := modelcmd.WriteCurrentModel("fubar")
	c.Assert(err, jc.ErrorIsNil)
	ctx := testing.Context(c)
	err = modelcmd.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")
}
Esempio n. 3
0
func (c *switchCommand) Run(ctx *cmd.Context) error {
	// 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.

	// 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 model")
		}
		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.ModelName != "" {
			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_MODEL")
	if jujuEnv != "" {
		if c.ModelName == "" {
			fmt.Fprintf(ctx.Stdout, "%s\n", jujuEnv)
			return nil
		} else {
			return errors.Errorf("cannot switch when JUJU_MODEL is overriding the model (set to %q)", jujuEnv)
		}
	}

	current, isController, err := modelcmd.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.ModelName == "" && current == "":
		// Nothing specified and nothing to switch to.
		return errors.New("no currently specified model")
	case c.ModelName == "":
		// Simply print the current environment.
		fmt.Fprintf(ctx.Stdout, "%s\n", current)
		return nil
	default:
		// Switch the environment.
		if !names.Contains(c.ModelName) {
			return errors.Errorf("%q is not a name of an existing defined model or controller", c.ModelName)
		}
		// 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("models: %v", configEnvirons)
		newEnv := c.ModelName
		if configControllers.Contains(newEnv) && !configEnvirons.Contains(newEnv) {
			return modelcmd.SetCurrentController(ctx, newEnv)
		}
		return modelcmd.SetCurrentModel(ctx, newEnv)
	}
}
Esempio n. 4
0
// 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 modelcmd.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(modelcmd.SetCurrentController(ctx, c.Name))
}