func (s *AddMachineSuite) TestAddUnsupportedContainerToMachine(c *gc.C) { context, err := runAddMachine(c) c.Assert(err, gc.IsNil) c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n") m, err := s.State.Machine("0") c.Assert(err, gc.IsNil) m.SetSupportedContainers([]instance.ContainerType{instance.KVM}) context, err = runAddMachine(c, "lxc:0") c.Assert(err, gc.ErrorMatches, "cannot add a new machine: machine 0 cannot host lxc containers") c.Assert(testing.Stderr(context), gc.Equals, "failed to create 1 machine\n") }
func (s *cmdRegistrationSuite) TestAddUserAndRegister(c *gc.C) { // First, add user "bob", and record the "juju register" command // that is printed out. context := s.run(c, nil, "add-user", "bob", "Bob Dobbs") c.Check(testing.Stderr(context), gc.Equals, "") stdout := testing.Stdout(context) c.Check(stdout, gc.Matches, ` 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:]) jujuRegisterCommand := strings.Fields(strings.TrimSpace( strings.SplitN(stdout[strings.Index(stdout, "juju register"):], "\n", 2)[0], )) c.Logf("%q", jujuRegisterCommand) // Now run the "juju register" command. We need to pass the // controller name and password to set. stdin := strings.NewReader("bob-controller\nhunter2\nhunter2\n") args := jujuRegisterCommand[1:] // drop the "juju" context = s.run(c, stdin, args...) c.Check(testing.Stdout(context), gc.Equals, "") c.Check(testing.Stderr(context), gc.Equals, ` Please set a name for this controller: Enter password: Confirm password: Welcome, bob. You are now logged into "bob-controller". There are no models available. You can create models with "juju create-model", or you can ask an administrator or owner of a model to grant access to that model with "juju grant". `[1:]) // Make sure that the saved server details are sufficient to connect // to the api server. accountDetails, err := s.ControllerStore.AccountByName("bob-controller", "bob@local") c.Assert(err, jc.ErrorIsNil) api, err := juju.NewAPIConnection(juju.NewAPIConnectionParams{ Store: s.ControllerStore, ControllerName: "bob-controller", AccountDetails: accountDetails, BootstrapConfig: noBootstrapConfig, DialOpts: api.DefaultDialOpts(), }) c.Assert(err, jc.ErrorIsNil) c.Assert(api.Close(), jc.ErrorIsNil) }
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@local", UUID: "df136476-12e9-11e4-8a70-b2227cce2b54", }, { Name: "model2", Owner: "bob@local", UUID: "df136476-12e9-11e4-8a70-b2227cce2b55", }}, nil } ctx := s.testRegister(c, "") // 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) stderr := testing.Stderr(ctx) c.Assert(stderr, gc.Equals, ` Enter a name for this controller [controller-name]: Enter a new password: Confirm password: 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:]) }
func (s *filesSuite) TestSetCurrentModel(c *gc.C) { ctx := testing.Context(c) err := modelcmd.SetCurrentModel(ctx, "new-model") c.Assert(err, jc.ErrorIsNil) s.assertCurrentModel(c, "new-model") c.Assert(testing.Stderr(ctx), gc.Equals, "-> new-model\n") }
func (s *AddMachineSuite) TestAddContainerToExistingMachine(c *gc.C) { context, err := runAddMachine(c) c.Assert(err, gc.IsNil) c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n") for i, container := range instance.ContainerTypes { machineNum := strconv.Itoa(i + 1) context, err = runAddMachine(c) c.Assert(err, gc.IsNil) c.Assert(testing.Stderr(context), gc.Equals, "created machine "+machineNum+"\n") context, err := runAddMachine(c, fmt.Sprintf("%s:%s", container, machineNum)) c.Assert(err, gc.IsNil) machine := fmt.Sprintf("%s/%s/0", machineNum, container) c.Assert(testing.Stderr(context), gc.Equals, "created container "+machine+"\n") s._assertAddContainer(c, machineNum, machine, container) } }
func (s *KillSuite) TestKillEarlyAPIConnectionTimeout(c *gc.C) { stop := make(chan struct{}) defer close(stop) testDialer := func(sysName string) (*api.State, error) { <-stop return nil, errors.New("kill command waited too long") } done := make(chan struct{}) go func() { defer close(done) cmd := system.NewKillCommand(nil, nil, nil, testDialer) ctx, err := testing.RunCommand(c, cmd, "test1", "-y") c.Check(err, jc.ErrorIsNil) c.Check(testing.Stderr(ctx), jc.Contains, "Unable to open API: connection to state server timed out") c.Check(s.api.ignoreBlocks, jc.IsFalse) c.Check(s.api.destroyAll, jc.IsFalse) checkSystemRemovedFromStore(c, "test1", s.store) }() select { case <-done: case <-time.After(1 * time.Minute): c.Fatalf("Kill command waited too long to open the API") } }
func (s *KillSuite) TestKillCannotConnectToAPISucceeds(c *gc.C) { s.apierror = errors.New("connection refused") ctx, err := s.runKillCommand(c, "local.test1", "-y") c.Assert(err, jc.ErrorIsNil) c.Check(testing.Stderr(ctx), jc.Contains, "Unable to open API: connection refused") checkControllerRemovedFromStore(c, "local.test1", s.store) }
func (s *credentialsSuite) TestFinalizeCredentialUserPass(c *gc.C) { in := cloud.NewCredential("userpass", map[string]string{ "application-id": "application", "application-password": "******", "subscription-id": "subscription", "tenant-id": "tenant", }) ctx := coretesting.Context(c) out, err := s.provider.FinalizeCredential(ctx, environs.FinalizeCredentialParams{Credential: in}) c.Assert(err, jc.ErrorIsNil) c.Assert(out, gc.NotNil) c.Assert(out.AuthType(), gc.Equals, cloud.AuthType("service-principal-secret")) c.Assert(out.Attributes(), jc.DeepEquals, map[string]string{ "application-id": "application", "application-password": "******", "subscription-id": "subscription", }) stderr := coretesting.Stderr(ctx) c.Assert(stderr, gc.Equals, ` WARNING: The "userpass" auth-type is deprecated, and will be removed soon. Please update the credential in ~/.local/share/juju/credentials.yaml, changing auth-type to "service-principal-secret", and dropping the tenant-id field. `[1:]) }
func (s *LogoutCommandSuite) TestLogoutCount(c *gc.C) { // Create multiple controllers. We'll log out of each one // to observe the messages printed out by "logout". s.setPassword(c, "testing", "") controllers := []string{"testing", "testing2", "testing3"} details := s.store.Accounts["testing"] for _, controller := range controllers { s.store.Controllers[controller] = s.store.Controllers["testing"] err := s.store.UpdateAccount(controller, details) c.Assert(err, jc.ErrorIsNil) } expected := []string{ "Logged out. You are still logged into 2 controllers.\n", "Logged out. You are still logged into 1 controller.\n", "Logged out. You are no longer logged into any controllers.\n", } for i, controller := range controllers { ctx, err := s.run(c, "-c", controller) c.Assert(err, jc.ErrorIsNil) c.Assert(coretesting.Stdout(ctx), gc.Equals, "") c.Assert(coretesting.Stderr(ctx), gc.Equals, expected[i]) } }
func (s *filesystemListSuite) assertUserFacingOutput(c *gc.C, context *cmd.Context, expectedOut, expectedErr string) { obtainedOut := testing.Stdout(context) c.Assert(obtainedOut, gc.Equals, expectedOut) obtainedErr := testing.Stderr(context) c.Assert(obtainedErr, gc.Equals, expectedErr) }
func (s *SwitchSimpleSuite) TestSwitchLocalControllerWithCurrent(c *gc.C) { s.currentController = "old" s.addController(c, "local.new") context, err := s.run(c, "new") c.Assert(err, jc.ErrorIsNil) c.Assert(coretesting.Stderr(context), gc.Equals, "old (controller) -> local.new (controller)\n") }
func (s *detectCredentialsSuite) assertDetectCredential(c *gc.C, cloudName, expectedRegion, errText string) { s.aCredential = jujucloud.CloudCredential{ DefaultRegion: "default region", AuthCredentials: map[string]jujucloud.Credential{ "test": s.credentialWithLabel(jujucloud.AccessKeyAuthType, "credential")}, } clouds := map[string]jujucloud.Cloud{ "test-cloud": { Type: "mock-provider", }, "another-cloud": { Type: "another-provider", }, } stdin := strings.NewReader(fmt.Sprintf("1\n%s\nQ\n", cloudName)) ctx, err := s.run(c, stdin, clouds) c.Assert(err, jc.ErrorIsNil) if errText == "" { if expectedRegion != "" { s.aCredential.DefaultRegion = expectedRegion } c.Assert(s.store.Credentials["test-cloud"], jc.DeepEquals, s.aCredential) } else { output := strings.Replace(testing.Stderr(ctx), "\n", "", -1) c.Assert(output, gc.Matches, ".*"+regexp.QuoteMeta(errText)+".*") } }
func (s *addSuite) assertExpectedOutput(c *gc.C, context *cmd.Context, expectedOut, expectedErr string) { obtainedErr := testing.Stderr(context) c.Assert(obtainedErr, gc.Equals, expectedErr) obtainedValid := testing.Stdout(context) c.Assert(obtainedValid, gc.Equals, expectedOut) }
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) TestSetCurrentEnvironment(c *gc.C) { ctx := testing.Context(c) err := envcmd.SetCurrentEnvironment(ctx, "new-env") c.Assert(err, jc.ErrorIsNil) s.assertCurrentEnvironment(c, "new-env") c.Assert(testing.Stderr(ctx), gc.Equals, "-> new-env\n") }
func (s *bootstrapSuite) TestBootstrapGUISuccessLocal(c *gc.C) { path := makeGUIArchive(c, "jujugui-2.2.0") s.PatchEnvironment("JUJU_GUI", path) env := newEnviron("foo", useDefaultKeys, nil) ctx := coretesting.Context(c) err := bootstrap.Bootstrap(modelcmd.BootstrapContext(ctx), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) c.Assert(coretesting.Stderr(ctx), jc.Contains, "Preparing for Juju GUI 2.2.0 installation from local archive\n") // Check GUI URL and version. c.Assert(env.instanceConfig.GUI.URL, gc.Equals, "file://"+path) c.Assert(env.instanceConfig.GUI.Version.String(), gc.Equals, "2.2.0") // Check GUI size. f, err := os.Open(path) c.Assert(err, jc.ErrorIsNil) defer f.Close() info, err := f.Stat() c.Assert(err, jc.ErrorIsNil) c.Assert(env.instanceConfig.GUI.Size, gc.Equals, info.Size()) // Check GUI hash. h := sha256.New() _, err = io.Copy(h, f) c.Assert(err, jc.ErrorIsNil) c.Assert(env.instanceConfig.GUI.SHA256, gc.Equals, fmt.Sprintf("%x", h.Sum(nil))) }
func (s *bootstrapSuite) TestBootstrapGUISuccessRemote(c *gc.C) { s.PatchValue(bootstrap.GUIFetchMetadata, func(stream string, sources ...simplestreams.DataSource) ([]*gui.Metadata, error) { c.Assert(stream, gc.Equals, gui.ReleasedStream) c.Assert(sources[0].Description(), gc.Equals, "gui simplestreams") c.Assert(sources[0].RequireSigned(), jc.IsTrue) return []*gui.Metadata{{ Version: version.MustParse("2.0.42"), FullPath: "https://1.2.3.4/juju-gui-2.0.42.tar.bz2", SHA256: "hash-2.0.42", Size: 42, }, { Version: version.MustParse("2.0.47"), FullPath: "https://1.2.3.4/juju-gui-2.0.47.tar.bz2", SHA256: "hash-2.0.47", Size: 47, }}, nil }) env := newEnviron("foo", useDefaultKeys, nil) ctx := coretesting.Context(c) err := bootstrap.Bootstrap(modelcmd.BootstrapContext(ctx), env, bootstrap.BootstrapParams{ GUIDataSourceBaseURL: "https://1.2.3.4/gui/sources", }) c.Assert(err, jc.ErrorIsNil) c.Assert(coretesting.Stderr(ctx), jc.Contains, "Preparing for Juju GUI 2.0.42 release installation\n") // The most recent GUI release info has been stored. c.Assert(env.instanceConfig.GUI.URL, gc.Equals, "https://1.2.3.4/juju-gui-2.0.42.tar.bz2") c.Assert(env.instanceConfig.GUI.Version.String(), gc.Equals, "2.0.42") c.Assert(env.instanceConfig.GUI.Size, gc.Equals, int64(42)) c.Assert(env.instanceConfig.GUI.SHA256, gc.Equals, "hash-2.0.42") }
func (s *cmdStorageSuite) TestStorageAddToUnitInvalidUnitName(c *gc.C) { cmdArgs := append([]string{"add-storage"}, "fluffyunit-0", "allecto=1") context, err := runJujuCommand(c, cmdArgs...) c.Assert(err, gc.ErrorMatches, `unit name "fluffyunit-0" not valid`) c.Assert(testing.Stdout(context), gc.Equals, "") c.Assert(testing.Stderr(context), gc.Equals, "error: unit name \"fluffyunit-0\" not valid\n") }
func (s *DestroySuite) TestDestroyReturnsBlocks(c *gc.C) { s.api.SetErrors(¶ms.Error{Code: params.CodeOperationBlocked}) s.api.blocks = []params.ModelBlockInfo{ params.ModelBlockInfo{ Name: "test1", UUID: test1UUID, OwnerTag: "cheryl@local", Blocks: []string{ "BlockDestroy", }, }, params.ModelBlockInfo{ Name: "test2", UUID: test2UUID, OwnerTag: "bob@local", Blocks: []string{ "BlockDestroy", "BlockChange", }, }, } ctx, _ := s.runDestroyCommand(c, "local.test1", "-y", "--destroy-all-models") c.Assert(testing.Stderr(ctx), gc.Equals, "Destroying controller\n"+ "NAME MODEL UUID OWNER BLOCKS\n"+ "test1 1871299e-1370-4f3e-83ab-1849ed7b1076 cheryl@local destroy-model\n"+ "test2 c59d0e3b-2bd7-4867-b1b9-f1ef8a0bb004 bob@local destroy-model,all-changes\n") }
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, }) s.listModels = func(_ jujuclient.ClientStore, controllerName, userName string) ([]base.UserModel, error) { return []base.UserModel{{ Name: "model-name", Owner: "bob@local", UUID: "df136476-12e9-11e4-8a70-b2227cce2b54", }}, nil } ctx := s.testRegister(c, "you must specify a non-empty controller name") secretKey := []byte(strings.Repeat("X", 32)) registrationData := s.encodeRegistrationDataWithControllerName(c, "bob", secretKey, "controller-name") stdin := strings.NewReader("another-controller-name\nhunter2\nhunter2\n") _, err = s.run(c, stdin, registrationData) c.Assert(err, jc.ErrorIsNil) stderr := testing.Stderr(ctx) c.Assert(stderr, gc.Equals, ` WARNING: You already have a controller registered with the name "controller-name". Please choose a different name for the new controller. Enter a name for this controller: `[1:]) }
func (s *ChangePasswordCommandSuite) TestChangePasswordGenerate(c *gc.C) { context, err := s.run(c, "--generate") c.Assert(err, jc.ErrorIsNil) c.Assert(s.mockAPI.username, gc.Equals, "user-name") s.assertRandomPassword(c) c.Assert(testing.Stderr(context), gc.Equals, "Your password has been updated.\n") }
func (s *BootstrapSuite) TestMissingToolsUploadFailedError(c *gc.C) { buildToolsTarballAlwaysFails := func(forceVersion *version.Number, stream string) (*sync.BuiltTools, error) { return nil, fmt.Errorf("an error") } s.setupAutoUploadTest(c, "1.7.3", "precise") s.PatchValue(&sync.BuildToolsTarball, buildToolsTarballAlwaysFails) ctx, err := coretesting.RunCommand( c, s.newBootstrapCommand(), "devcontroller", "dummy-cloud/region-1", "--config", "default-series=raring", "--config", "agent-stream=proposed", "--auto-upgrade", ) c.Check(coretesting.Stderr(ctx), gc.Equals, fmt.Sprintf(` Creating Juju controller "local.devcontroller" on dummy-cloud/region-1 Bootstrapping model "admin" Starting new instance for initial controller Building tools to upload (1.7.3.1-raring-%s) `[1:], arch.HostArch())) c.Check(err, gc.ErrorMatches, "failed to bootstrap model: cannot upload bootstrap tools: an error") }
func (s *UseEnvironmentSuite) TestUseEnvAlreadyExisting(c *gc.C) { s.makeLocalEnvironment(c, "unique", "", "") ctx, err := s.run(c, "unique") c.Assert(err, gc.ErrorMatches, "existing environment") expected := `You have an existing environment called "unique", use --name to specify a different local name.` c.Assert(testing.Stderr(ctx), jc.Contains, expected) }
func (s *RegisterSuite) TestRegisterMultipleModels(c *gc.C) { s.refreshModels = func(store jujuclient.ClientStore, controller, account string) error { for _, name := range [...]string{"model1", "model2"} { err := store.UpdateModel(controller, account, name, jujuclient.ModelDetails{ ModelUUID: "df136476-12e9-11e4-8a70-b2227cce2b54", }) c.Assert(err, jc.ErrorIsNil) } return nil } ctx := s.testRegister(c) // 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", "bob@local") c.Assert(err, jc.Satisfies, errors.IsNotFound) stderr := testing.Stderr(ctx) c.Assert(stderr, gc.Equals, ` Please set a name for this controller: Enter password: Confirm password: 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:]) }
func (s *DestroySuite) TestDestroyReturnsBlocks(c *gc.C) { s.api.err = ¶ms.Error{Code: params.CodeOperationBlocked} s.api.blocks = []params.ModelBlockInfo{ params.ModelBlockInfo{ Name: "test1", UUID: "test1-uuid", OwnerTag: "cheryl@local", Blocks: []string{ "BlockDestroy", }, }, params.ModelBlockInfo{ Name: "test2", UUID: "test2-uuid", OwnerTag: "bob@local", Blocks: []string{ "BlockDestroy", "BlockChange", }, }, } ctx, _ := s.runDestroyCommand(c, "test1", "-y", "--destroy-all-models") c.Assert(testing.Stderr(ctx), gc.Equals, ""+ "NAME MODEL UUID OWNER BLOCKS\n"+ "test1 test1-uuid cheryl@local destroy-model\n"+ "test2 test2-uuid bob@local destroy-model,all-changes\n") }
func (s *cmdLoginSuite) TestLoginCommand(c *gc.C) { s.createTestUser(c) // logout "admin" first; we'll need to give it // a non-random password before we can do so. s.changeUserPassword(c, "admin", "hunter2") s.run(c, nil, "logout") context := s.run(c, strings.NewReader("hunter2\nhunter2\n"), "login", "test") c.Assert(testing.Stdout(context), gc.Equals, "") c.Assert(testing.Stderr(context), gc.Equals, ` password: You are now logged in to "kontroll" as "test@local". `[1:]) // We should have a macaroon, but no password, in the client store. store := jujuclient.NewFileClientStore() accountDetails, err := store.AccountByName("kontroll", "test@local") c.Assert(err, jc.ErrorIsNil) c.Assert(accountDetails.Password, gc.Equals, "") c.Assert(accountDetails.Macaroon, gc.Not(gc.Equals), "") // We should be able to login with the macaroon. s.run(c, nil, "status") }
func (s *cmdControllerSuite) TestAddModel(c *gc.C) { // The JujuConnSuite doesn't set up an ssh key in the fake home dir, // so fake one on the command line. The dummy provider also expects // a config value for 'controller'. context := s.run(c, "add-model", "new-model", "authorized-keys=fake-key", "controller=false") c.Check(testing.Stdout(context), gc.Equals, "") c.Check(testing.Stderr(context), gc.Equals, "added model \"new-model\"\n") // Make sure that the saved server details are sufficient to connect // to the api server. accountDetails, err := s.ControllerStore.AccountByName("kontroll", "admin@local") c.Assert(err, jc.ErrorIsNil) modelDetails, err := s.ControllerStore.ModelByName("kontroll", "admin@local", "new-model") c.Assert(err, jc.ErrorIsNil) api, err := juju.NewAPIConnection(juju.NewAPIConnectionParams{ Store: s.ControllerStore, ControllerName: "kontroll", AccountDetails: accountDetails, ModelUUID: modelDetails.ModelUUID, BootstrapConfig: noBootstrapConfig, DialOpts: api.DefaultDialOpts(), }) c.Assert(err, jc.ErrorIsNil) api.Close() }
func (s *cmdLoginSuite) TestLoginCommand(c *gc.C) { s.createTestUser(c) // logout "admin" first; we'll need to give it // a non-random password before we can do so. s.changeUserPassword(c, "admin", "hunter2") s.run(c, nil, "logout") // TODO(axw) 2016-09-08 #1621375 // "juju logout" should clear the cookies for the controller. os.Remove(filepath.Join(utils.Home(), ".go-cookies")) context := s.run(c, strings.NewReader("hunter2\nhunter2\n"), "login", "test") c.Assert(testing.Stdout(context), gc.Equals, "") c.Assert(testing.Stderr(context), gc.Equals, ` please enter password for test@local on kontroll: You are now logged in to "kontroll" as "test@local". `[1:]) // We should have a macaroon, but no password, in the client store. store := jujuclient.NewFileClientStore() accountDetails, err := store.AccountDetails("kontroll") c.Assert(err, jc.ErrorIsNil) c.Assert(accountDetails.Password, gc.Equals, "") // We should be able to login with the macaroon. s.run(c, nil, "status") }
func (s *DeployCharmStoreSuite) TestDeployAuthorization(c *gc.C) { // Upload the two charms required to upload the bundle. testcharms.UploadCharm(c, s.client, "trusty/mysql-0", "mysql") testcharms.UploadCharm(c, s.client, "trusty/wordpress-1", "wordpress") // Run the tests. for i, test := range deployAuthorizationTests { c.Logf("test %d: %s", i, test.about) // Upload the charm or bundle under test. url := charm.MustParseURL(test.uploadURL) if url.Series == "bundle" { url, _ = testcharms.UploadBundle(c, s.client, test.uploadURL, "wordpress-simple") } else { url, _ = testcharms.UploadCharm(c, s.client, test.uploadURL, "wordpress") } // Change the ACL of the uploaded entity if required in this case. if test.readPermUser != "" { s.changeReadPerm(c, url, test.readPermUser) } ctx, err := coretesting.RunCommand(c, envcmd.Wrap(&deployCommand{}), test.deployURL, fmt.Sprintf("wordpress%d", i)) if test.expectError != "" { c.Assert(err, gc.ErrorMatches, test.expectError) continue } c.Assert(err, jc.ErrorIsNil) output := strings.Trim(coretesting.Stderr(ctx), "\n") c.Assert(output, gc.Equals, strings.TrimSpace(test.expectOutput)) } }
func (s *retryProvisioningSuite) TestResolved(c *gc.C) { m, err := s.State.AddOneMachine(state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobManageEnviron}, }) c.Assert(err, gc.IsNil) err = m.SetStatus(params.StatusError, "broken", nil) c.Assert(err, gc.IsNil) _, err = s.State.AddOneMachine(state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, }) c.Assert(err, gc.IsNil) for i, t := range resolvedMachineTests { c.Logf("test %d: %v", i, t.args) context, err := testing.RunCommand(c, envcmd.Wrap(&RetryProvisioningCommand{}), t.args...) if t.err != "" { c.Check(err, gc.ErrorMatches, t.err) continue } else { c.Check(err, gc.IsNil) } output := testing.Stderr(context) stripped := strings.Replace(output, "\n", "", -1) c.Check(stripped, gc.Equals, t.stdErr) if t.args[0] == "0" { status, info, data, err := m.Status() c.Check(err, gc.IsNil) c.Check(status, gc.Equals, params.StatusError) c.Check(info, gc.Equals, "broken") c.Check(data["transient"], jc.IsTrue) } } }