Repository: vmware/govmomi
Pull request #3410 (2024-04-12 06:19:23)

govc: add default output formatting for namespace commands
Including a few other minor changes for the new set of namespace commands.



Patch:
diff --git a/govc/USAGE.md b/govc/USAGE.md
index 35bfba96..79765f63 100644
--- a/govc/USAGE.md
+++ b/govc/USAGE.md
@@ -4284,23 +4284,24 @@ Options:
 ## namespace.create
 
 ```
-Usage: govc namespace.create [OPTIONS]
+Usage: govc namespace.create [OPTIONS] NAME
 
-Creates a new vSphere Namespace on a Supervisor. 
+Creates a new vSphere Namespace on a Supervisor.
+
+The '-library' and '-vm-class' flags can each be specified multiple times.
 
 Examples:
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,dca9cc16-9460-4da0-802c-4aa148ac6cf7
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -vm-classes=best-effort-2xlarge
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -vm-classes=best-effort-2xlarge,best-effort-4xlarge
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,dca9cc16-9460-4da0-802c-4aa148ac6cf7 -vm-classes=best-effort-2xlarge,best-effort-4xlarge
+  govc namespace.create -supervisor=domain-c1 test-namespace
+  govc namespace.create -supervisor=domain-c1 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
+  govc namespace.create -supervisor=domain-c1 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
+  govc namespace.create -supervisor=domain-c1 -vm-class=best-effort-2xlarge test-namespace
+  govc namespace.create -supervisor=domain-c1 -vm-class=best-effort-2xlarge -vm-class best-effort-4xlarge test-namespace
+  govc namespace.create -supervisor=domain-c1 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -vm-class=best-effort-2xlarge -vm-class=best-effort-4xlarge test-namespace
 
 Options:
-  -content-libraries=    The identifiers of the content libraries to associate with the vSphere Namespace.
-  -namespace=            The name of the vSphere Namespace.
+  -library=[]            Content library IDs to associate with the vSphere Namespace.
   -supervisor=           The identifier of the Supervisor.
-  -vm-classes=           The identifiers of the virtual machine classes to associate with the vSphere Namespace.
+  -vm-class=[]           Virtual machine class IDs to associate with the vSphere Namespace.
 ```
 
 ## namespace.info
@@ -4308,7 +4309,7 @@ Options:
 ```
 Usage: govc namespace.info [OPTIONS] NAME
 
-Displays the details of a vSphere Namespace. 
+Displays the details of a vSphere Namespace.
 
 Examples:
   govc namespace.info test-namespace
@@ -4341,7 +4342,7 @@ Options:
 ```
 Usage: govc namespace.ls [OPTIONS]
 
-Displays the list of vSphere Namespaces. 
+Displays the list of vSphere Namespaces.
 
 Examples:
   govc namespace.ls
@@ -4449,40 +4450,39 @@ Options:
 ```
 Usage: govc namespace.update [OPTIONS] NAME
 
-Modifies an existing vSphere Namespace on a Supervisor. 
+Modifies an existing vSphere Namespace on a Supervisor.
 
 Examples:
-  govc namespace.update -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
-  govc namespace.update -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,617a3ee3-a2ff-4311-9a7c-0016ccf958bd test-namespace
-  govc namespace.update -vm-classes=best-effort-2xlarge test-namespace
-  govc namespace.update -vm-classes=best-effort-2xlarge,best-effort-4xlarge test-namespace
-  govc namespace.update -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,617a3ee3-a2ff-4311-9a7c-0016ccf958bd -vm-classes=best-effort-2xlarge,best-effort-4xlarge test-namespace
+  govc namespace.update -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
+  govc namespace.update -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=617a3ee3-a2ff-4311-9a7c-0016ccf958bd test-namespace
+  govc namespace.update -vm-class=best-effort-2xlarge test-namespace
+  govc namespace.update -vm-class=best-effort-2xlarge -vm-class=best-effort-4xlarge test-namespace
+  govc namespace.update -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=617a3ee3-a2ff-4311-9a7c-0016ccf958bd -vm-class=best-effort-2xlarge -vm-class=best-effort-4xlarge test-namespace
 
 Options:
-  -content-libraries=    The list of content libraries to associate with the vSphere Namespace.
-  -vm-classes=           The list of virtual machine classes to associate with the vSphere Namespace.
+  -library=[]            Content library IDs to associate with the vSphere Namespace.
+  -vm-class=[]           Virtual machine class IDs to associate with the vSphere Namespace.
 ```
 
 ## namespace.vmclass.create
 
 ```
-Usage: govc namespace.vmclass.create [OPTIONS]
+Usage: govc namespace.vmclass.create [OPTIONS] NAME
 
-Creates a new virtual machine class. 
+Creates a new virtual machine class.
 
- The name of the virtual machine class has DNS_LABEL restrictions
- as specified in "https://tools.ietf.org/html/rfc1123". It
- must be an alphanumeric (a-z and 0-9) string and with maximum length
- of 63 characters and with the '-' character allowed anywhere except
- the first or last character. This name is unique in this vCenter server.
+The name of the virtual machine class has DNS_LABEL restrictions
+as specified in "https://tools.ietf.org/html/rfc1123". It
+must be an alphanumeric (a-z and 0-9) string and with maximum length
+of 63 characters and with the '-' character allowed anywhere except
+the first or last character. This name is unique in this vCenter server.
 
 Examples:
-  govc namespace.vmclass.create -name=test-class-01 -cpus=8 -memory=8192
+  govc namespace.vmclass.create -cpus=8 -memory=8192 test-class-01
 
 Options:
   -cpus=0                The number of CPUs.
   -memory=0              The amount of memory (in MB).
-  -name=                 The name of the virtual machine class.
 ```
 
 ## namespace.vmclass.info
@@ -4490,7 +4490,7 @@ Options:
 ```
 Usage: govc namespace.vmclass.info [OPTIONS] NAME
 
-Displays the details of a virtual machine class. 
+Displays the details of a virtual machine class.
 
 Examples:
   govc namespace.vmclass.info test-class
@@ -4503,7 +4503,7 @@ Options:
 ```
 Usage: govc namespace.vmclass.ls [OPTIONS]
 
-Displays the list of virtual machine classes. 
+Displays the list of virtual machine classes.
 
 Examples:
   govc namespace.vmclass.ls
diff --git a/govc/namespace/create.go b/govc/namespace/create.go
index ef19616e..d9caa06e 100644
--- a/govc/namespace/create.go
+++ b/govc/namespace/create.go
@@ -19,7 +19,6 @@ package namespace
 import (
 	"context"
 	"flag"
-	"strings"
 
 	"github.com/vmware/govmomi/govc/cli"
 	"github.com/vmware/govmomi/govc/flags"
@@ -29,8 +28,8 @@ import (
 type create struct {
 	*flags.ClientFlag
 
-	libraries string
-	vmClasses string
+	libraries flags.StringList
+	vmClasses flags.StringList
 	spec      namespace.NamespacesInstanceCreateSpec
 }
 
@@ -43,36 +42,42 @@ func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag.Register(ctx, f)
 
 	f.StringVar(&cmd.spec.Cluster, "supervisor", "", "The identifier of the Supervisor.")
-	f.StringVar(&cmd.spec.Namespace, "namespace", "", "The name of the vSphere Namespace.")
-	f.StringVar(&cmd.libraries, "content-libraries", "", "The identifiers of the content libraries to associate with the vSphere Namespace.")
-	f.StringVar(&cmd.vmClasses, "vm-classes", "", "The identifiers of the virtual machine classes to associate with the vSphere Namespace.")
+	f.Var(&cmd.libraries, "library", "Content library IDs to associate with the vSphere Namespace.")
+	f.Var(&cmd.vmClasses, "vm-class", "Virtual machine class IDs to associate with the vSphere Namespace.")
+}
+
+func (*create) Usage() string {
+	return "NAME"
 }
 
 func (cmd *create) Process(ctx context.Context) error {
-	if len(cmd.libraries) > 0 {
-		cmd.spec.VmServiceSpec.ContentLibraries = strings.Split(cmd.libraries, ",")
-	}
-	if len(cmd.vmClasses) > 0 {
-		cmd.spec.VmServiceSpec.VmClasses = strings.Split(cmd.vmClasses, ",")
-	}
+	cmd.spec.VmServiceSpec.ContentLibraries = cmd.libraries
+	cmd.spec.VmServiceSpec.VmClasses = cmd.vmClasses
+
 	return cmd.ClientFlag.Process(ctx)
 }
 
 func (cmd *create) Description() string {
-	return `Creates a new vSphere Namespace on a Supervisor. 
+	return `Creates a new vSphere Namespace on a Supervisor.
+
+The '-library' and '-vm-class' flags can each be specified multiple times.
 
 Examples:
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,dca9cc16-9460-4da0-802c-4aa148ac6cf7
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -vm-classes=best-effort-2xlarge
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -vm-classes=best-effort-2xlarge,best-effort-4xlarge
-  govc namespace.create -namespace=test-namespace -supervisor=domain-c1 -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,dca9cc16-9460-4da0-802c-4aa148ac6cf7 -vm-classes=best-effort-2xlarge,best-effort-4xlarge`
+  govc namespace.create -supervisor=domain-c1 test-namespace
+  govc namespace.create -supervisor=domain-c1 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
+  govc namespace.create -supervisor=domain-c1 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
+  govc namespace.create -supervisor=domain-c1 -vm-class=best-effort-2xlarge test-namespace
+  govc namespace.create -supervisor=domain-c1 -vm-class=best-effort-2xlarge -vm-class best-effort-4xlarge test-namespace
+  govc namespace.create -supervisor=domain-c1 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -vm-class=best-effort-2xlarge -vm-class=best-effort-4xlarge test-namespace`
 }
 
 func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
-	rc, err := cmd.RestClient()
+	cmd.spec.Namespace = f.Arg(0)
+	if f.NArg() != 1 {
+		return flag.ErrHelp
+	}
 
+	rc, err := cmd.RestClient()
 	if err != nil {
 		return err
 	}
diff --git a/govc/namespace/info.go b/govc/namespace/info.go
index cac64f07..34cc2216 100644
--- a/govc/namespace/info.go
+++ b/govc/namespace/info.go
@@ -19,7 +19,10 @@ package namespace
 import (
 	"context"
 	"flag"
+	"fmt"
 	"io"
+	"strings"
+	"text/tabwriter"
 
 	"github.com/vmware/govmomi/vapi/namespace"
 
@@ -30,7 +33,12 @@ import (
 type infoResult namespace.NamespacesInstanceInfo
 
 func (r infoResult) Write(w io.Writer) error {
-	return nil
+	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+	fmt.Fprintf(tw, "Cluster:\t%s\n", r.ClusterId)
+	fmt.Fprintf(tw, "Status:\t%s\n", r.ConfigStatus)
+	fmt.Fprintf(tw, "VM Classes:\t%s\n", strings.Join(r.VmServiceSpec.VmClasses, ","))
+	fmt.Fprintf(tw, "VM Libraries:\t%s\n", strings.Join(r.VmServiceSpec.ContentLibraries, ","))
+	return tw.Flush()
 }
 
 type info struct {
@@ -47,6 +55,7 @@ func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag.Register(ctx, f)
 
 	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
 }
 
 func (cmd *info) Process(ctx context.Context) error {
@@ -65,15 +74,18 @@ func (cmd *info) Usage() string {
 }
 
 func (cmd *info) Description() string {
-	return `Displays the details of a vSphere Namespace. 
+	return `Displays the details of a vSphere Namespace.
 
 Examples:
   govc namespace.info test-namespace`
 }
 
 func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
-	rc, err := cmd.RestClient()
+	if f.NArg() != 1 {
+		return flag.ErrHelp
+	}
 
+	rc, err := cmd.RestClient()
 	if err != nil {
 		return err
 	}
@@ -81,11 +93,9 @@ func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
 	nm := namespace.NewManager(rc)
 
 	d, err := nm.GetNamespace(ctx, f.Arg(0))
-
 	if err != nil {
 		return err
 	}
 
-	cmd.JSON = !cmd.All()
 	return cmd.WriteResult(infoResult(d))
 }
diff --git a/govc/namespace/ls.go b/govc/namespace/ls.go
index b61aaefd..6604a077 100644
--- a/govc/namespace/ls.go
+++ b/govc/namespace/ls.go
@@ -19,6 +19,7 @@ package namespace
 import (
 	"context"
 	"flag"
+	"fmt"
 	"io"
 
 	"github.com/vmware/govmomi/vapi/namespace"
@@ -30,6 +31,9 @@ import (
 type lsResult []namespace.NamespacesInstanceSummary
 
 func (r lsResult) Write(w io.Writer) error {
+	for _, e := range r {
+		fmt.Fprintln(w, e.Namespace)
+	}
 	return nil
 }
 
@@ -47,6 +51,7 @@ func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag.Register(ctx, f)
 
 	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
 }
 
 func (cmd *ls) Process(ctx context.Context) error {
@@ -61,7 +66,7 @@ func (cmd *ls) Process(ctx context.Context) error {
 }
 
 func (cmd *ls) Description() string {
-	return `Displays the list of vSphere Namespaces. 
+	return `Displays the list of vSphere Namespaces.
 
 Examples:
   govc namespace.ls`
@@ -69,7 +74,6 @@ Examples:
 
 func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
 	rc, err := cmd.RestClient()
-
 	if err != nil {
 		return err
 	}
@@ -77,11 +81,9 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
 	nm := namespace.NewManager(rc)
 
 	d, err := nm.ListNamespaces(ctx)
-
 	if err != nil {
 		return err
 	}
 
-	cmd.JSON = !cmd.All()
 	return cmd.WriteResult(lsResult(d))
 }
diff --git a/govc/namespace/update.go b/govc/namespace/update.go
index b8810690..5fbdd863 100644
--- a/govc/namespace/update.go
+++ b/govc/namespace/update.go
@@ -19,7 +19,6 @@ package namespace
 import (
 	"context"
 	"flag"
-	"strings"
 
 	"github.com/vmware/govmomi/govc/cli"
 	"github.com/vmware/govmomi/govc/flags"
@@ -29,8 +28,8 @@ import (
 type update struct {
 	*flags.ClientFlag
 
-	libraries string
-	vmClasses string
+	libraries flags.StringList
+	vmClasses flags.StringList
 	spec      namespace.NamespacesInstanceUpdateSpec
 }
 
@@ -42,17 +41,14 @@ func (cmd *update) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
 	cmd.ClientFlag.Register(ctx, f)
 
-	f.StringVar(&cmd.libraries, "content-libraries", "", "The list of content libraries to associate with the vSphere Namespace.")
-	f.StringVar(&cmd.vmClasses, "vm-classes", "", "The list of virtual machine classes to associate with the vSphere Namespace.")
+	f.Var(&cmd.libraries, "library", "Content library IDs to associate with the vSphere Namespace.")
+	f.Var(&cmd.vmClasses, "vm-class", "Virtual machine class IDs to associate with the vSphere Namespace.")
 }
 
 func (cmd *update) Process(ctx context.Context) error {
-	if len(cmd.libraries) > 0 {
-		cmd.spec.VmServiceSpec.ContentLibraries = strings.Split(cmd.libraries, ",")
-	}
-	if len(cmd.vmClasses) > 0 {
-		cmd.spec.VmServiceSpec.VmClasses = strings.Split(cmd.vmClasses, ",")
-	}
+	cmd.spec.VmServiceSpec.ContentLibraries = cmd.libraries
+	cmd.spec.VmServiceSpec.VmClasses = cmd.vmClasses
+
 	return cmd.ClientFlag.Process(ctx)
 }
 
@@ -61,19 +57,22 @@ func (cmd *update) Usage() string {
 }
 
 func (cmd *update) Description() string {
-	return `Modifies an existing vSphere Namespace on a Supervisor. 
+	return `Modifies an existing vSphere Namespace on a Supervisor.
 
 Examples:
-  govc namespace.update -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
-  govc namespace.update -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,617a3ee3-a2ff-4311-9a7c-0016ccf958bd test-namespace
-  govc namespace.update -vm-classes=best-effort-2xlarge test-namespace
-  govc namespace.update -vm-classes=best-effort-2xlarge,best-effort-4xlarge test-namespace
-  govc namespace.update -content-libraries=dca9cc16-9460-4da0-802c-4aa148ac6cf7,617a3ee3-a2ff-4311-9a7c-0016ccf958bd -vm-classes=best-effort-2xlarge,best-effort-4xlarge test-namespace`
+  govc namespace.update -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 test-namespace
+  govc namespace.update -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=617a3ee3-a2ff-4311-9a7c-0016ccf958bd test-namespace
+  govc namespace.update -vm-class=best-effort-2xlarge test-namespace
+  govc namespace.update -vm-class=best-effort-2xlarge -vm-class=best-effort-4xlarge test-namespace
+  govc namespace.update -library=dca9cc16-9460-4da0-802c-4aa148ac6cf7 -library=617a3ee3-a2ff-4311-9a7c-0016ccf958bd -vm-class=best-effort-2xlarge -vm-class=best-effort-4xlarge test-namespace`
 }
 
 func (cmd *update) Run(ctx context.Context, f *flag.FlagSet) error {
-	rc, err := cmd.RestClient()
+	if f.NArg() != 1 {
+		return flag.ErrHelp
+	}
 
+	rc, err := cmd.RestClient()
 	if err != nil {
 		return err
 	}
diff --git a/govc/namespace/vmclass/create.go b/govc/namespace/vmclass/create.go
index b30ae9d1..b3cccea9 100644
--- a/govc/namespace/vmclass/create.go
+++ b/govc/namespace/vmclass/create.go
@@ -39,31 +39,34 @@ func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
 	cmd.ClientFlag.Register(ctx, f)
 
-	f.StringVar(&cmd.spec.Id, "name", "", "The name of the virtual machine class.")
 	f.Int64Var(&cmd.spec.CpuCount, "cpus", 0, "The number of CPUs.")
 	f.Int64Var(&cmd.spec.MemoryMb, "memory", 0, "The amount of memory (in MB).")
 }
 
-func (cmd *create) Process(ctx context.Context) error {
-	return cmd.ClientFlag.Process(ctx)
+func (*create) Usage() string {
+	return "NAME"
 }
 
 func (cmd *create) Description() string {
-	return `Creates a new virtual machine class. 
+	return `Creates a new virtual machine class.
 
- The name of the virtual machine class has DNS_LABEL restrictions
- as specified in "https://tools.ietf.org/html/rfc1123". It
- must be an alphanumeric (a-z and 0-9) string and with maximum length
- of 63 characters and with the '-' character allowed anywhere except
- the first or last character. This name is unique in this vCenter server.
+The name of the virtual machine class has DNS_LABEL restrictions
+as specified in "https://tools.ietf.org/html/rfc1123". It
+must be an alphanumeric (a-z and 0-9) string and with maximum length
+of 63 characters and with the '-' character allowed anywhere except
+the first or last character. This name is unique in this vCenter server.
 
 Examples:
-  govc namespace.vmclass.create -name=test-class-01 -cpus=8 -memory=8192`
+  govc namespace.vmclass.create -cpus=8 -memory=8192 test-class-01`
 }
 
 func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
-	rc, err := cmd.RestClient()
+	cmd.spec.Id = f.Arg(0)
+	if f.NArg() != 1 {
+		return flag.ErrHelp
+	}
 
+	rc, err := cmd.RestClient()
 	if err != nil {
 		return err
 	}
diff --git a/govc/namespace/vmclass/info.go b/govc/namespace/vmclass/info.go
index 6cf96562..acf92bc6 100644
--- a/govc/namespace/vmclass/info.go
+++ b/govc/namespace/vmclass/info.go
@@ -19,8 +19,11 @@ package vmclass
 import (
 	"context"
 	"flag"
+	"fmt"
 	"io"
+	"text/tabwriter"
 
+	"github.com/vmware/govmomi/units"
 	"github.com/vmware/govmomi/vapi/namespace"
 
 	"github.com/vmware/govmomi/govc/cli"
@@ -30,7 +33,13 @@ import (
 type infoResult namespace.VirtualMachineClassInfo
 
 func (r infoResult) Write(w io.Writer) error {
-	return nil
+	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
+
+	fmt.Fprintf(tw, "ID:\t%s\n", r.Id)
+	fmt.Fprintf(tw, "CPUs:\t%d\n", r.CpuCount)
+	fmt.Fprintf(tw, "Memory:\t%s\n", units.ByteSize(r.MemoryMb*1024*1024))
+
+	return tw.Flush()
 }
 
 type info struct {
@@ -47,6 +56,7 @@ func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag.Register(ctx, f)
 
 	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
 }
 
 func (cmd *info) Process(ctx context.Context) error {
@@ -65,15 +75,18 @@ func (cmd *info) Usage() string {
 }
 
 func (cmd *info) Description() string {
-	return `Displays the details of a virtual machine class. 
+	return `Displays the details of a virtual machine class.
 
 Examples:
   govc namespace.vmclass.info test-class`
 }
 
 func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
-	rc, err := cmd.RestClient()
+	if f.NArg() != 1 {
+		return flag.ErrHelp
+	}
 
+	rc, err := cmd.RestClient()
 	if err != nil {
 		return err
 	}
@@ -81,11 +94,9 @@ func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
 	nm := namespace.NewManager(rc)
 
 	d, err := nm.GetVmClass(ctx, f.Arg(0))
-
 	if err != nil {
 		return err
 	}
 
-	cmd.JSON = !cmd.All()
 	return cmd.WriteResult(infoResult(d))
 }
diff --git a/govc/namespace/vmclass/ls.go b/govc/namespace/vmclass/ls.go
index 01299175..36fb2444 100644
--- a/govc/namespace/vmclass/ls.go
+++ b/govc/namespace/vmclass/ls.go
@@ -19,6 +19,7 @@ package vmclass
 import (
 	"context"
 	"flag"
+	"fmt"
 	"io"
 
 	"github.com/vmware/govmomi/vapi/namespace"
@@ -30,6 +31,9 @@ import (
 type lsResult []namespace.VirtualMachineClassInfo
 
 func (r lsResult) Write(w io.Writer) error {
+	for _, e := range r {
+		fmt.Fprintln(w, e.Id)
+	}
 	return nil
 }
 
@@ -47,6 +51,7 @@ func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag.Register(ctx, f)
 
 	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
 }
 
 func (cmd *ls) Process(ctx context.Context) error {
@@ -61,7 +66,7 @@ func (cmd *ls) Process(ctx context.Context) error {
 }
 
 func (cmd *ls) Description() string {
-	return `Displays the list of virtual machine classes. 
+	return `Displays the list of virtual machine classes.
 
 Examples:
   govc namespace.vmclass.ls`
@@ -69,7 +74,6 @@ Examples:
 
 func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
 	rc, err := cmd.RestClient()
-
 	if err != nil {
 		return err
 	}
@@ -77,11 +81,9 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
 	nm := namespace.NewManager(rc)
 
 	d, err := nm.ListVmClasses(ctx)
-
 	if err != nil {
 		return err
 	}
 
-	cmd.JSON = !cmd.All()
 	return cmd.WriteResult(lsResult(d))
 }
diff --git a/vapi/namespace/simulator/simulator.go b/vapi/namespace/simulator/simulator.go
index f992b6de..0ef27d7a 100644
--- a/vapi/namespace/simulator/simulator.go
+++ b/vapi/namespace/simulator/simulator.go
@@ -281,7 +281,6 @@ func (h *Handler) namespaces(w http.ResponseWriter, r *http.Request) {
 		if len(subpath) > 0 {
 			if entry, contains := namespacesMap[subpath]; contains {
 				var spec namespace.NamespacesInstanceUpdateSpec
-				// If vapi.Decode fails it sets the status to bad request
 				if vapi.Decode(r, w, &spec) {
 					entry.VmServiceSpec = spec.VmServiceSpec
 					vapi.StatusOK(w)
@@ -292,7 +291,6 @@ func (h *Handler) namespaces(w http.ResponseWriter, r *http.Request) {
 		vapi.ApiErrorNotFound(w)
 	case http.MethodPost:
 		var spec namespace.NamespacesInstanceCreateSpec
-		// If vapi.Decode fails it sets the status to bad request
 		if !vapi.Decode(r, w, &spec) {
 			return
 		}
@@ -346,7 +344,6 @@ func (h *Handler) vmClasses(w http.ResponseWriter, r *http.Request) {
 		if len(subpath) > 0 {
 			if entry, contains := vmClassesMap[subpath]; contains {
 				var spec namespace.VirtualMachineClassUpdateSpec
-				// If vapi.Decode fails it sets the status to bad request
 				if !vapi.Decode(r, w, &spec) {
 					return
 				}
@@ -365,7 +362,6 @@ func (h *Handler) vmClasses(w http.ResponseWriter, r *http.Request) {
 		vapi.ApiErrorNotFound(w)
 	case http.MethodPost:
 		var spec namespace.VirtualMachineClassCreateSpec
-		// If vapi.Decode fails it sets the status to bad request
 		if !vapi.Decode(r, w, &spec) {
 			return
 		}


Test patch:
diff --git a/govc/test/namespace.bats b/govc/test/namespace.bats
index e5cd7a9a..eb460af6 100755
--- a/govc/test/namespace.bats
+++ b/govc/test/namespace.bats
@@ -117,61 +117,61 @@ load test_helper
 @test "namespace.create" {
     vcsim_env
 
-    run govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-1
+    run govc namespace.create -supervisor=domain-c1 test-namespace-1
     assert_success
 
-    ns=$(govc namespace.info test-namespace-1 | jq)
+    ns=$(govc namespace.info -json test-namespace-1 | jq)
     assert_equal "domain-c1" $(echo $ns | jq -r '."cluster"')
     assert_equal "0" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"' | jq length)
 
-    run govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-2 -content-libraries=lib1,lib2
+    run govc namespace.create -supervisor=domain-c1 -library=lib1 -library=lib2 test-namespace-2
     assert_success
 
-    ns=$(govc namespace.info test-namespace-2 | jq)
+    ns=$(govc namespace.info -json test-namespace-2 | jq)
     assert_equal "2" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"' | jq length)
 }
 
 @test "namespace.update" {
     vcsim_env
 
-    govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-1
+    govc namespace.create -supervisor=domain-c1 test-namespace-1
 
-    run govc namespace.update -content-libraries=lib1,lib2 -vm-classes=class1 test-namespace-1
+    run govc namespace.update -library=lib1 -library=lib2 -vm-class=class1 test-namespace-1
     assert_success
 
-    ns=$(govc namespace.info test-namespace-1 | jq)
+    ns=$(govc namespace.info -json test-namespace-1 | jq)
     assert_equal "2" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"' | jq length)
     assert_matches "lib[0-9]+" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"[0]')
     assert_matches "lib[0-9]+" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"[1]')
     assert_equal "1" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"' | jq length)
     assert_equal "class1" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"[0]')
 
-    run govc namespace.update -content-libraries=lib3 test-namespace-1
+    run govc namespace.update -library=lib3 test-namespace-1
     assert_success
 
-    ns=$(govc namespace.info test-namespace-1 | jq)
+    ns=$(govc namespace.info -json test-namespace-1 | jq)
     assert_equal "1" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"' | jq length)
     assert_equal "lib3" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"[0]')
     assert_equal "0" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"' | jq length)
 
-    run govc namespace.update -vm-classes=class3 test-namespace-1
+    run govc namespace.update -vm-class=class3 test-namespace-1
     assert_success
 
-    ns=$(govc namespace.info test-namespace-1 | jq)
+    ns=$(govc namespace.info -json test-namespace-1 | jq)
     assert_equal "0" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"' | jq length)
     assert_equal "1" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"' | jq length)
     assert_equal "class3" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"[0]')
 
-    run govc namespace.update -content-libraries=lib4 -vm-classes=class4 test-namespace-1
+    run govc namespace.update -library=lib4 -vm-class=class4 test-namespace-1
     assert_success
 
-    ns=$(govc namespace.info test-namespace-1 | jq)
+    ns=$(govc namespace.info -json test-namespace-1 | jq)
     assert_equal "1" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"' | jq length)
     assert_equal "lib4" $(echo $ns | jq -r '."vm_service_spec"."content_libraries"[0]')
     assert_equal "1" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"' | jq length)
     assert_equal "class4" $(echo $ns | jq -r '."vm_service_spec"."vm_classes"[0]')
 
-    run govc namespace.update -content-libraries=lib1,lib2 -vm-classes=class1 non-existing-namespace
+    run govc namespace.update -library=lib1 -library=lib2 -vm-class=class1 non-existing-namespace
     assert_failure
     assert_matches "404 Not Found"
 }
@@ -179,10 +179,14 @@ load test_helper
 @test "namespace.info" {
     vcsim_env
 
-    govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-1
+    govc namespace.create -supervisor=domain-c1 test-namespace-1
 
-    ns=$(govc namespace.info test-namespace-1 | jq)
+    ns=$(govc namespace.info -json test-namespace-1 | jq)
     assert_equal "domain-c1" $(echo $ns | jq -r '."cluster"')
+
+    run govc namespace.info test-namespace-1
+    assert_success
+
     run govc namespace.info non-existing-namespace
     assert_failure
     assert_matches "404 Not Found"
@@ -191,16 +195,22 @@ load test_helper
 @test "namespace.ls" {
     vcsim_env
 
-    ls=$(govc namespace.ls)
+    run govc namespace.ls
+    assert_success ""
+
+    ls=$(govc namespace.ls -json)
     assert_equal "0" $(echo $ls | jq length)
 
-    govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-1
-    ls=$(govc namespace.ls)
+    govc namespace.create -supervisor=domain-c1 test-namespace-1
+    ls=$(govc namespace.ls -json)
     assert_equal "1" $(echo $ls | jq length)
     assert_equal "test-namespace-1" $(echo $ls | jq -r '.[0]."namespace"')
 
-    govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-2
-    ls=$(govc namespace.ls)
+    run govc namespace.ls
+    assert_success test-namespace-1
+
+    govc namespace.create -supervisor=domain-c1 test-namespace-2
+    ls=$(govc namespace.ls -json)
     assert_equal "2" $(echo $ls | jq length)
     assert_equal "domain-c1" $(echo $ls | jq -r '.[0]."cluster"')
     assert_matches "test-namespace-[0-9]+" $(echo $ls | jq -r '.[0]."namespace"')
@@ -215,7 +225,7 @@ load test_helper
     assert_failure
     assert_matches "404 Not Found"
 
-    govc namespace.create -supervisor=domain-c1 -namespace=test-namespace-1
+    govc namespace.create -supervisor=domain-c1 test-namespace-1
 
     run govc namespace.rm test-namespace-1
     assert_success
@@ -224,10 +234,10 @@ load test_helper
 @test "namespace.vmclass.create" {
     vcsim_env
 
-    run govc namespace.vmclass.create -name=test-class-1 -cpus=16 -memory=16000
+    run govc namespace.vmclass.create -cpus=16 -memory=16000 test-class-1
     assert_success
 
-    c=$(govc namespace.vmclass.info test-class-1 | jq)
+    c=$(govc namespace.vmclass.info -json test-class-1 | jq)
     assert_equal "16" $(echo $c | jq -r '."cpu_count"')
     assert_equal "16000" $(echo $c | jq -r '."memory_mb"')
 }
@@ -235,10 +245,10 @@ load test_helper
 @test "namespace.vmclass.update" {
     vcsim_env
 
-    govc namespace.vmclass.create -name=test-class-1 -cpus=16 -memory=16000
+    govc namespace.vmclass.create -cpus=16 -memory=16000 test-class-1
 
     govc namespace.vmclass.update -cpus=24 -memory=24000 test-class-1
-    c=$(govc namespace.vmclass.info test-class-1 | jq)
+    c=$(govc namespace.vmclass.info -json test-class-1 | jq)
     assert_equal "24" $(echo $c | jq -r '."cpu_count"')
     assert_equal "24000" $(echo $c | jq -r '."memory_mb"')
 }
@@ -246,10 +256,16 @@ load test_helper
 @test "namespace.vmclass.info" {
     vcsim_env
 
-    run govc namespace.vmclass.create -name=test-class-1 -cpus=16 -memory=16000
+    run govc namespace.vmclass.info
+    assert_failure
+
+    run govc namespace.vmclass.create -cpus=16 -memory=16000 test-class-1
+    assert_success
+
+    run govc namespace.vmclass.info test-class-1
     assert_success
 
-    c=$(govc namespace.vmclass.info test-class-1 | jq)
+    c=$(govc namespace.vmclass.info -json test-class-1 | jq)
     assert_equal "16" $(echo $c | jq -r '."cpu_count"')
     assert_equal "16000" $(echo $c | jq -r '."memory_mb"')
 
@@ -261,15 +277,18 @@ load test_helper
 @test "namespace.vmclass.ls" {
     vcsim_env
 
-    ls=$(govc namespace.vmclass.ls)
+    run govc namespace.vmclass.ls
+    assert_success ""
+
+    ls=$(govc namespace.vmclass.ls -json)
     assert_equal "0" $(echo $ls | jq length)
 
-    govc namespace.vmclass.create -name=test-class-1 -cpus=16 -memory=16000
-    ls=$(govc namespace.vmclass.ls)
+    govc namespace.vmclass.create -cpus=16 -memory=16000 test-class-1
+    ls=$(govc namespace.vmclass.ls -json)
     assert_equal "1" $(echo $ls | jq length)
 
-    govc namespace.vmclass.create -name=test-class-2 -cpus=16 -memory=16000
-    ls=$(govc namespace.vmclass.ls)
+    govc namespace.vmclass.create -cpus=16 -memory=16000 test-class-2
+    ls=$(govc namespace.vmclass.ls -json)
     assert_equal "2" $(echo $ls | jq length)
 }
 
@@ -280,8 +299,8 @@ load test_helper
     assert_failure
     assert_matches "404 Not Found"
 
-    govc namespace.vmclass.create -name=test-class-1 -cpus=16 -memory=16000
+    govc namespace.vmclass.create -cpus=16 -memory=16000 test-class-1
 
     run govc namespace.vmclass.rm test-class-1
     assert_success
-}
\ No newline at end of file
+}