[lxc-devel] [lxd/master] Cobra all the things (CLI)

stgraber on Github lxc-bot at linuxcontainers.org
Sat Feb 24 02:38:36 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180224/2ec06ca7/attachment.bin>
-------------- next part --------------
From 592d0aa4f9784e8bc978db50e9f63a1fd512df3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 23 Feb 2018 19:23:33 -0500
Subject: [PATCH 1/5] lxd-p2c: Drop duplicate definition of Use
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd-p2c/main.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lxd-p2c/main.go b/lxd-p2c/main.go
index 5a9d71340..535f71305 100644
--- a/lxd-p2c/main.go
+++ b/lxd-p2c/main.go
@@ -15,7 +15,6 @@ type cmdGlobal struct {
 
 func main() {
 	app := &cobra.Command{}
-	app.Use = "lxd-p2c"
 	app.Short = "Physical to container migration tool"
 	app.Long = `Description:
   Physical to container migration tool

From 7f7aca0e60bc90cd40a4086e7035a7e5b118530d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 23 Feb 2018 19:23:47 -0500
Subject: [PATCH 2/5] fuidshift: Drop duplicate definition of Use
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 fuidshift/main.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fuidshift/main.go b/fuidshift/main.go
index 3bf1f18b4..0909b976d 100644
--- a/fuidshift/main.go
+++ b/fuidshift/main.go
@@ -15,7 +15,6 @@ type cmdGlobal struct {
 
 func main() {
 	app := &cobra.Command{}
-	app.Use = "fuidshift"
 	app.Short = "UID/GID shifter"
 	app.Long = `Description:
   UID/GID shifter

From c500a82f3920a9c5783df7a8ece10a8e3d273693 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 23 Feb 2018 20:47:28 -0500
Subject: [PATCH 3/5] lxd-benchmark: Port to cobra
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd-benchmark/main.go        | 205 +++++++++++++++++++++----------------------
 lxd-benchmark/main_delete.go |  50 +++++++++++
 lxd-benchmark/main_init.go   |  55 ++++++++++++
 lxd-benchmark/main_launch.go |  55 ++++++++++++
 lxd-benchmark/main_start.go  |  50 +++++++++++
 lxd-benchmark/main_stop.go   |  50 +++++++++++
 6 files changed, 362 insertions(+), 103 deletions(-)
 create mode 100644 lxd-benchmark/main_delete.go
 create mode 100644 lxd-benchmark/main_init.go
 create mode 100644 lxd-benchmark/main_launch.go
 create mode 100644 lxd-benchmark/main_start.go
 create mode 100644 lxd-benchmark/main_stop.go

diff --git a/lxd-benchmark/main.go b/lxd-benchmark/main.go
index 50cdfe87d..1d0da671e 100644
--- a/lxd-benchmark/main.go
+++ b/lxd-benchmark/main.go
@@ -1,135 +1,134 @@
 package main
 
 import (
-	"fmt"
 	"os"
 	"time"
 
+	"github.com/spf13/cobra"
+
 	"github.com/lxc/lxd/client"
 	"github.com/lxc/lxd/lxd-benchmark/benchmark"
 	"github.com/lxc/lxd/shared"
-	"github.com/lxc/lxd/shared/gnuflag"
 	"github.com/lxc/lxd/shared/version"
 )
 
-var argCount = gnuflag.Int("count", 1, "Number of containers to create")
-var argParallel = gnuflag.Int("parallel", -1, "Number of threads to use")
-var argImage = gnuflag.String("image", "ubuntu:", "Image to use for the test")
-var argPrivileged = gnuflag.Bool("privileged", false, "Use privileged containers")
-var argStart = gnuflag.Bool("start", true, "Start the container after creation")
-var argFreeze = gnuflag.Bool("freeze", false, "Freeze the container right after start")
-var argReportFile = gnuflag.String("report-file", "", "A CSV file to write test file to. If the file is present, it will be appended to.")
-var argReportLabel = gnuflag.String("report-label", "", "A label for the report entry. By default, the action is used.")
-
-func main() {
-	err := run(os.Args)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "error: %s\n", err)
-		os.Exit(1)
-	}
+type cmdGlobal struct {
+	flagHelp        bool
+	flagParallel    int
+	flagReportFile  string
+	flagReportLabel string
+	flagVersion     bool
 
-	os.Exit(0)
+	srv    lxd.ContainerServer
+	report *benchmark.CSVReport
 }
 
-func run(args []string) error {
-	// Parse command line
-	// "spawn" is being deprecated, use "launch" instead.
-	if len(os.Args) == 1 || !shared.StringInSlice(os.Args[1], []string{"launch", "spawn", "start", "stop", "delete"}) {
-		if len(os.Args) > 1 && os.Args[1] == "--version" {
-			fmt.Println(version.Version)
-			return nil
-		}
-
-		out := os.Stderr
-		if len(os.Args) > 1 && os.Args[1] == "--help" {
-			out = os.Stdout
-		}
-		gnuflag.SetOut(out)
-
-		fmt.Fprintf(out, "Usage: %s launch [--count=COUNT] [--image=IMAGE] [--privileged=BOOL] [--start=BOOL] [--freeze=BOOL] [--parallel=COUNT]\n", os.Args[0])
-		fmt.Fprintf(out, "       %s start [--parallel=COUNT]\n", os.Args[0])
-		fmt.Fprintf(out, "       %s stop [--parallel=COUNT]\n", os.Args[0])
-		fmt.Fprintf(out, "       %s delete [--parallel=COUNT]\n\n", os.Args[0])
-		gnuflag.PrintDefaults()
-		fmt.Fprintf(out, "\n")
-
-		if len(os.Args) > 1 && os.Args[1] == "--help" {
-			return nil
-		}
-
-		return fmt.Errorf("A valid action (launch, start, stop, delete) must be passed")
-	}
-
-	gnuflag.Parse(true)
-
+func (c *cmdGlobal) Setup() error {
 	// Connect to LXD
-	c, err := lxd.ConnectLXDUnix("", nil)
+	srv, err := lxd.ConnectLXDUnix("", nil)
 	if err != nil {
 		return err
 	}
+	c.srv = srv
 
-	benchmark.PrintServerInfo(c)
+	// Print the initial header
+	benchmark.PrintServerInfo(srv)
 
-	var report *benchmark.CSVReport
-	if *argReportFile != "" {
-		report = &benchmark.CSVReport{Filename: *argReportFile}
-		if shared.PathExists(*argReportFile) {
-			err := report.Load()
+	// Setup report handling
+	if c.flagReportFile != "" {
+		c.report = &benchmark.CSVReport{Filename: c.flagReportFile}
+		if shared.PathExists(c.flagReportFile) {
+			err := c.report.Load()
 			if err != nil {
 				return err
 			}
 		}
 	}
 
-	action := os.Args[1]
-	var duration time.Duration
-	switch action {
-	// "spawn" is being deprecated.
-	case "launch", "spawn":
-		duration, err = benchmark.LaunchContainers(
-			c, *argCount, *argParallel, *argImage, *argPrivileged, *argStart, *argFreeze)
-		if err != nil {
-			return err
-		}
-	case "start":
-		containers, err := benchmark.GetContainers(c)
-		if err != nil {
-			return err
-		}
-		duration, err = benchmark.StartContainers(c, containers, *argParallel)
-		if err != nil {
-			return err
-		}
-	case "stop":
-		containers, err := benchmark.GetContainers(c)
-		if err != nil {
-			return err
-		}
-		duration, err = benchmark.StopContainers(c, containers, *argParallel)
-		if err != nil {
-			return err
-		}
-	case "delete":
-		containers, err := benchmark.GetContainers(c)
-		if err != nil {
-			return err
-		}
-		duration, err = benchmark.DeleteContainers(c, containers, *argParallel)
-		if err != nil {
-			return err
-		}
+	return nil
+}
+
+func (c *cmdGlobal) Teardown(action string, duration time.Duration) error {
+	// Nothing to do with not reporting
+	if c.report == nil {
+		return nil
 	}
 
-	if report != nil {
-		label := action
-		if *argReportLabel != "" {
-			label = *argReportLabel
-		}
-		report.AddRecord(label, duration)
-		err := report.Write()
-		if err != nil {
-			return err
-		}
+	label := action
+	if c.flagReportLabel != "" {
+		label = c.flagReportLabel
+	}
+
+	c.report.AddRecord(label, duration)
+
+	err := c.report.Write()
+	if err != nil {
+		return err
 	}
+
 	return nil
 }
+
+func main() {
+	app := &cobra.Command{}
+	app.Use = "lxd-benchmark"
+	app.Short = "Benchmark performance of LXD"
+	app.Long = `Description:
+  Benchmark performance of LXD
+
+  This tool lets you benchmark various actions on a local LXD daemon.
+
+  It can be used to just to check how fast a given LXD host is, to
+  compare performance on different servers or for performance tracking
+  when doing changes to the LXD codebase.
+
+  A CSV report can be produced to be consumed by graphing software.
+`
+	app.Example = `  # Spawn 20 Ubuntu containers in batches of 4
+  lxd-benchmark launch --count 20 --parallel 4
+
+  # Create 50 Alpine containers in batches of 10
+  lxd-benchmark init --count 50 --parallel 10 images:alpine/edge
+
+  # Delete all test containers using dynamic batch size
+  lxd-benchmark delete`
+	app.SilenceUsage = true
+
+	// Global flags
+	globalCmd := cmdGlobal{}
+	app.PersistentFlags().BoolVar(&globalCmd.flagVersion, "version", false, "Print version number")
+	app.PersistentFlags().BoolVarP(&globalCmd.flagHelp, "help", "h", false, "Print help")
+	app.PersistentFlags().IntVarP(&globalCmd.flagParallel, "parallel", "P", -1, "Number of threads to use"+"``")
+	app.PersistentFlags().StringVar(&globalCmd.flagReportFile, "report-file", "", "Path to the CSV report file"+"``")
+	app.PersistentFlags().StringVar(&globalCmd.flagReportLabel, "report-label", "", "Label for the new entry in the report [default=ACTION]"+"``")
+
+	// Version handling
+	app.SetVersionTemplate("{{.Version}}\n")
+	app.Version = version.Version
+
+	// init sub-command
+	initCmd := cmdInit{global: &globalCmd}
+	app.AddCommand(initCmd.Command())
+
+	// launch sub-command
+	launchCmd := cmdLaunch{global: &globalCmd, init: &initCmd}
+	app.AddCommand(launchCmd.Command())
+
+	// start sub-command
+	startCmd := cmdStart{global: &globalCmd}
+	app.AddCommand(startCmd.Command())
+
+	// stop sub-command
+	stopCmd := cmdStop{global: &globalCmd}
+	app.AddCommand(stopCmd.Command())
+
+	// delete sub-command
+	deleteCmd := cmdDelete{global: &globalCmd}
+	app.AddCommand(deleteCmd.Command())
+
+	// Run the main command and handle errors
+	err := app.Execute()
+	if err != nil {
+		os.Exit(1)
+	}
+}
diff --git a/lxd-benchmark/main_delete.go b/lxd-benchmark/main_delete.go
new file mode 100644
index 000000000..5b0ed64c3
--- /dev/null
+++ b/lxd-benchmark/main_delete.go
@@ -0,0 +1,50 @@
+package main
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/lxc/lxd/lxd-benchmark/benchmark"
+)
+
+type cmdDelete struct {
+	cmd    *cobra.Command
+	global *cmdGlobal
+}
+
+func (c *cmdDelete) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "delete"
+	cmd.Short = "Delete containers"
+	cmd.RunE = c.Run
+
+	c.cmd = cmd
+	return cmd
+}
+
+func (c *cmdDelete) Run(cmd *cobra.Command, args []string) error {
+	// Run shared setup code
+	err := c.global.Setup()
+	if err != nil {
+		return err
+	}
+
+	// Get the containers
+	containers, err := benchmark.GetContainers(c.global.srv)
+	if err != nil {
+		return err
+	}
+
+	// Run the test
+	duration, err := benchmark.DeleteContainers(c.global.srv, containers, c.global.flagParallel)
+	if err != nil {
+		return err
+	}
+
+	// Run shared reporting and teardown code
+	err = c.global.Teardown("delete", duration)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/lxd-benchmark/main_init.go b/lxd-benchmark/main_init.go
new file mode 100644
index 000000000..b7ef8d30d
--- /dev/null
+++ b/lxd-benchmark/main_init.go
@@ -0,0 +1,55 @@
+package main
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/lxc/lxd/lxd-benchmark/benchmark"
+)
+
+type cmdInit struct {
+	cmd    *cobra.Command
+	global *cmdGlobal
+
+	flagCount      int
+	flagPrivileged bool
+}
+
+func (c *cmdInit) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "init [[<remote>:]<image>]"
+	cmd.Short = "Create containers"
+	cmd.RunE = c.Run
+	cmd.Flags().IntVarP(&c.flagCount, "count", "C", 1, "Number of containers to create"+"``")
+	cmd.Flags().BoolVar(&c.flagPrivileged, "privileged", false, "Use privileged containers")
+
+	c.cmd = cmd
+	return cmd
+}
+
+func (c *cmdInit) Run(cmd *cobra.Command, args []string) error {
+	// Run shared setup code
+	err := c.global.Setup()
+	if err != nil {
+		return err
+	}
+
+	// Choose the image
+	image := "ubuntu:"
+	if len(args) > 0 {
+		image = args[0]
+	}
+
+	// Run the test
+	duration, err := benchmark.LaunchContainers(c.global.srv, c.flagCount, c.global.flagParallel, image, c.flagPrivileged, false, false)
+	if err != nil {
+		return err
+	}
+
+	// Run shared reporting and teardown code
+	err = c.global.Teardown("init", duration)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/lxd-benchmark/main_launch.go b/lxd-benchmark/main_launch.go
new file mode 100644
index 000000000..419d16fca
--- /dev/null
+++ b/lxd-benchmark/main_launch.go
@@ -0,0 +1,55 @@
+package main
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/lxc/lxd/lxd-benchmark/benchmark"
+)
+
+type cmdLaunch struct {
+	cmd    *cobra.Command
+	global *cmdGlobal
+	init   *cmdInit
+
+	flagFreeze bool
+}
+
+func (c *cmdLaunch) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "launch [[<remote>:]<image>]"
+	cmd.Short = "Create and start containers"
+	cmd.RunE = c.Run
+	cmd.Flags().AddFlagSet(c.init.cmd.Flags())
+	cmd.Flags().BoolVarP(&c.flagFreeze, "freeze", "F", false, "Freeze the container right after start")
+
+	c.cmd = cmd
+	return cmd
+}
+
+func (c *cmdLaunch) Run(cmd *cobra.Command, args []string) error {
+	// Run shared setup code
+	err := c.global.Setup()
+	if err != nil {
+		return err
+	}
+
+	// Choose the image
+	image := "ubuntu:"
+	if len(args) > 0 {
+		image = args[0]
+	}
+
+	// Run the test
+	duration, err := benchmark.LaunchContainers(c.global.srv, c.init.flagCount, c.global.flagParallel, image, c.init.flagPrivileged, true, c.flagFreeze)
+	if err != nil {
+		return err
+	}
+
+	// Run shared reporting and teardown code
+	err = c.global.Teardown("launch", duration)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/lxd-benchmark/main_start.go b/lxd-benchmark/main_start.go
new file mode 100644
index 000000000..b6d9655c1
--- /dev/null
+++ b/lxd-benchmark/main_start.go
@@ -0,0 +1,50 @@
+package main
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/lxc/lxd/lxd-benchmark/benchmark"
+)
+
+type cmdStart struct {
+	cmd    *cobra.Command
+	global *cmdGlobal
+}
+
+func (c *cmdStart) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "start"
+	cmd.Short = "Start containers"
+	cmd.RunE = c.Run
+
+	c.cmd = cmd
+	return cmd
+}
+
+func (c *cmdStart) Run(cmd *cobra.Command, args []string) error {
+	// Run shared setup code
+	err := c.global.Setup()
+	if err != nil {
+		return err
+	}
+
+	// Get the containers
+	containers, err := benchmark.GetContainers(c.global.srv)
+	if err != nil {
+		return err
+	}
+
+	// Run the test
+	duration, err := benchmark.StartContainers(c.global.srv, containers, c.global.flagParallel)
+	if err != nil {
+		return err
+	}
+
+	// Run shared reporting and teardown code
+	err = c.global.Teardown("start", duration)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/lxd-benchmark/main_stop.go b/lxd-benchmark/main_stop.go
new file mode 100644
index 000000000..f41f42f67
--- /dev/null
+++ b/lxd-benchmark/main_stop.go
@@ -0,0 +1,50 @@
+package main
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/lxc/lxd/lxd-benchmark/benchmark"
+)
+
+type cmdStop struct {
+	cmd    *cobra.Command
+	global *cmdGlobal
+}
+
+func (c *cmdStop) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "stop"
+	cmd.Short = "Stop containers"
+	cmd.RunE = c.Run
+
+	c.cmd = cmd
+	return cmd
+}
+
+func (c *cmdStop) Run(cmd *cobra.Command, args []string) error {
+	// Run shared setup code
+	err := c.global.Setup()
+	if err != nil {
+		return err
+	}
+
+	// Get the containers
+	containers, err := benchmark.GetContainers(c.global.srv)
+	if err != nil {
+		return err
+	}
+
+	// Run the test
+	duration, err := benchmark.StopContainers(c.global.srv, containers, c.global.flagParallel)
+	if err != nil {
+		return err
+	}
+
+	// Run shared reporting and teardown code
+	err = c.global.Teardown("stop", duration)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}

From 9d3e3bf47ba4260211286cb12e6bdaab1c27f983 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 23 Feb 2018 20:54:51 -0500
Subject: [PATCH 4/5] fuidshift: Reshuffle code to match lxd-benchmark
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 fuidshift/main.go       | 32 ++++----------------------------
 fuidshift/main_shift.go | 29 +++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 28 deletions(-)

diff --git a/fuidshift/main.go b/fuidshift/main.go
index 0909b976d..4fc45d9d9 100644
--- a/fuidshift/main.go
+++ b/fuidshift/main.go
@@ -3,8 +3,6 @@ package main
 import (
 	"os"
 
-	"github.com/spf13/cobra"
-
 	"github.com/lxc/lxd/shared/version"
 )
 
@@ -14,28 +12,14 @@ type cmdGlobal struct {
 }
 
 func main() {
-	app := &cobra.Command{}
-	app.Short = "UID/GID shifter"
-	app.Long = `Description:
-  UID/GID shifter
-
-  This tool lets you remap a filesystem tree, switching it from one
-  set of UID/GID ranges to another.
-
-  This is mostly useful when retrieving a wrongly shifted filesystem tree
-  from a backup or broken system and having to remap everything either to
-  the host UID/GID range (uid/gid 0 is root) or to an existing container's
-  range.
-
-
-  A range is represented as <u|b|g>:<first_container_id>:<first_host_id>:<size>.
-  Where "u" means shift uid, "g" means shift gid and "b" means shift uid and gid.
-`
-	app.Example = `  fuidshift my-dir/ b:0:100000:65536 u:10000:1000:1`
+	// shift command (main)
+	shiftCmd := cmdShift{}
+	app := shiftCmd.Command()
 	app.SilenceUsage = true
 
 	// Global flags
 	globalCmd := cmdGlobal{}
+	shiftCmd.global = &globalCmd
 	app.PersistentFlags().BoolVar(&globalCmd.flagVersion, "version", false, "Print version number")
 	app.PersistentFlags().BoolVarP(&globalCmd.flagHelp, "help", "h", false, "Print help")
 
@@ -43,14 +27,6 @@ func main() {
 	app.SetVersionTemplate("{{.Version}}\n")
 	app.Version = version.Version
 
-	// shift command (main)
-	shiftCmd := cmdShift{global: &globalCmd}
-	app.Flags().BoolVarP(&shiftCmd.flagTestMode, "test", "t", false, "Test mode (no change to files)")
-	app.Flags().BoolVarP(&shiftCmd.flagReverse, "reverse", "r", false, "Perform a reverse mapping")
-	app.Use = "fuidshift <directory> <range> [<range>...]"
-	app.RunE = shiftCmd.Run
-	app.Args = cobra.ArbitraryArgs
-
 	// Run the main command and handle errors
 	err := app.Execute()
 	if err != nil {
diff --git a/fuidshift/main_shift.go b/fuidshift/main_shift.go
index 32c939bc0..74403aaed 100644
--- a/fuidshift/main_shift.go
+++ b/fuidshift/main_shift.go
@@ -10,12 +10,41 @@ import (
 )
 
 type cmdShift struct {
+	cmd    *cobra.Command
 	global *cmdGlobal
 
 	flagReverse  bool
 	flagTestMode bool
 }
 
+func (c *cmdShift) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "fuidshift <directory> <range> [<range>...]"
+	cmd.Short = "UID/GID shifter"
+	cmd.Long = `Description:
+  UID/GID shifter
+
+  This tool lets you remap a filesystem tree, switching it from one
+  set of UID/GID ranges to another.
+
+  This is mostly useful when retrieving a wrongly shifted filesystem tree
+  from a backup or broken system and having to remap everything either to
+  the host UID/GID range (uid/gid 0 is root) or to an existing container's
+  range.
+
+
+  A range is represented as <u|b|g>:<first_container_id>:<first_host_id>:<size>.
+  Where "u" means shift uid, "g" means shift gid and "b" means shift uid and gid.
+`
+	cmd.Example = `  fuidshift my-dir/ b:0:100000:65536 u:10000:1000:1`
+	cmd.RunE = c.Run
+	cmd.Flags().BoolVarP(&c.flagTestMode, "test", "t", false, "Test mode (no change to files)")
+	cmd.Flags().BoolVarP(&c.flagReverse, "reverse", "r", false, "Perform a reverse mapping")
+
+	c.cmd = cmd
+	return cmd
+}
+
 func (c *cmdShift) Run(cmd *cobra.Command, args []string) error {
 	// Help and usage
 	if len(args) == 0 {

From 038e9ae9986e2867219ac41145947b4723e14cd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 23 Feb 2018 21:02:48 -0500
Subject: [PATCH 5/5] lxd-p2c: Reshuffle code to match lxd-benchmark
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd-p2c/main.go         | 40 ++++++++--------------------------------
 lxd-p2c/main_migrate.go | 29 +++++++++++++++++++++++++++++
 lxd-p2c/main_netcat.go  | 13 +++++++++++++
 3 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/lxd-p2c/main.go b/lxd-p2c/main.go
index 535f71305..a350214ed 100644
--- a/lxd-p2c/main.go
+++ b/lxd-p2c/main.go
@@ -14,24 +14,17 @@ type cmdGlobal struct {
 }
 
 func main() {
-	app := &cobra.Command{}
-	app.Short = "Physical to container migration tool"
-	app.Long = `Description:
-  Physical to container migration tool
-
-  This tool lets you turn any Linux filesystem (including your current one)
-  into a LXD container on a remote LXD host.
-
-  It will setup a clean mount tree made of the root filesystem and any
-  additional mount you list, then transfer this through LXD's migration
-  API to create a new container from it.
-
-  The same set of options as ` + "`lxc launch`" + ` are also supported.
-`
+	// migrate command (main)
+	migrateCmd := cmdMigrate{}
+	app := migrateCmd.Command()
 	app.SilenceUsage = true
 
+	// Workaround for main command
+	app.Args = cobra.ArbitraryArgs
+
 	// Global flags
 	globalCmd := cmdGlobal{}
+	migrateCmd.global = &globalCmd
 	app.PersistentFlags().BoolVar(&globalCmd.flagVersion, "version", false, "Print version number")
 	app.PersistentFlags().BoolVarP(&globalCmd.flagHelp, "help", "h", false, "Print help")
 
@@ -39,26 +32,9 @@ func main() {
 	app.SetVersionTemplate("{{.Version}}\n")
 	app.Version = version.Version
 
-	// migrate command (main)
-	migrateCmd := cmdMigrate{global: &globalCmd}
-	app.Flags().StringArrayVarP(&migrateCmd.flagConfig, "config", "c", nil, "Configuration key and value to set on the container"+"``")
-	app.Flags().StringVarP(&migrateCmd.flagNetwork, "network", "n", "", "Network to use for the container"+"``")
-	app.Flags().StringArrayVarP(&migrateCmd.flagProfile, "profile", "p", nil, "Profile to apply to the container"+"``")
-	app.Flags().StringVarP(&migrateCmd.flagStorage, "storage", "s", "", "Storage pool to use for the container"+"``")
-	app.Flags().StringVarP(&migrateCmd.flagType, "type", "t", "", "Instance type to use for the container"+"``")
-	app.Flags().BoolVar(&migrateCmd.flagNoProfiles, "no-profiles", false, "Create the container with no profiles applied")
-	app.Use = "lxd-p2c <target URL> <container name> <filesystem root> [<filesystem mounts>...]"
-	app.RunE = migrateCmd.Run
-	app.Args = cobra.ArbitraryArgs
-
 	// netcat sub-command
 	netcatCmd := cmdNetcat{global: &globalCmd}
-	appNetcat := &cobra.Command{}
-	appNetcat.Use = "netcat <address>"
-	appNetcat.Hidden = true
-	appNetcat.Short = "Sends stdin data to a unix socket"
-	appNetcat.RunE = netcatCmd.Run
-	app.AddCommand(appNetcat)
+	app.AddCommand(netcatCmd.Command())
 
 	// Run the main command and handle errors
 	err := app.Execute()
diff --git a/lxd-p2c/main_migrate.go b/lxd-p2c/main_migrate.go
index 9b25cec09..39c5f4536 100644
--- a/lxd-p2c/main_migrate.go
+++ b/lxd-p2c/main_migrate.go
@@ -17,6 +17,7 @@ import (
 )
 
 type cmdMigrate struct {
+	cmd    *cobra.Command
 	global *cmdGlobal
 
 	flagConfig     []string
@@ -27,6 +28,34 @@ type cmdMigrate struct {
 	flagNoProfiles bool
 }
 
+func (c *cmdMigrate) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+	cmd.Use = "lxd-p2c <target URL> <container name> <filesystem root> [<filesystem mounts>...]"
+	cmd.Short = "Physical to container migration tool"
+	cmd.Long = `Description:
+  Physical to container migration tool
+
+  This tool lets you turn any Linux filesystem (including your current one)
+  into a LXD container on a remote LXD host.
+
+  It will setup a clean mount tree made of the root filesystem and any
+  additional mount you list, then transfer this through LXD's migration
+  API to create a new container from it.
+
+  The same set of options as ` + "`lxc launch`" + ` are also supported.
+`
+	cmd.RunE = c.Run
+	cmd.Flags().StringArrayVarP(&c.flagConfig, "config", "c", nil, "Configuration key and value to set on the container"+"``")
+	cmd.Flags().StringVarP(&c.flagNetwork, "network", "n", "", "Network to use for the container"+"``")
+	cmd.Flags().StringArrayVarP(&c.flagProfile, "profile", "p", nil, "Profile to apply to the container"+"``")
+	cmd.Flags().StringVarP(&c.flagStorage, "storage", "s", "", "Storage pool to use for the container"+"``")
+	cmd.Flags().StringVarP(&c.flagType, "type", "t", "", "Instance type to use for the container"+"``")
+	cmd.Flags().BoolVar(&c.flagNoProfiles, "no-profiles", false, "Create the container with no profiles applied")
+
+	c.cmd = cmd
+	return cmd
+}
+
 func (c *cmdMigrate) Run(cmd *cobra.Command, args []string) error {
 	// Help and usage
 	if len(args) == 0 {
diff --git a/lxd-p2c/main_netcat.go b/lxd-p2c/main_netcat.go
index 20350a27d..53814bd16 100644
--- a/lxd-p2c/main_netcat.go
+++ b/lxd-p2c/main_netcat.go
@@ -13,9 +13,22 @@ import (
 )
 
 type cmdNetcat struct {
+	cmd    *cobra.Command
 	global *cmdGlobal
 }
 
+func (c *cmdNetcat) Command() *cobra.Command {
+	cmd := &cobra.Command{}
+
+	cmd.Use = "netcat <address>"
+	cmd.Short = "Sends stdin data to a unix socket"
+	cmd.RunE = c.Run
+	cmd.Hidden = true
+
+	c.cmd = cmd
+	return cmd
+}
+
 func (c *cmdNetcat) Run(cmd *cobra.Command, args []string) error {
 	// Help and usage
 	if len(args) == 0 {


More information about the lxc-devel mailing list