Exemple #1
0
Fichier : base.go Projet : bac/juju
// RefreshModels refreshes the local models cache for the current user
// on the specified controller.
func (c *JujuCommandBase) RefreshModels(store jujuclient.ClientStore, controllerName string) error {
	modelManager, err := c.modelAPI(store, controllerName)
	if err != nil {
		return errors.Trace(err)
	}
	defer modelManager.Close()

	accountDetails, err := store.AccountDetails(controllerName)
	if err != nil {
		return errors.Trace(err)
	}

	models, err := modelManager.ListModels(accountDetails.User)
	if err != nil {
		return errors.Trace(err)
	}
	for _, model := range models {
		modelDetails := jujuclient.ModelDetails{model.UUID}
		owner := names.NewUserTag(model.Owner)
		modelName := jujuclient.JoinOwnerModelName(owner, model.Name)
		if err := store.UpdateModel(controllerName, modelName, modelDetails); err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}
Exemple #2
0
// decorateAndWriteInfo decorates the info struct with information
// from the given cfg, and the writes that out to the filesystem.
func decorateAndWriteInfo(
	store jujuclient.ClientStore,
	details prepareDetails,
	controllerName, modelName string,
) error {
	qualifiedModelName := jujuclient.JoinOwnerModelName(
		names.NewUserTag(details.AccountDetails.User),
		modelName,
	)
	if err := store.AddController(controllerName, details.ControllerDetails); err != nil {
		return errors.Trace(err)
	}
	if err := store.UpdateBootstrapConfig(controllerName, details.BootstrapConfig); err != nil {
		return errors.Trace(err)
	}
	if err := store.UpdateAccount(controllerName, details.AccountDetails); err != nil {
		return errors.Trace(err)
	}
	if err := store.UpdateModel(controllerName, qualifiedModelName, details.ModelDetails); err != nil {
		return errors.Trace(err)
	}
	if err := store.SetCurrentModel(controllerName, qualifiedModelName); err != nil {
		return errors.Trace(err)
	}
	return nil
}
Exemple #3
0
// QualifiedModelName returns a Qualified model name, given either
// an unqualified or qualified model name. If the input is a
// fully qualified name, it is returned untouched; otherwise it is
// return qualified with the logged-in user name.
func (s QualifyingClientStore) QualifiedModelName(controllerName, modelName string) (string, error) {
	if !jujuclient.IsQualifiedModelName(modelName) {
		details, err := s.ClientStore.AccountDetails(controllerName)
		if err != nil {
			return "", errors.Annotate(err, "getting account details for qualifying model name")
		}
		owner := names.NewUserTag(details.User)
		modelName = jujuclient.JoinOwnerModelName(owner, modelName)
	} else {
		unqualifiedModelName, owner, err := jujuclient.SplitModelName(modelName)
		if err != nil {
			return "", errors.Trace(err)
		}
		owner = names.NewUserTag(owner.Id())
		modelName = jujuclient.JoinOwnerModelName(owner, unqualifiedModelName)
	}
	return modelName, nil
}
Exemple #4
0
func (c *registerCommand) run(ctx *cmd.Context) error {
	store := modelcmd.QualifyingClientStore{c.store}
	registrationParams, err := c.getParameters(ctx, store)
	if err != nil {
		return errors.Trace(err)
	}
	controllerDetails, accountDetails, err := c.controllerDetails(ctx, registrationParams)
	if err != nil {
		return errors.Trace(err)
	}
	controllerName, err := c.updateController(
		ctx,
		store,
		registrationParams.defaultControllerName,
		controllerDetails,
		accountDetails,
	)
	if err != nil {
		return errors.Trace(err)
	}
	// Log into the controller to verify the credentials, and
	// list the models available.
	models, err := c.listModelsFunc(store, controllerName, accountDetails.User)
	if err != nil {
		return errors.Trace(err)
	}
	for _, model := range models {
		owner := names.NewUserTag(model.Owner)
		if err := store.UpdateModel(
			controllerName,
			jujuclient.JoinOwnerModelName(owner, model.Name),
			jujuclient.ModelDetails{model.UUID},
		); err != nil {
			return errors.Annotate(err, "storing model details")
		}
	}
	if err := store.SetCurrentController(controllerName); err != nil {
		return errors.Trace(err)
	}

	fmt.Fprintf(
		ctx.Stderr, "\nWelcome, %s. You are now logged into %q.\n",
		friendlyUserName(accountDetails.User), controllerName,
	)
	return c.maybeSetCurrentModel(ctx, store, controllerName, accountDetails.User, models)
}
Exemple #5
0
func (c *registerCommand) maybeSetCurrentModel(ctx *cmd.Context, store jujuclient.ClientStore, controllerName, userName string, models []base.UserModel) error {
	if len(models) == 0 {
		fmt.Fprintf(ctx.Stderr, "\n%s\n\n", errNoModels.Error())
		return nil
	}

	// If we get to here, there is at least one model.
	if len(models) == 1 {
		// There is exactly one model shared,
		// so set it as the current model.
		model := models[0]
		owner := names.NewUserTag(model.Owner)
		modelName := jujuclient.JoinOwnerModelName(owner, model.Name)
		err := store.SetCurrentModel(controllerName, modelName)
		if err != nil {
			return errors.Trace(err)
		}
		fmt.Fprintf(ctx.Stderr, "\nCurrent model set to %q.\n\n", modelName)
	} else {
		fmt.Fprintf(ctx.Stderr, `
There are %d models available. Use "juju switch" to select
one of them:
`, len(models))
		user := names.NewUserTag(userName)
		ownerModelNames := make(set.Strings)
		otherModelNames := make(set.Strings)
		for _, model := range models {
			if model.Owner == userName {
				ownerModelNames.Add(model.Name)
				continue
			}
			owner := names.NewUserTag(model.Owner)
			modelName := common.OwnerQualifiedModelName(model.Name, owner, user)
			otherModelNames.Add(modelName)
		}
		for _, modelName := range ownerModelNames.SortedValues() {
			fmt.Fprintf(ctx.Stderr, "  - juju switch %s\n", modelName)
		}
		for _, modelName := range otherModelNames.SortedValues() {
			fmt.Fprintf(ctx.Stderr, "  - juju switch %s\n", modelName)
		}
		fmt.Fprintln(ctx.Stderr)
	}
	return nil
}
Exemple #6
0
// formatTabular takes an interface{} to adhere to the cmd.Formatter interface
func (c *modelsCommand) formatTabular(writer io.Writer, value interface{}) error {
	modelSet, ok := value.(ModelSet)
	if !ok {
		return errors.Errorf("expected value of type %T, got %T", modelSet, value)
	}

	// We need the tag of the user for which we're listing models,
	// and for the logged-in user. We use these below when formatting
	// the model display names.
	loggedInUser := names.NewUserTag(c.loggedInUser)
	userForLastConn := loggedInUser
	var userForListing names.UserTag
	if c.user != "" {
		userForListing = names.NewUserTag(c.user)
		userForLastConn = userForListing
	}

	tw := output.TabWriter(writer)
	w := output.Wrapper{tw}
	w.Println("Controller: " + c.ControllerName())
	w.Println()
	w.Print("Model")
	if c.listUUID {
		w.Print("UUID")
	}
	// Only owners, or users with write access or above get to see machines and cores.
	haveMachineInfo := false
	for _, m := range modelSet.Models {
		if haveMachineInfo = len(m.Machines) > 0; haveMachineInfo {
			break
		}
	}
	if haveMachineInfo {
		w.Println("Owner", "Status", "Machines", "Cores", "Access", "Last connection")
		offset := 0
		if c.listUUID {
			offset++
		}
		tw.SetColumnAlignRight(3 + offset)
		tw.SetColumnAlignRight(4 + offset)
	} else {
		w.Println("Owner", "Status", "Access", "Last connection")
	}
	for _, model := range modelSet.Models {
		owner := names.NewUserTag(model.Owner)
		name := common.OwnerQualifiedModelName(model.Name, owner, userForListing)
		if jujuclient.JoinOwnerModelName(owner, model.Name) == modelSet.CurrentModelQualified {
			name += "*"
			w.PrintColor(output.CurrentHighlight, name)
		} else {
			w.Print(name)
		}
		if c.listUUID {
			w.Print(model.UUID)
		}
		lastConnection := model.Users[userForLastConn.Id()].LastConnection
		if lastConnection == "" {
			lastConnection = "never connected"
		}
		userForAccess := loggedInUser
		if c.user != "" {
			userForAccess = names.NewUserTag(c.user)
		}
		access := model.Users[userForAccess.Id()].Access
		w.Print(model.Owner, model.Status.Current)
		if haveMachineInfo {
			machineInfo := fmt.Sprintf("%d", len(model.Machines))
			cores := uint64(0)
			for _, m := range model.Machines {
				cores += m.Cores
			}
			coresInfo := "-"
			if cores > 0 {
				coresInfo = fmt.Sprintf("%d", cores)
			}
			w.Print(machineInfo, coresInfo)
		}
		w.Println(access, lastConnection)
	}
	tw.Flush()
	return nil
}
Exemple #7
0
func (c *registerCommand) Run(ctx *cmd.Context) error {

	store := modelcmd.QualifyingClientStore{c.store}
	registrationParams, err := c.getParameters(ctx, store)
	if err != nil {
		return errors.Trace(err)
	}
	_, err = store.ControllerByName(registrationParams.controllerName)
	if err == nil {
		return errors.AlreadyExistsf("controller %q", registrationParams.controllerName)
	} else if !errors.IsNotFound(err) {
		return errors.Trace(err)
	}

	// During registration we must set a new password. This has to be done
	// atomically with the clearing of the secret key.
	payloadBytes, err := json.Marshal(params.SecretKeyLoginRequestPayload{
		registrationParams.newPassword,
	})
	if err != nil {
		return errors.Trace(err)
	}

	// Make the registration call. If this is successful, the client's
	// cookie jar will be populated with a macaroon that may be used
	// to log in below without the user having to type in the password
	// again.
	req := params.SecretKeyLoginRequest{
		Nonce: registrationParams.nonce[:],
		User:  registrationParams.userTag.String(),
		PayloadCiphertext: secretbox.Seal(
			nil, payloadBytes,
			&registrationParams.nonce,
			&registrationParams.key,
		),
	}
	resp, err := c.secretKeyLogin(registrationParams.controllerAddrs, req)
	if err != nil {
		return errors.Trace(err)
	}

	// Decrypt the response to authenticate the controller and
	// obtain its CA certificate.
	if len(resp.Nonce) != len(registrationParams.nonce) {
		return errors.NotValidf("response nonce")
	}
	var respNonce [24]byte
	copy(respNonce[:], resp.Nonce)
	payloadBytes, ok := secretbox.Open(nil, resp.PayloadCiphertext, &respNonce, &registrationParams.key)
	if !ok {
		return errors.NotValidf("response payload")
	}
	var responsePayload params.SecretKeyLoginResponsePayload
	if err := json.Unmarshal(payloadBytes, &responsePayload); err != nil {
		return errors.Annotate(err, "unmarshalling response payload")
	}

	// Store the controller and account details.
	controllerDetails := jujuclient.ControllerDetails{
		APIEndpoints:   registrationParams.controllerAddrs,
		ControllerUUID: responsePayload.ControllerUUID,
		CACert:         responsePayload.CACert,
	}
	if err := store.AddController(registrationParams.controllerName, controllerDetails); err != nil {
		return errors.Trace(err)
	}
	accountDetails := jujuclient.AccountDetails{
		User:            registrationParams.userTag.Canonical(),
		LastKnownAccess: string(permission.LoginAccess),
	}
	if err := store.UpdateAccount(registrationParams.controllerName, accountDetails); err != nil {
		return errors.Trace(err)
	}

	// Log into the controller to verify the credentials, and
	// list the models available.
	models, err := c.listModelsFunc(store, registrationParams.controllerName, accountDetails.User)
	if err != nil {
		return errors.Trace(err)
	}
	for _, model := range models {
		owner := names.NewUserTag(model.Owner)
		if err := store.UpdateModel(
			registrationParams.controllerName,
			jujuclient.JoinOwnerModelName(owner, model.Name),
			jujuclient.ModelDetails{model.UUID},
		); err != nil {
			return errors.Annotate(err, "storing model details")
		}
	}
	if err := store.SetCurrentController(registrationParams.controllerName); err != nil {
		return errors.Trace(err)
	}

	fmt.Fprintf(
		ctx.Stderr, "\nWelcome, %s. You are now logged into %q.\n",
		registrationParams.userTag.Id(), registrationParams.controllerName,
	)
	return c.maybeSetCurrentModel(ctx, store, registrationParams.controllerName, accountDetails.User, models)
}