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, ®istrationParams.nonce, ®istrationParams.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, ®istrationParams.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) }
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 }