func (s *DebugHooksSuite) TestDebugHooksCommand(c *gc.C) { //TODO(bogdanteleaga): Fix once debughooks are supported on windows if runtime.GOOS == "windows" { c.Skip("bug 1403084: Skipping on windows for now") } machines := s.makeMachines(3, c, true) dummy := s.AddTestingCharm(c, "dummy") srv := s.AddTestingService(c, "mysql", dummy) s.addUnit(srv, machines[0], c) srv = s.AddTestingService(c, "mongodb", dummy) s.addUnit(srv, machines[1], c) s.addUnit(srv, machines[2], c) for i, t := range debugHooksTests { c.Logf("test %d: %s\n\t%s\n", i, t.info, t.args) ctx := coretesting.Context(c) debugHooksCmd := &debugHooksCommand{} debugHooksCmd.proxy = true err := modelcmd.Wrap(debugHooksCmd).Init(t.args) if err == nil { err = modelcmd.Wrap(debugHooksCmd).Run(ctx) } if t.error != "" { c.Assert(err, gc.ErrorMatches, t.error) } else { c.Assert(err, jc.ErrorIsNil) } } }
func (s *UpgradeJujuSuite) TestResetPreviousUpgrade(c *gc.C) { fakeAPI := NewFakeUpgradeJujuAPI(c, s.State) fakeAPI.patch(s) ctx := coretesting.Context(c) var stdin bytes.Buffer ctx.Stdin = &stdin run := func(answer string, expect bool, args ...string) { stdin.Reset() if answer != "" { stdin.WriteString(answer) } fakeAPI.reset() cmd := &upgradeJujuCommand{} err := coretesting.InitCommand(modelcmd.Wrap(cmd), append([]string{"--reset-previous-upgrade"}, args...)) c.Assert(err, jc.ErrorIsNil) err = modelcmd.Wrap(cmd).Run(ctx) if expect { c.Assert(err, jc.ErrorIsNil) } else { c.Assert(err, gc.ErrorMatches, "previous upgrade not reset and no new upgrade triggered") } c.Assert(fakeAPI.abortCurrentUpgradeCalled, gc.Equals, expect) expectedVersion := version.Number{} if expect { expectedVersion = fakeAPI.nextVersion.Number } c.Assert(fakeAPI.setVersionCalledWith, gc.Equals, expectedVersion) } const expectUpgrade = true const expectNoUpgrade = false // EOF on stdin - equivalent to answering no. run("", expectNoUpgrade) // -y on command line - no confirmation required run("", expectUpgrade, "-y") // --yes on command line - no confirmation required run("", expectUpgrade, "--yes") // various ways of saying "yes" to the prompt for _, answer := range []string{"y", "Y", "yes", "YES"} { run(answer, expectUpgrade) } // various ways of saying "no" to the prompt for _, answer := range []string{"n", "N", "no", "foo"} { run(answer, expectNoUpgrade) } }
func (s *SCPSuite) TestSCPCommand(c *gc.C) { m := s.makeMachines(4, c, true) ch := testcharms.Repo.CharmDir("dummy") curl := charm.MustParseURL( fmt.Sprintf("local:quantal/%s-%d", ch.Meta().Name, ch.Revision()), ) info := state.CharmInfo{ Charm: ch, ID: curl, StoragePath: "dummy-path", SHA256: "dummy-1-sha256", } dummyCharm, err := s.State.AddCharm(info) c.Assert(err, jc.ErrorIsNil) srv := s.AddTestingService(c, "mysql", dummyCharm) s.addUnit(srv, m[0], c) srv = s.AddTestingService(c, "mongodb", dummyCharm) s.addUnit(srv, m[1], c) s.addUnit(srv, m[2], c) srv = s.AddTestingService(c, "ipv6-svc", dummyCharm) s.addUnit(srv, m[3], c) // Simulate machine 3 has a public IPv6 address. ipv6Addr := network.NewScopedAddress("2001:db8::1", network.ScopePublic) err = m[3].SetProviderAddresses(ipv6Addr) c.Assert(err, jc.ErrorIsNil) for i, t := range scpTests { c.Logf("test %d: %s -> %s\n", i, t.about, t.args) ctx := coretesting.Context(c) scpcmd := &scpCommand{} scpcmd.proxy = t.proxy err := modelcmd.Wrap(scpcmd).Init(t.args) c.Check(err, jc.ErrorIsNil) err = modelcmd.Wrap(scpcmd).Run(ctx) if t.error != "" { c.Check(err, gc.ErrorMatches, t.error) c.Check(t.result, gc.Equals, "") } else { c.Check(err, jc.ErrorIsNil) // we suppress stdout from scp c.Check(ctx.Stderr.(*bytes.Buffer).String(), gc.Equals, "") c.Check(ctx.Stdout.(*bytes.Buffer).String(), gc.Equals, "") data, err := ioutil.ReadFile(filepath.Join(s.bin, "scp.args")) c.Check(err, jc.ErrorIsNil) actual := string(data) if t.proxy { actual = strings.Replace(actual, ".dns", ".internal", 2) } c.Check(actual, gc.Equals, t.result) } } }
func (s *UpgradeJujuSuite) TestBlockUpgradeInProgress(c *gc.C) { fakeAPI := NewFakeUpgradeJujuAPI(c, s.State) fakeAPI.setVersionErr = common.OperationBlockedError("the operation has been blocked") fakeAPI.patch(s) cmd := &upgradeJujuCommand{} err := coretesting.InitCommand(modelcmd.Wrap(cmd), []string{}) c.Assert(err, jc.ErrorIsNil) // Block operation s.BlockAllChanges(c, "TestBlockUpgradeInProgress") err = modelcmd.Wrap(cmd).Run(coretesting.Context(c)) s.AssertBlocked(c, err, ".*To enable changes.*") }
func NewRestoreCommandForTest( store jujuclient.ClientStore, api RestoreAPI, getArchive func(string) (ArchiveReader, *params.BackupsMetadataResult, error), newEnviron func(environs.OpenParams) (environs.Environ, error), getRebootstrapParams func(*cmd.Context, string, *params.BackupsMetadataResult) (*restoreBootstrapParams, error), ) cmd.Command { c := &restoreCommand{ getArchiveFunc: getArchive, newEnvironFunc: newEnviron, getRebootstrapParamsFunc: getRebootstrapParams, newAPIClientFunc: func() (RestoreAPI, error) { return api, nil }, waitForAgentFunc: func(ctx *cmd.Context, c *modelcmd.ModelCommandBase, controllerName, hostedModelName string) error { return nil }, } if getRebootstrapParams == nil { c.getRebootstrapParamsFunc = c.getRebootstrapParams } if newEnviron == nil { c.newEnvironFunc = environs.New } c.Log = &cmd.Log{} c.SetClientStore(store) return modelcmd.Wrap(c) }
func newVolumeListCommand() cmd.Command { cmd := &volumeListCommand{} cmd.newAPIFunc = func() (VolumeListAPI, error) { return cmd.NewStorageAPI() } return modelcmd.Wrap(cmd) }
func newFilesystemListCommand() cmd.Command { cmd := &filesystemListCommand{} cmd.newAPIFunc = func() (FilesystemListAPI, error) { return cmd.NewStorageAPI() } return modelcmd.Wrap(cmd) }
// NewDestroyCommand returns a command used to destroy a model. func NewDestroyCommand() cmd.Command { return modelcmd.Wrap( &destroyCommand{}, modelcmd.WrapSkipDefaultModel, modelcmd.WrapSkipModelFlags, ) }
func NewDeployCommandWithDefaultAPI(steps []DeployStep) cmd.Command { deployCmd := &DeployCommand{Steps: steps} cmd := modelcmd.Wrap(deployCmd) deployCmd.NewAPIRoot = func() (DeployAPI, error) { apiRoot, err := deployCmd.ModelCommandBase.NewAPIRoot() if err != nil { return nil, errors.Trace(err) } bakeryClient, err := deployCmd.BakeryClient() if err != nil { return nil, errors.Trace(err) } cstoreClient := newCharmStoreClient(bakeryClient).WithChannel(deployCmd.Channel) adapter := &deployAPIAdapter{ Connection: apiRoot, apiClient: &apiClient{Client: apiRoot.Client()}, charmsClient: &charmsClient{Client: apicharms.NewClient(apiRoot)}, applicationClient: &applicationClient{Client: application.NewClient(apiRoot)}, modelConfigClient: &modelConfigClient{Client: modelconfig.NewClient(apiRoot)}, charmstoreClient: &charmstoreClient{Client: cstoreClient}, annotationsClient: &annotationsClient{Client: annotations.NewClient(apiRoot)}, charmRepoClient: &charmRepoClient{CharmStore: charmrepo.NewCharmStoreFromClient(cstoreClient)}, } return adapter, nil } return cmd }
func newAddCommand() cmd.Command { cmd := &addCommand{} cmd.newAPIFunc = func() (StorageAddAPI, error) { return cmd.NewStorageAPI() } return modelcmd.Wrap(cmd) }
// NewDestroyCommand returns a command used to destroy a model. func NewDestroyCommand() cmd.Command { return modelcmd.Wrap( &destroyCommand{}, modelcmd.ModelSkipDefault, modelcmd.ModelSkipFlags, ) }
func NewAddCommandForTest(api StorageAddAPI, store jujuclient.ClientStore) cmd.Command { cmd := &addCommand{newAPIFunc: func() (StorageAddAPI, error) { return api, nil }} cmd.SetClientStore(store) return modelcmd.Wrap(cmd) }
func NewPoolCreateCommandForTest(api PoolCreateAPI, store jujuclient.ClientStore) cmd.Command { cmd := &poolCreateCommand{newAPIFunc: func() (PoolCreateAPI, error) { return api, nil }} cmd.SetClientStore(store) return modelcmd.Wrap(cmd) }
// NewShowCommand returns a command that shows storage details // on the specified machine func NewShowCommand() cmd.Command { cmd := &showCommand{} cmd.newAPIFunc = func() (StorageShowAPI, error) { return cmd.NewStorageAPI() } return modelcmd.Wrap(cmd) }
// NewListCommand returns a command for listing storage instances. func NewListCommand() cmd.Command { cmd := &listCommand{} cmd.newAPIFunc = func() (StorageListAPI, error) { return cmd.NewStorageAPI() } return modelcmd.Wrap(cmd) }
func newDeleteImageMetadataCommand() cmd.Command { deleteCmd := &deleteImageMetadataCommand{} deleteCmd.newAPIFunc = func() (MetadataDeleteAPI, error) { return deleteCmd.NewImageMetadataAPI() } return modelcmd.Wrap(deleteCmd) }
func newPoolCreateCommand() cmd.Command { cmd := &poolCreateCommand{} cmd.newAPIFunc = func() (PoolCreateAPI, error) { return cmd.NewStorageAPI() } return modelcmd.Wrap(cmd) }
// NewEnableCommand returns a new command that eanbles previously disabled // command sets. func NewEnableCommand() cmd.Command { return modelcmd.Wrap(&enableCommand{ apiFunc: func(c newAPIRoot) (unblockClientAPI, error) { return getBlockAPI(c) }, }) }
func RunPlugin(ctx *cmd.Context, subcommand string, args []string) error { cmdName := JujuPluginPrefix + subcommand plugin := modelcmd.Wrap(&PluginCommand{name: cmdName}) // We process common flags supported by Juju commands. // To do this, we extract only those supported flags from the // argument list to avoid confusing flags.Parse(). flags := gnuflag.NewFlagSet(cmdName, gnuflag.ContinueOnError) flags.SetOutput(ioutil.Discard) plugin.SetFlags(flags) jujuArgs := extractJujuArgs(args) if err := flags.Parse(false, jujuArgs); err != nil { return err } if err := plugin.Init(args); err != nil { return err } err := plugin.Run(ctx) _, execError := err.(*exec.Error) // exec.Error results are for when the executable isn't found, in // those cases, drop through. if !execError { return err } return &cmd.UnrecognizedCommand{Name: subcommand} }
func (s *UpgradeJujuSuite) TestUpgradeUnknownSeriesInStreams(c *gc.C) { fakeAPI := NewFakeUpgradeJujuAPI(c, s.State) fakeAPI.addTools("2.1.0-weird-amd64") fakeAPI.patch(s) cmd := &upgradeJujuCommand{} err := coretesting.InitCommand(modelcmd.Wrap(cmd), []string{}) c.Assert(err, jc.ErrorIsNil) err = modelcmd.Wrap(cmd).Run(coretesting.Context(c)) c.Assert(err, gc.IsNil) // ensure find tools was called c.Assert(fakeAPI.findToolsCalled, jc.IsTrue) c.Assert(fakeAPI.tools, gc.DeepEquals, []string{"2.1.0-weird-amd64", fakeAPI.nextVersion.String()}) }
// NewAddCommand returns an AddCommand with the api provided as specified. func NewAddCommandForTest(api AddMachineAPI, mmApi MachineManagerAPI) (cmd.Command, *AddCommand) { cmd := &addCommand{ api: api, machineManagerAPI: mmApi, } return modelcmd.Wrap(cmd), &AddCommand{cmd} }
func (*RunSuite) TestTimeoutArgParsing(c *gc.C) { for i, test := range []struct { message string args []string errMatch string timeout time.Duration }{{ message: "default time", args: []string{"--all", "sudo reboot"}, timeout: 5 * time.Minute, }, { message: "invalid time", args: []string{"--timeout=foo", "--all", "sudo reboot"}, errMatch: `invalid value "foo" for flag --timeout: time: invalid duration foo`, }, { message: "two hours", args: []string{"--timeout=2h", "--all", "sudo reboot"}, timeout: 2 * time.Hour, }, { message: "3 minutes 30 seconds", args: []string{"--timeout=3m30s", "--all", "sudo reboot"}, timeout: (3 * time.Minute) + (30 * time.Second), }} { c.Log(fmt.Sprintf("%v: %s", i, test.message)) cmd := &runCommand{} runCmd := modelcmd.Wrap(cmd) testing.TestInit(c, runCmd, test.args, test.errMatch) if test.errMatch == "" { c.Check(cmd.timeout, gc.Equals, test.timeout) } } }
func (s *ModelCommandSuite) TestWrapWithoutFlags(c *gc.C) { cmd := new(testCommand) wrapped := modelcmd.Wrap(cmd, modelcmd.ModelSkipFlags) args := []string{"-m", "testenv"} err := cmdtesting.InitCommand(wrapped, args) // 1st position is always the flag msg := fmt.Sprintf("flag provided but not defined: %v", args[0]) c.Assert(err, gc.ErrorMatches, msg) }
func (s *ValidateToolsMetadataSuite) TestInitErrors(c *gc.C) { for i, t := range validateInitToolsErrorTests { c.Logf("test %d", i) cmd := &validateToolsMetadataCommand{} cmd.SetClientStore(s.store) err := coretesting.InitCommand(modelcmd.Wrap(cmd), t.args) c.Check(err, gc.ErrorMatches, t.err) } }
func (s *PublishSuite) TestFullPublish(c *gc.C) { addMeta(c, s.branch, "") digest, err := s.branch.RevisionId() c.Assert(err, jc.ErrorIsNil) pushBranch := bzr.New(c.MkDir()) err = pushBranch.Init() c.Assert(err, jc.ErrorIsNil) cmd := &publishCommand{} cmd.ChangePushLocation(func(location string) string { c.Assert(location, gc.Equals, "lp:~user/charms/precise/wordpress/trunk") return pushBranch.Location() }) cmd.SetPollDelay(testing.ShortWait) var body string // The local digest isn't found. body = `{"cs:~user/precise/wordpress": {"kind": "", "errors": ["entry not found"]}}` gitjujutesting.Server.Response(200, nil, []byte(body)) // But the charm exists with an arbitrary non-matching digest. body = `{"cs:~user/precise/wordpress": {"kind": "published", "digest": "other-digest"}}` gitjujutesting.Server.Response(200, nil, []byte(body)) // After the branch is pushed we fake the publishing delay. body = `{"cs:~user/precise/wordpress": {"kind": "published", "digest": "other-digest"}}` gitjujutesting.Server.Response(200, nil, []byte(body)) // And finally report success. body = `{"cs:~user/precise/wordpress": {"kind": "published", "digest": %q, "revision": 42}}` gitjujutesting.Server.Response(200, nil, []byte(fmt.Sprintf(body, digest))) ctx, err := testing.RunCommandInDir(c, modelcmd.Wrap(cmd), []string{"cs:~user/precise/wordpress"}, s.dir) c.Assert(err, jc.ErrorIsNil) c.Assert(testing.Stdout(ctx), gc.Equals, "cs:~user/precise/wordpress-42\n") // Ensure the branch was actually pushed. pushDigest, err := pushBranch.RevisionId() c.Assert(err, jc.ErrorIsNil) c.Assert(pushDigest, gc.Equals, digest) // And that all the requests were sent with the proper data. req := gitjujutesting.Server.WaitRequest() c.Assert(req.URL.Path, gc.Equals, "/charm-event") c.Assert(req.Form.Get("charms"), gc.Equals, "cs:~user/precise/wordpress@"+digest) for i := 0; i < 3; i++ { // The second request grabs tip to see the current state, and the // following requests are done after pushing to see when it changes. req = gitjujutesting.Server.WaitRequest() c.Assert(req.URL.Path, gc.Equals, "/charm-event") c.Assert(req.Form.Get("charms"), gc.Equals, "cs:~user/precise/wordpress") } }
// NewDeployCommand returns a command to deploy services. func NewDeployCommand() cmd.Command { return modelcmd.Wrap(&DeployCommand{ Steps: []DeployStep{ &RegisterMeteredCharm{ RegisterURL: planURL + "/plan/authorize", QueryURL: planURL + "/charm", }, &AllocateBudget{}}}) }
func newRestoreCommand() cmd.Command { restoreCmd := &restoreCommand{} restoreCmd.getEnvironFunc = restoreCmd.getEnviron restoreCmd.newAPIClientFunc = func() (RestoreAPI, error) { return restoreCmd.newClient() } restoreCmd.getArchiveFunc = getArchive return modelcmd.Wrap(restoreCmd) }
// NewRestoreCommand returns a command used to restore a backup. func NewRestoreCommand() cmd.Command { restoreCmd := &restoreCommand{} restoreCmd.getEnvironFunc = restoreCmd.getEnviron restoreCmd.newAPIClientFunc = func() (RestoreAPI, error) { return restoreCmd.newClient() } restoreCmd.getArchiveFunc = getArchive restoreCmd.waitForAgentFunc = common.WaitForAgentInitialisation return modelcmd.Wrap(restoreCmd) }
func (s *UpgradeJujuSuite) TestUpgradeInProgress(c *gc.C) { fakeAPI := NewFakeUpgradeJujuAPI(c, s.State) fakeAPI.setVersionErr = ¶ms.Error{ Message: "a message from the server about the problem", Code: params.CodeUpgradeInProgress, } fakeAPI.patch(s) cmd := &upgradeJujuCommand{} err := coretesting.InitCommand(modelcmd.Wrap(cmd), []string{}) c.Assert(err, jc.ErrorIsNil) err = modelcmd.Wrap(cmd).Run(coretesting.Context(c)) c.Assert(err, gc.ErrorMatches, "a message from the server about the problem\n"+ "\n"+ "Please wait for the upgrade to complete or if there was a problem with\n"+ "the last upgrade that has been resolved, consider running the\n"+ "upgrade-juju command with the --reset-previous-upgrade flag.", ) }
// NewListCommand returns the command that lists the disabled // commands for the model. func NewListCommand() cmd.Command { return modelcmd.Wrap(&listCommand{ apiFunc: func(c newAPIRoot) (blockListAPI, error) { return getBlockAPI(c) }, controllerAPIFunc: func(c newControllerAPIRoot) (controllerListAPI, error) { return getControllerAPI(c) }, }) }