func (s *RegisterSuite) TestRegisterEmptyControllerName(c *gc.C) { srv := s.mockServer(c) s.httpHandler = srv registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, }) // We check that it loops when an empty controller name // is entered and that the loop terminates when the user // types ^D. prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller: » You must specify a non-empty controller name. Enter a name for this controller: » You must specify a non-empty controller name. Enter a name for this controller: »» `[1:]) err := s.run(c, prompter, registrationData) c.Assert(err, gc.ErrorMatches, "EOF") prompter.AssertDone() }
func (s *RegisterSuite) TestRegisterServerError(c *gc.C) { response, err := json.Marshal(params.ErrorResult{ Error: ¶ms.Error{Message: "xyz", Code: "123"}, }) s.httpHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) _, err = w.Write(response) c.Check(err, jc.ErrorIsNil) }) prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 `[1:]) registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, }) err = s.run(c, prompter, registrationData) c.Assert(err, gc.ErrorMatches, "xyz") // Check that the controller hasn't been added. _, err = s.store.ControllerByName("controller-name") c.Assert(err, jc.Satisfies, errors.IsNotFound) }
func (s *RegisterSuite) TestProposedControllerNameExists(c *gc.C) { // Controller does not have the UUID from s.testRegister, thereby // mimicing a user with an already registered 'foreign' controller. err := s.store.AddController("controller-name", jujuclient.ControllerDetails{ ControllerUUID: "0d75314a-5266-4f4f-8523-415be76f92dc", CACert: testing.CACert, }) c.Assert(err, jc.ErrorIsNil) s.listModels = func(_ jujuclient.ClientStore, controllerName, userName string) ([]base.UserModel, error) { return []base.UserModel{{ Name: "model-name", Owner: "bob", UUID: mockControllerUUID, }}, nil } prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller: »controller-name Controller "controller-name" already exists. Enter a name for this controller: »other-name Welcome, bob. You are now logged into "other-name". Current model set to "bob/model-name". `[1:]) defer prompter.CheckDone() s.testRegisterSuccess(c, prompter, "other-name") }
func (s *RegisterSuite) TestRegisterOneModel(c *gc.C) { s.listModels = func(_ jujuclient.ClientStore, controllerName, userName string) ([]base.UserModel, error) { return []base.UserModel{{ Name: "theoneandonly", Owner: "carol", UUID: mockControllerUUID, }}, nil } prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller \[controller-name\]: » Welcome, bob. You are now logged into "controller-name". Current model set to "carol/theoneandonly". `[1:]) s.testRegisterSuccess(c, prompter, "") c.Assert( s.store.Models["controller-name"].CurrentModel, gc.Equals, "carol/theoneandonly", ) prompter.CheckDone() }
func (s *RegisterSuite) TestRegisterPublic(c *gc.C) { s.apiConnection.authTag = names.NewUserTag("bob@external") s.apiConnection.controllerAccess = "login" prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a name for this controller: »public-controller-name Welcome, bob@external. You are now logged into "public-controller-name". `[1:]+noModelsText) defer prompter.CheckDone() err := s.run(c, prompter, "0.1.2.3") c.Assert(err, jc.ErrorIsNil) // The controller and account details should be recorded with // the specified controller name and user // name from the auth tag. controller, err := s.store.ControllerByName("public-controller-name") c.Assert(err, jc.ErrorIsNil) c.Assert(controller, jc.DeepEquals, &jujuclient.ControllerDetails{ ControllerUUID: mockControllerUUID, APIEndpoints: []string{"0.1.2.3:443"}, }) account, err := s.store.AccountDetails("public-controller-name") c.Assert(err, jc.ErrorIsNil) c.Assert(account, jc.DeepEquals, &jujuclient.AccountDetails{ User: "******", LastKnownAccess: "login", }) }
func (*prompterSuite) TestSeqPrompterEOF(c *gc.C) { p := cmdtesting.NewSeqPrompter(c, "»", ` hello: »» final `[1:]) fmt.Fprint(p, "hello: ") n, err := p.Read(make([]byte, 10)) c.Assert(n, gc.Equals, 0) c.Assert(err, gc.Equals, io.EOF) fmt.Fprint(p, "final\n") p.AssertDone() }
func (s *RegisterSuite) TestRegisterEmptyPassword(c *gc.C) { registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, }) prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: » `[1:]) defer prompter.CheckDone() err := s.run(c, prompter, registrationData) c.Assert(err, gc.ErrorMatches, "you must specify a non-empty password") }
func (s *RegisterSuite) TestRegisterPasswordMismatch(c *gc.C) { registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, }) prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter3 `[1:]) defer prompter.CheckDone() err := s.run(c, prompter, registrationData) c.Assert(err, gc.ErrorMatches, "passwords do not match") }
func (s *RegisterSuite) TestAPIOpenError(c *gc.C) { registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, }) prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 `[1:]) defer prompter.CheckDone() s.apiOpenError = errors.New("open failed") err := s.run(c, prompter, registrationData) c.Assert(err, gc.ErrorMatches, `open failed`) }
func (*prompterSuite) TestSeqPrompter(c *gc.C) { p := cmdtesting.NewSeqPrompter(c, "»", ` hello: »reply some text goodbye: »again final `[1:]) fmt.Fprint(p, "hello: ") c.Assert(readStr(c, p, 1), gc.Equals, "r") c.Assert(readStr(c, p, 20), gc.Equals, "eply\n") fmt.Fprint(p, "some text\n") fmt.Fprint(p, "goodbye: ") c.Assert(readStr(c, p, 20), gc.Equals, "again\n") fmt.Fprint(p, "final\n") p.AssertDone() }
func (*prompterSuite) TestNewIOChecker(c *gc.C) { checker := cmdtesting.NewSeqPrompter(c, "»", `What is your name: »Bob »more And your age: »148 You're .* old, Bob more! `) fmt.Fprintf(checker, "What is your name: ") buf := make([]byte, 100) n, _ := checker.Read(buf) name := strings.TrimSpace(string(buf[0:n])) fmt.Fprintf(checker, "And your age: ") n, _ = checker.Read(buf) age, err := strconv.Atoi(strings.TrimSpace(string(buf[0:n]))) c.Assert(err, gc.IsNil) if age > 90 { fmt.Fprintf(checker, "You're very old, %s!\n", name) } checker.CheckDone() }
func (s *RegisterSuite) TestRegisterControllerNameExists(c *gc.C) { err := s.store.AddController("controller-name", jujuclient.ControllerDetails{ ControllerUUID: "0d75314a-5266-4f4f-8523-415be76f92dc", CACert: testing.CACert, }) c.Assert(err, jc.ErrorIsNil) prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller: »controller-name Controller "controller-name" already exists. Enter a name for this controller: »other-name Welcome, bob. You are now logged into "other-name". `[1:]+noModelsText) s.testRegisterSuccess(c, prompter, "other-name") prompter.AssertDone() }
func (s *RegisterSuite) TestControllerUUIDExists(c *gc.C) { // Controller has the UUID from s.testRegister to mimic a user with // this controller already registered (regardless of its name). err := s.store.AddController("controller-name", jujuclient.ControllerDetails{ ControllerUUID: mockControllerUUID, CACert: testing.CACert, }) s.listModels = func(_ jujuclient.ClientStore, controllerName, userName string) ([]base.UserModel, error) { return []base.UserModel{{ Name: "model-name", Owner: "bob", UUID: mockControllerUUID, }}, nil } registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, ControllerName: "controller-name", }) srv := s.mockServer(c) s.httpHandler = srv prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. `[1:]) err = s.run(c, prompter, registrationData) c.Assert(err, gc.ErrorMatches, `controller is already registered as "controller-name"`, gc.Commentf("details: %v", errors.Details(err))) prompter.CheckDone() }
func (s *RegisterSuite) TestRegisterMultipleModels(c *gc.C) { s.listModels = func(_ jujuclient.ClientStore, controllerName, userName string) ([]base.UserModel, error) { return []base.UserModel{{ Name: "model1", Owner: "bob", UUID: mockControllerUUID, }, { Name: "model2", Owner: "bob", UUID: "eeeeeeee-12e9-11e4-8a70-b2227cce2b55", }}, nil } prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller \[controller-name\]: » Welcome, bob. You are now logged into "controller-name". There are 2 models available. Use "juju switch" to select one of them: - juju switch model1 - juju switch model2 `[1:]) defer prompter.CheckDone() s.testRegisterSuccess(c, prompter, "") // When there are multiple models, no current model will be set. // Instead, the command will output the list of models and inform // the user how to set the current model. _, err := s.store.CurrentModel("controller-name") c.Assert(err, jc.Satisfies, errors.IsNotFound) }
// testRegisterSuccess tests that the register command when the given // stdio instance is used for input and output. If stdio is nil, a // default prompter will be used. // If controllerName is non-empty, that name will be expected // to be the name of the registered controller. func (s *RegisterSuite) testRegisterSuccess(c *gc.C, stdio io.ReadWriter, controllerName string) { srv := s.mockServer(c) s.httpHandler = srv if controllerName == "" { controllerName = "controller-name" } registrationData := s.encodeRegistrationData(c, jujuclient.RegistrationInfo{ User: "******", SecretKey: mockSecretKey, ControllerName: "controller-name", }) c.Logf("registration data: %q", registrationData) if stdio == nil { prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller \[controller-name\]: » Welcome, bob. You are now logged into "controller-name". `[1:]+noModelsText) defer prompter.CheckDone() stdio = prompter } err := s.run(c, stdio, registrationData) c.Assert(err, jc.ErrorIsNil) // There should have been one POST command to "/register". c.Assert(srv.requests, gc.HasLen, 1) c.Assert(srv.requests[0].Method, gc.Equals, "POST") c.Assert(srv.requests[0].URL.Path, gc.Equals, "/register") var request params.SecretKeyLoginRequest err = json.Unmarshal(srv.requestBodies[0], &request) c.Assert(err, jc.ErrorIsNil) c.Assert(request.User, jc.DeepEquals, "user-bob") c.Assert(request.Nonce, gc.HasLen, 24) requestPayloadPlaintext, err := json.Marshal(params.SecretKeyLoginRequestPayload{ "hunter2", }) c.Assert(err, jc.ErrorIsNil) expectedCiphertext := s.seal(c, requestPayloadPlaintext, mockSecretKey, request.Nonce) c.Assert(request.PayloadCiphertext, jc.DeepEquals, expectedCiphertext) // The controller and account details should be recorded with // the specified controller name and user // name from the registration string. controller, err := s.store.ControllerByName(controllerName) c.Assert(err, jc.ErrorIsNil) c.Assert(controller, jc.DeepEquals, &jujuclient.ControllerDetails{ ControllerUUID: mockControllerUUID, APIEndpoints: []string{s.apiConnection.addr}, CACert: testing.CACert, }) account, err := s.store.AccountDetails(controllerName) c.Assert(err, jc.ErrorIsNil) c.Assert(account, jc.DeepEquals, &jujuclient.AccountDetails{ User: "******", LastKnownAccess: "login", }) }
func noPrompts(c *gc.C) *cmdtesting.SeqPrompter { return cmdtesting.NewSeqPrompter(c, "»", "") }
func (s *cmdRegistrationSuite) TestAddUserAndRegister(c *gc.C) { // First, add user "bob", and record the "juju register" command // that is printed out. context := run(c, nil, "add-user", "bob", "Bob Dobbs") c.Check(testing.Stderr(context), gc.Equals, "") stdout := testing.Stdout(context) expectPat := ` User "Bob Dobbs \(bob\)" added Please send this command to bob: juju register (.+) "Bob Dobbs \(bob\)" has not been granted access to any models(.|\n)* `[1:] c.Assert(stdout, gc.Matches, expectPat) arg := regexp.MustCompile("^" + expectPat + "$").FindStringSubmatch(stdout)[1] c.Logf("juju register %q", arg) // Now run the "juju register" command. We need to pass the // controller name and password to set, and we need a different // file store to mimic a different local OS user. s.CreateUserHome(c, &jujutesting.UserHomeParams{ Username: "******", }) // The expected prompt does not include a warning about the controller // name, as this new local user does not have a controller named // "kontroll" registered. prompter := cmdtesting.NewSeqPrompter(c, "»", ` Enter a new password: »hunter2 Confirm password: »hunter2 Initial password successfully set for bob. Enter a name for this controller \[kontroll\]: »bob-controller Welcome, bob. You are now logged into "bob-controller". There are no models available. (.|\n)* `[1:]) context = run(c, prompter, "register", arg) prompter.AssertDone() // Make sure that the saved server details are sufficient to connect // to the api server. jar, err := cookiejar.New(&cookiejar.Options{ Filename: cookiejar.DefaultCookieFile(), }) c.Assert(err, jc.ErrorIsNil) dialOpts := api.DefaultDialOpts() dialOpts.BakeryClient = httpbakery.NewClient() dialOpts.BakeryClient.Jar = jar accountDetails, err := s.ControllerStore.AccountDetails("bob-controller") c.Assert(err, jc.ErrorIsNil) api, err := juju.NewAPIConnection(juju.NewAPIConnectionParams{ Store: s.ControllerStore, ControllerName: "bob-controller", AccountDetails: accountDetails, DialOpts: dialOpts, OpenAPI: api.Open, }) c.Assert(err, jc.ErrorIsNil) c.Assert(api.Close(), jc.ErrorIsNil) }