Flatten subnet commands #5240

Merged
merged 3 commits into from Apr 21, 2016
Jump to file or symbol
Failed to load files and symbols.
+55 −169
Split
@@ -311,8 +311,12 @@ func registerCommands(r commandRegistry, ctx *cmd.Context) {
r.RegisterSuperAlias("list-spaces", "space", "list", nil)
// Manage subnets
- r.Register(subnet.NewSuperCommand())
- r.RegisterSuperAlias("add-subnet", "subnet", "add", nil)
+ r.Register(subnet.NewAddCommand())
+ r.Register(subnet.NewListCommand())
+ if featureflag.Enabled(feature.PostNetCLIMVP) {
+ r.Register(subnet.NewCreateCommand())
+ r.Register(subnet.NewRemoveCommand())
+ }
// Manage controllers
r.Register(controller.NewCreateModelCommand())
@@ -398,6 +398,7 @@ var commandNames = []string{
"list-spaces",
"list-storage",
"list-storage-pools",
+ "list-subnets",
"list-users",
"login",
"logout",
@@ -453,7 +454,7 @@ var commandNames = []string{
"status",
"status-history",
"storage",
- "subnet",
+ "subnets",
"switch",
"sync-tools",
"unblock",
View
@@ -14,7 +14,8 @@ import (
"github.com/juju/juju/cmd/modelcmd"
)
-func newAddCommand() cmd.Command {
+// NewAddCommand returns a command used to add an existing subnet to Juju.
+func NewAddCommand() cmd.Command {
return modelcmd.Wrap(&addCommand{})
}
@@ -31,7 +32,7 @@ type addCommand struct {
const addCommandDoc = `
Adds an existing subnet to Juju, making it available for use. Unlike
-"juju subnet create", this command does not create a new subnet, so it
+"juju create-subnet", this command does not create a new subnet, so it
is supported on a wider variety of clouds (where SDN features are not
available, e.g. MAAS). The subnet will be associated with the given
existing Juju network space.
@@ -50,7 +51,7 @@ zone(s) is required.
// Info is defined on the cmd.Command interface.
func (c *addCommand) Info() *cmd.Info {
return &cmd.Info{
- Name: "add",
+ Name: "add-subnet",
Args: "<CIDR>|<provider-id> <space> [<zone1> <zone2> ...]",
Purpose: "add an existing subnet to Juju",
Doc: strings.TrimSpace(addCommandDoc),
@@ -25,7 +25,7 @@ var _ = gc.Suite(&AddSuite{})
func (s *AddSuite) SetUpTest(c *gc.C) {
s.BaseSubnetSuite.SetUpTest(c)
- s.command, _ = subnet.NewAddCommand(s.api)
+ s.command, _ = subnet.NewAddCommandForTest(s.api)
c.Assert(s.command, gc.NotNil)
}
@@ -94,7 +94,7 @@ func (s *AddSuite) TestInit(c *gc.C) {
// Create a new instance of the subcommand for each test, but
// since we're not running the command no need to use
// modelcmd.Wrap().
- wrappedCommand, command := subnet.NewAddCommand(s.api)
+ wrappedCommand, command := subnet.NewAddCommandForTest(s.api)
err := coretesting.InitCommand(wrappedCommand, test.args)
if test.expectErr != "" {
prefixedErr := "invalid arguments specified: " + test.expectErr
@@ -16,7 +16,8 @@ import (
"github.com/juju/juju/cmd/modelcmd"
)
-func newCreateCommand() cmd.Command {
+// NewCreateCommand returns a command to create a new subnet.
+func NewCreateCommand() cmd.Command {
return modelcmd.Wrap(&createCommand{})
}
@@ -62,7 +63,7 @@ supported.
// Info is defined on the cmd.Command interface.
func (c *createCommand) Info() *cmd.Info {
return &cmd.Info{
- Name: "create",
+ Name: "create-subnet",
Args: "<CIDR> <space> <zone1> [<zone2> <zone3> ...] [--public|--private]",
Purpose: "create a new subnet",
Doc: strings.TrimSpace(createCommandDoc),
@@ -23,7 +23,7 @@ var _ = gc.Suite(&CreateSuite{})
func (s *CreateSuite) SetUpTest(c *gc.C) {
s.BaseSuite.SetFeatureFlags(feature.PostNetCLIMVP)
s.BaseSubnetSuite.SetUpTest(c)
- s.command, _ = subnet.NewCreateCommand(s.api)
+ s.command, _ = subnet.NewCreateCommandForTest(s.api)
c.Assert(s.command, gc.NotNil)
}
@@ -125,7 +125,7 @@ func (s *CreateSuite) TestInit(c *gc.C) {
// Create a new instance of the subcommand for each test, but
// since we're not running the command no need to use
// modelcmd.Wrap().
- wrappedCommand, command := subnet.NewCreateCommand(s.api)
+ wrappedCommand, command := subnet.NewCreateCommandForTest(s.api)
err := coretesting.InitCommand(wrappedCommand, test.args)
if test.expectErr != "" {
c.Check(err, gc.ErrorMatches, test.expectErr)
@@ -13,7 +13,7 @@ type CreateCommand struct {
*createCommand
}
-func NewCreateCommand(api SubnetAPI) (cmd.Command, *CreateCommand) {
+func NewCreateCommandForTest(api SubnetAPI) (cmd.Command, *CreateCommand) {
cmd := &createCommand{
SubnetCommandBase: SubnetCommandBase{api: api},
}
@@ -24,7 +24,7 @@ type AddCommand struct {
*addCommand
}
-func NewAddCommand(api SubnetAPI) (cmd.Command, *AddCommand) {
+func NewAddCommandForTest(api SubnetAPI) (cmd.Command, *AddCommand) {
cmd := &addCommand{
SubnetCommandBase: SubnetCommandBase{api: api},
}
@@ -35,7 +35,7 @@ type RemoveCommand struct {
*removeCommand
}
-func NewRemoveCommand(api SubnetAPI) (cmd.Command, *RemoveCommand) {
+func NewRemoveCommandForTest(api SubnetAPI) (cmd.Command, *RemoveCommand) {
removeCmd := &removeCommand{
SubnetCommandBase: SubnetCommandBase{api: api},
}
@@ -46,7 +46,7 @@ type ListCommand struct {
*listCommand
}
-func NewListCommand(api SubnetAPI) (cmd.Command, *ListCommand) {
+func NewListCommandForTest(api SubnetAPI) (cmd.Command, *ListCommand) {
cmd := &listCommand{
SubnetCommandBase: SubnetCommandBase{api: api},
}
@@ -17,7 +17,9 @@ import (
"github.com/juju/juju/cmd/modelcmd"
)
-func newListCommand() cmd.Command {
+// NewListCommand returns a cammin used to list all subnets
+// known to Juju.
+func NewListCommand() cmd.Command {
return modelcmd.Wrap(&listCommand{})
}
@@ -47,10 +49,11 @@ output to a file, use --output.
// Info is defined on the cmd.Command interface.
func (c *listCommand) Info() *cmd.Info {
return &cmd.Info{
- Name: "list",
+ Name: "list-subnets",
Args: "[--space <name>] [--zone <name>] [--format yaml|json] [--output <path>]",
Purpose: "list subnets known to Juju",
Doc: strings.TrimSpace(listCommandDoc),
+ Aliases: []string{"subnets"},
}
}
@@ -25,7 +25,7 @@ var _ = gc.Suite(&ListSuite{})
func (s *ListSuite) SetUpTest(c *gc.C) {
s.BaseSubnetSuite.SetUpTest(c)
- s.command, _ = subnet.NewListCommand(s.api)
+ s.command, _ = subnet.NewListCommandForTest(s.api)
c.Assert(s.command, gc.NotNil)
}
@@ -86,7 +86,7 @@ func (s *ListSuite) TestInit(c *gc.C) {
// Create a new instance of the subcommand for each test, but
// since we're not running the command no need to use
// modelcmd.Wrap().
- wrappedCommand, command := subnet.NewListCommand(s.api)
+ wrappedCommand, command := subnet.NewListCommandForTest(s.api)
err := coretesting.InitCommand(wrappedCommand, test.args)
if test.expectErr != "" {
c.Check(err, gc.ErrorMatches, test.expectErr)
@@ -5,7 +5,6 @@ package subnet_test
import (
"net"
- "regexp"
stdtesting "testing"
"github.com/juju/cmd"
@@ -31,9 +30,8 @@ type BaseSubnetSuite struct {
coretesting.FakeJujuXDGDataHomeSuite
coretesting.BaseSuite
- superCmd cmd.Command
- command cmd.Command
- api *StubAPI
+ command cmd.Command
+ api *StubAPI
}
var _ = gc.Suite(&BaseSubnetSuite{})
@@ -59,9 +57,6 @@ func (s *BaseSubnetSuite) SetUpTest(c *gc.C) {
s.BaseSuite.SetFeatureFlags(feature.PostNetCLIMVP)
}
- s.superCmd = subnet.NewSuperCommand()
- c.Assert(s.superCmd, gc.NotNil)
-
s.api = NewStubAPI()
c.Assert(s.api, gc.NotNil)
@@ -74,27 +69,12 @@ func (s *BaseSubnetSuite) TearDownTest(c *gc.C) {
s.FakeJujuXDGDataHomeSuite.TearDownTest(c)
}
-// RunSuperCommand executes the super command passing any args and
-// returning the stdout and stderr output as strings, as well as any
-// error. If s.command is set, the subcommand's name will be passed as
-// first argument.
-func (s *BaseSubnetSuite) RunSuperCommand(c *gc.C, args ...string) (string, string, error) {
- if s.command != nil {
- args = append([]string{s.command.Info().Name}, args...)
- }
- ctx, err := coretesting.RunCommand(c, s.superCmd, args...)
- if ctx != nil {
- return coretesting.Stdout(ctx), coretesting.Stderr(ctx), err
- }
- return "", "", err
-}
-
-// RunSubCommand executes the s.command subcommand passing any args
+// RunCommand executes the s.command passing any args
// and returning the stdout and stderr output as strings, as well as
// any error.
-func (s *BaseSubnetSuite) RunSubCommand(c *gc.C, args ...string) (string, string, error) {
+func (s *BaseSubnetSuite) RunCommand(c *gc.C, args ...string) (string, string, error) {
if s.command == nil {
- panic("subcommand is nil")
+ panic("command is nil")
}
ctx, err := coretesting.RunCommand(c, s.command, args...)
if ctx != nil {
@@ -103,60 +83,28 @@ func (s *BaseSubnetSuite) RunSubCommand(c *gc.C, args ...string) (string, string
return "", "", err
}
-// AssertRunFails is a shortcut for calling RunSubCommand with the
+// AssertRunFails is a shortcut for calling RunCommand with the
// passed args then asserting the output is empty and the error is as
// expected, finally returning the error.
func (s *BaseSubnetSuite) AssertRunFails(c *gc.C, expectErr string, args ...string) error {
- stdout, stderr, err := s.RunSubCommand(c, args...)
+ stdout, stderr, err := s.RunCommand(c, args...)
c.Assert(err, gc.ErrorMatches, expectErr)
c.Assert(stdout, gc.Equals, "")
c.Assert(stderr, gc.Equals, "")
return err
}
-// AssertRunSucceeds is a shortcut for calling RunSuperCommand with
+// AssertRunSucceeds is a shortcut for calling RunCommand with
// the passed args then asserting the stderr output matches
// expectStderr, stdout is equal to expectStdout, and the error is
// nil.
func (s *BaseSubnetSuite) AssertRunSucceeds(c *gc.C, expectStderr, expectStdout string, args ...string) {
- stdout, stderr, err := s.RunSubCommand(c, args...)
+ stdout, stderr, err := s.RunCommand(c, args...)
c.Assert(err, jc.ErrorIsNil)
c.Assert(stdout, gc.Equals, expectStdout)
c.Assert(stderr, gc.Matches, expectStderr)
}
-// TestHelp runs the command with --help as argument and verifies the
-// output.
-func (s *BaseSubnetSuite) TestHelp(c *gc.C) {
- stderr, stdout, err := s.RunSuperCommand(c, "--help")
- c.Assert(err, jc.ErrorIsNil)
- c.Check(stdout, gc.Equals, "")
- c.Check(stderr, gc.Not(gc.Equals), "")
-
- // If s.command is set, use it instead of s.superCmd.
- cmdInfo := s.superCmd.Info()
- var expected string
- if s.command != nil {
- // Subcommands embed ModelCommandBase and have an extra
- // "[options]" prepended before the args.
- cmdInfo = s.command.Info()
- expected = "(?sm).*^Usage: juju subnet " +
- regexp.QuoteMeta(cmdInfo.Name) +
- `( \[options\])? ` + regexp.QuoteMeta(cmdInfo.Args) + ".+"
- } else {
- expected = "(?sm).*^Usage: juju subnet" +
- `( \[options\])? ` + regexp.QuoteMeta(cmdInfo.Args) + ".+"
- }
- c.Check(cmdInfo, gc.NotNil)
- c.Check(stderr, gc.Matches, expected)
-
- expected = "(?sm).*^Summary:\n" + regexp.QuoteMeta(cmdInfo.Purpose) + "$.*"
- c.Check(stderr, gc.Matches, expected)
-
- expected = "(?sm).*^Details:\n" + regexp.QuoteMeta(cmdInfo.Doc) + "$.*"
- c.Check(stderr, gc.Matches, expected)
-}
-
// Strings makes tests taking a slice of strings slightly easier to
// write: e.g. s.Strings("foo", "bar") vs. []string{"foo", "bar"}.
func (s *BaseSubnetSuite) Strings(values ...string) []string {
@@ -13,7 +13,8 @@ import (
"github.com/juju/juju/cmd/modelcmd"
)
-func newRemoveCommand() cmd.Command {
+// NewRemoveCommand returns a command used to remove an unused subnet from Juju.
+func NewRemoveCommand() cmd.Command {
return modelcmd.Wrap(&removeCommand{})
}
@@ -42,7 +43,7 @@ until all related entites are cleaned up (e.g. allocated addresses).
// Info is defined on the cmd.Command interface.
func (c *removeCommand) Info() *cmd.Info {
return &cmd.Info{
- Name: "remove",
+ Name: "remove-subnet",
Args: "<CIDR>",
Purpose: "remove an existing subnet from Juju",
Doc: strings.TrimSpace(removeCommandDoc),
@@ -23,7 +23,7 @@ var _ = gc.Suite(&RemoveSuite{})
func (s *RemoveSuite) SetUpTest(c *gc.C) {
s.BaseSuite.SetFeatureFlags(feature.PostNetCLIMVP)
s.BaseSubnetSuite.SetUpTest(c)
- s.command, _ = subnet.NewRemoveCommand(s.api)
+ s.command, _ = subnet.NewRemoveCommandForTest(s.api)
c.Assert(s.command, gc.NotNil)
}
@@ -54,7 +54,7 @@ func (s *RemoveSuite) TestInit(c *gc.C) {
// Create a new instance of the subcommand for each test, but
// since we're not running the command no need to use
// modelcmd.Wrap().
- wrappedCommand, command := subnet.NewRemoveCommand(s.api)
+ wrappedCommand, command := subnet.NewRemoveCommandForTest(s.api)
err := coretesting.InitCommand(wrappedCommand, test.args)
if test.expectErr != "" {
c.Check(err, gc.ErrorMatches, test.expectErr)
Oops, something went wrong.