func (s *SSHSuite) testSSHCommandHostAddressRetry(c *gc.C, proxy bool) { m := s.makeMachines(1, c, false) ctx := coretesting.Context(c) var called int next := func() bool { called++ return called < 2 } attemptStarter := &callbackAttemptStarter{next: next} s.PatchValue(&sshHostFromTargetAttemptStrategy, attemptStarter) // Ensure that the ssh command waits for a public address, or the attempt // strategy's Done method returns false. args := []string{"--proxy=" + fmt.Sprint(proxy), "0"} code := cmd.Main(envcmd.Wrap(&SSHCommand{}), ctx, args) c.Check(code, gc.Equals, 1) c.Assert(called, gc.Equals, 2) called = 0 attemptStarter.next = func() bool { called++ if called > 1 { s.setAddresses(m[0], c) } return true } code = cmd.Main(envcmd.Wrap(&SSHCommand{}), ctx, args) c.Check(code, gc.Equals, 0) c.Assert(called, gc.Equals, 2) }
// In the case where we cannot examine an environment, we want the // error to propagate back up to the user. func (s *BootstrapSuite) TestBootstrapPropagatesEnvErrors(c *gc.C) { //TODO(bogdanteleaga): fix this for windows once permissions are fixed if runtime.GOOS == "windows" { c.Skip("bug 1403084: this is very platform specific. When/if we will support windows state machine, this will probably be rewritten.") } const envName = "devenv" env := resetJujuHome(c, envName) defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) s.PatchValue(&environType, func(string) (string, error) { return "", nil }) _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, jc.ErrorIsNil) // Change permissions on the jenv file to simulate some kind of // unexpected error when trying to read info from the environment jenvFile := gitjujutesting.HomePath(".juju", "environments", envName+".jenv") err = os.Chmod(jenvFile, os.FileMode(0200)) c.Assert(err, jc.ErrorIsNil) // The second bootstrap should fail b/c of the propogated error _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.ErrorMatches, "there was an issue examining the environment: .*") }
// In the case where we cannot examine an environment, we want the // error to propagate back up to the user. func (s *BootstrapSuite) TestBootstrapPropagatesEnvErrors(c *gc.C) { env := resetJujuHome(c) defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) const envName = "peckham" _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.IsNil) // Change permissions on the jenv file to simulate some kind of // unexpected error when trying to read info from the environment jenvFile := gitjujutesting.HomePath(".juju", "environments", envName+".jenv") err = os.Chmod(jenvFile, os.FileMode(0200)) c.Assert(err, gc.IsNil) // The second bootstrap should fail b/c of the propogated error _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.ErrorMatches, "there was an issue examining the environment: .*") }
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 := envcmd.Wrap(debugHooksCmd).Init(t.args) if err == nil { err = envcmd.Wrap(debugHooksCmd).Run(ctx) } if t.error != "" { c.Assert(err, gc.ErrorMatches, t.error) } else { c.Assert(err, jc.ErrorIsNil) } } }
// Main registers subcommands for the juju-metadata executable, and hands over control // to the cmd package. This function is not redundant with main, because it // provides an entry point for testing with arbitrary command line arguments. func Main(args []string) { ctx, err := cmd.DefaultContext() if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(2) } if err := juju.InitJujuHome(); err != nil { fmt.Fprintf(os.Stderr, "error: %s\n", err) os.Exit(2) } metadatacmd := cmd.NewSuperCommand(cmd.SuperCommandParams{ Name: "metadata", UsagePrefix: "juju", Doc: metadataDoc, Purpose: "tools for generating and validating image and tools metadata", Log: &cmd.Log{}}) metadatacmd.Register(envcmd.Wrap(&ValidateImageMetadataCommand{})) metadatacmd.Register(envcmd.Wrap(&ImageMetadataCommand{})) metadatacmd.Register(envcmd.Wrap(&ToolsMetadataCommand{})) metadatacmd.Register(envcmd.Wrap(&ValidateToolsMetadataCommand{})) metadatacmd.Register(&SignMetadataCommand{}) os.Exit(cmd.Main(metadatacmd, ctx, args[1:])) }
func (s *RemoveUserSuite) TestRemoveUser(c *gc.C) { _, err := testing.RunCommand(c, envcmd.Wrap(&UserAddCommand{}), "foobar") c.Assert(err, gc.IsNil) _, err = testing.RunCommand(c, envcmd.Wrap(&RemoveUserCommand{}), "foobar") c.Assert(err, gc.IsNil) }
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(envcmd.Wrap(cmd), append([]string{"--reset-previous-upgrade"}, args...)) c.Assert(err, jc.ErrorIsNil) err = envcmd.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 *SetEnvironmentSuite) TestChangeAsCommandPair(c *gc.C) { _, err := testing.RunCommand(c, envcmd.Wrap(&SetEnvironmentCommand{}), "default-series=raring") c.Assert(err, gc.IsNil) context, err := testing.RunCommand(c, envcmd.Wrap(&GetEnvironmentCommand{}), "default-series") c.Assert(err, gc.IsNil) output := strings.TrimSpace(testing.Stdout(context)) c.Assert(output, gc.Equals, "raring") }
func (s *BootstrapSuite) TestBootstrapTwice(c *gc.C) { const envName = "devenv" s.patchVersionAndSeries(c, envName) _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, jc.ErrorIsNil) _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", envName) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") }
// NewPoolSuperCommand creates the storage pool super subcommand and // registers the subcommands that it supports. func NewPoolSuperCommand() cmd.Command { poolcmd := jujucmd.NewSubSuperCommand(cmd.SuperCommandParams{ Name: "pool", Doc: poolCmdDoc, UsagePrefix: "juju storage", Purpose: poolCmdPurpose, }) poolcmd.Register(envcmd.Wrap(&PoolListCommand{})) poolcmd.Register(envcmd.Wrap(&PoolCreateCommand{})) return poolcmd }
// NewSuperCommand creates the user supercommand and registers the subcommands // that it supports. func NewSuperCommand() cmd.Command { machineCmd := cmd.NewSuperCommand(cmd.SuperCommandParams{ Name: "machine", Doc: machineCommandDoc, UsagePrefix: "juju", Purpose: machineCommandPurpose, }) machineCmd.Register(envcmd.Wrap(&AddCommand{})) machineCmd.Register(envcmd.Wrap(&RemoveCommand{})) return machineCmd }
// NewSuperCommand creates the user supercommand and registers the subcommands // that it supports. func NewSuperCommand() cmd.Command { usercmd := cmd.NewSuperCommand(cmd.SuperCommandParams{ Name: "cached-images", Doc: cachedimagesCommandDoc, UsagePrefix: "juju", Purpose: cachedImagesCommandPurpose, }) usercmd.Register(envcmd.Wrap(&DeleteCommand{})) usercmd.Register(envcmd.Wrap(&ListCommand{})) return usercmd }
func (s *EndpointSuite) TestNoEndpoints(c *gc.C) { // Run command once to create store in test. _, err := coretesting.RunCommand(c, envcmd.Wrap(&EndpointCommand{})) c.Assert(err, gc.IsNil) info := s.APIInfo(c) s.setAPIAddresses(c) ctx, err := coretesting.RunCommand(c, envcmd.Wrap(&EndpointCommand{})) c.Assert(err, gc.IsNil) c.Assert(ctx.Stderr.(*bytes.Buffer).String(), gc.Equals, "") output := string(ctx.Stdout.(*bytes.Buffer).Bytes()) c.Assert(output, gc.Equals, fmt.Sprintf("%s\n", info.Addrs[0])) }
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(envcmd.Wrap(cmd), []string{}) c.Assert(err, jc.ErrorIsNil) // Block operation s.BlockAllChanges(c, "TestBlockUpgradeInProgress") err = envcmd.Wrap(cmd).Run(coretesting.Context(c)) s.AssertBlocked(c, err, ".*To unblock changes.*") }
// NewSuperCommand returns a new action super-command. func NewSuperCommand() cmd.Command { actionCmd := cmd.NewSuperCommand( cmd.SuperCommandParams{ Name: "action", Doc: actionDoc, UsagePrefix: "juju", Purpose: actionPurpose, }) actionCmd.Register(envcmd.Wrap(&DefinedCommand{})) actionCmd.Register(envcmd.Wrap(&DoCommand{})) actionCmd.Register(envcmd.Wrap(&FetchCommand{})) actionCmd.Register(envcmd.Wrap(&StatusCommand{})) return actionCmd }
func NewUserCommand() cmd.Command { usercmd := &UserCommand{ SuperCommand: cmd.NewSuperCommand(cmd.SuperCommandParams{ Name: "user", Doc: userCommandDoc, UsagePrefix: "juju", Purpose: userCommandPurpose, }), } // Define each subcommand in a separate "user_FOO.go" source file // (with tests in user_FOO_test.go) and wire in here. usercmd.Register(envcmd.Wrap(&UserAddCommand{})) usercmd.Register(envcmd.Wrap(&UserChangePasswordCommand{})) return usercmd }
// NewSuperCommand creates the storage supercommand and // registers the subcommands that it supports. func NewSuperCommand() cmd.Command { storagecmd := cmd.NewSuperCommand( cmd.SuperCommandParams{ Name: "storage", Doc: storageCmdDoc, UsagePrefix: "juju", Purpose: storageCmdPurpose, }) storagecmd.Register(envcmd.Wrap(&ShowCommand{})) storagecmd.Register(envcmd.Wrap(&ListCommand{})) storagecmd.Register(envcmd.Wrap(&AddCommand{})) storagecmd.Register(NewPoolSuperCommand()) storagecmd.Register(NewVolumeSuperCommand()) return storagecmd }
// NewSuperBlockCommand creates the block supercommand and // registers the subcommands that it supports. func NewSuperBlockCommand() cmd.Command { blockcmd := Command{ SuperCommand: *cmd.NewSuperCommand( cmd.SuperCommandParams{ Name: "block", Doc: superBlockCmdDoc, UsagePrefix: "juju", Purpose: superBlockCmdPurpose, })} blockcmd.Register(envcmd.Wrap(&DestroyCommand{})) blockcmd.Register(envcmd.Wrap(&RemoveCommand{})) blockcmd.Register(envcmd.Wrap(&ChangeCommand{})) blockcmd.Register(envcmd.Wrap(&ListCommand{})) return &blockcmd }
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()), ) dummyCharm, err := s.State.AddCharm(ch, curl, "dummy-path", "dummy-1-sha256") 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 := envcmd.Wrap(scpcmd).Init(t.args) c.Check(err, jc.ErrorIsNil) err = envcmd.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 *BootstrapSuite) TestBootstrapKeepBroken(c *gc.C) { resetJujuHome(c, "devenv") devVersion := version.Current // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. devVersion.Build = 1234 s.PatchValue(&version.Current, devVersion) opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(new(BootstrapCommand)), "-e", "brokenenv", "--keep-broken") err := <-errc c.Assert(err, gc.ErrorMatches, "failed to bootstrap environment: dummy.Bootstrap is broken") done := false for !done { select { case op, ok := <-opc: if !ok { done = true break } switch op.(type) { case dummy.OpDestroy: c.Error("unexpected call to env.Destroy") break } default: break } } }
func (s *BootstrapSuite) TestBootstrapDestroy(c *gc.C) { resetJujuHome(c, "devenv") devVersion := version.Current // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. devVersion.Build = 1234 s.PatchValue(&version.Current, devVersion) opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(new(BootstrapCommand)), "-e", "brokenenv") err := <-errc c.Assert(err, gc.ErrorMatches, "failed to bootstrap environment: dummy.Bootstrap is broken") var opDestroy *dummy.OpDestroy for opDestroy == nil { select { case op := <-opc: switch op := op.(type) { case dummy.OpDestroy: opDestroy = &op } default: c.Error("expected call to env.Destroy") return } } c.Assert(opDestroy.Error, gc.ErrorMatches, "dummy.Destroy is broken") }
func (s *BootstrapSuite) TestMissingToolsError(c *gc.C) { s.setupAutoUploadTest(c, "1.8.3", "precise") _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{})) c.Assert(err, gc.ErrorMatches, "failed to bootstrap environment: Juju cannot bootstrap because no tools are available for your environment(.|\n)*") }
func (s *BootstrapSuite) TestAutoUploadOnlyForDev(c *gc.C) { s.setupAutoUploadTest(c, "1.8.3", "precise") _, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(new(BootstrapCommand))) err := <-errc c.Assert(err, gc.ErrorMatches, "failed to bootstrap environment: Juju cannot bootstrap because no tools are available for your environment(.|\n)*") }
func (s *BootstrapSuite) TestRunEnvNameMissing(c *gc.C) { s.PatchValue(&getEnvName, func(*BootstrapCommand) string { return "" }) _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{})) c.Check(err, gc.ErrorMatches, "the name of the environment must be specified") }
func (s *BootstrapSuite) TestBootstrapTwice(c *gc.C) { env := resetJujuHome(c, "devenv") defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) _, err := coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", "devenv") c.Assert(err, jc.ErrorIsNil) _, err = coretesting.RunCommand(c, envcmd.Wrap(&BootstrapCommand{}), "-e", "devenv") c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") }
func (s *BlockCommandSuite) TestBlockCmdMoreArgs(c *gc.C) { _, err := testing.RunCommand(c, envcmd.Wrap(&block.DestroyCommand{}), "change", "too much") c.Assert( err, gc.ErrorMatches, `.*can only specify block message.*`) }
func (s *DeploySuite) TestInitErrors(c *gc.C) { for i, t := range initErrorTests { c.Logf("test %d", i) err := coretesting.InitCommand(envcmd.Wrap(&deployCommand{}), t.args) c.Assert(err, gc.ErrorMatches, t.err) } }
func (s *DeploySuite) TestAddMetricCredentialsHttp(c *gc.C) { handler := &testMetricsRegistrationHandler{} server := httptest.NewServer(handler) defer server.Close() var called bool setter := &testMetricCredentialsSetter{ assert: func(serviceName string, data []byte) { called = true c.Assert(serviceName, gc.DeepEquals, "metered") var b []byte err := json.Unmarshal(data, &b) c.Assert(err, gc.IsNil) c.Assert(string(b), gc.Equals, "hello registration") }, } cleanup := jujutesting.PatchValue(&getMetricCredentialsAPI, func(_ api.Connection) (metricCredentialsAPI, error) { return setter, nil }) defer cleanup() testcharms.Repo.ClonedDirPath(s.SeriesPath, "metered") _, err := coretesting.RunCommand(c, envcmd.Wrap(&deployCommand{RegisterURL: server.URL}), "local:quantal/metered-1") c.Assert(err, jc.ErrorIsNil) curl := charm.MustParseURL("local:quantal/metered-1") s.AssertService(c, "metered", curl, 1, 0) c.Assert(called, jc.IsTrue) c.Assert(handler.registrationCalls, gc.HasLen, 1) c.Assert(handler.registrationCalls[0].CharmURL, gc.DeepEquals, "local:quantal/metered-1") c.Assert(handler.registrationCalls[0].ServiceName, gc.DeepEquals, "metered") }
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 newDeleteImageMetadataCommand() cmd.Command { deleteCmd := &deleteImageMetadataCommand{} deleteCmd.newAPIFunc = func() (MetadataDeleteAPI, error) { return deleteCmd.NewImageMetadataAPI() } return envcmd.Wrap(deleteCmd) }