From 88d14fcb6d9f85d15710c6bd57668b0acd5d3e16 Mon Sep 17 00:00:00 2001 From: Jan Dubois Date: Tue, 27 Apr 2021 15:20:34 -0700 Subject: [PATCH] Move privileged subcommands to individual files under cmd/priv/ Also adds cmd.Abort() for standardized command failure. Signed-off-by: Jan Dubois --- cmd/priv/hyperkit.go | 40 +++++++++++++++++ cmd/priv/nfs-exports.go | 29 ++++++++++++ cmd/priv/uuid-to-mac-addr.go | 21 +++++++++ cmd/root.go | 11 +++++ main.go | 87 ++++++++++-------------------------- 5 files changed, 124 insertions(+), 64 deletions(-) create mode 100644 cmd/priv/hyperkit.go create mode 100644 cmd/priv/nfs-exports.go create mode 100644 cmd/priv/uuid-to-mac-addr.go diff --git a/cmd/priv/hyperkit.go b/cmd/priv/hyperkit.go new file mode 100644 index 0000000..1a0762d --- /dev/null +++ b/cmd/priv/hyperkit.go @@ -0,0 +1,40 @@ +package priv + +import ( + "encoding/json" + "fmt" + "os" + + hyperkit "github.com/moby/hyperkit/go" + "github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd" +) + +func Hyperkit() { + if len(os.Args) != 5 { + cmd.Abort("usage: hyperkit CONFIG DISKS CMDLINE") + } + + var h hyperkit.HyperKit + err := json.Unmarshal([]byte(os.Args[2]), &h) + if err != nil { + cmd.Abort("Unmarshalling hyperkit structure failed: %v", err) + } + + var disks []hyperkit.RawDisk + err = json.Unmarshal([]byte(os.Args[3]), &disks) + if err != nil { + cmd.Abort("Unmarshalling hyperkit disks structure failed: %v", err) + } + + // Type conversion from hyperkit.RawDisk to hyperkit.Disk + for _, disk := range disks { + h.Disks = append(h.Disks, &disk) + } + + _, err = h.Start(os.Args[4]) + if err != nil { + cmd.Abort("Failed to start hyperkit: %v", err) + } + _, _ = fmt.Fprintln(os.Stderr, "Hyperkit started successfully") + os.Exit(0) +} diff --git a/cmd/priv/nfs-exports.go b/cmd/priv/nfs-exports.go new file mode 100644 index 0000000..0367abb --- /dev/null +++ b/cmd/priv/nfs-exports.go @@ -0,0 +1,29 @@ +package priv + +import ( + "fmt" + "os" + + "github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd" + "github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit" +) + +func NFSExports() { + if len(os.Args) < 4 { + cmd.Abort("usage: nfs-exports [add|remove] arguments") + } + + var err error + switch os.Args[2] { + case "add": + err = hyperkit.AddNFSExports(os.Args[3:]...) + case "remove": + err = hyperkit.RemoveNFSExports(os.Args[3:]...) + default: + err = fmt.Errorf("Unknown nfs-export subcommand: %s", os.Args[2]) + } + if err != nil { + cmd.Abort("nfs-export %s failed: %v", os.Args[2], err) + } + os.Exit(0) +} diff --git a/cmd/priv/uuid-to-mac-addr.go b/cmd/priv/uuid-to-mac-addr.go new file mode 100644 index 0000000..7337bc7 --- /dev/null +++ b/cmd/priv/uuid-to-mac-addr.go @@ -0,0 +1,21 @@ +package priv + +import ( + "fmt" + "os" + + "github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd" + "github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit" +) + +func UUIDtoMacAddr() { + if len(os.Args) != 3 { + cmd.Abort("usage: uuid-to-mac-addr UUID") + } + mac, err := hyperkit.GetMACAddressFromUUID(os.Args[2]) + if err != nil { + cmd.Abort("Getting MAC address from UUID failed: %v", err) + } + fmt.Println(mac) + os.Exit(0) +} diff --git a/cmd/root.go b/cmd/root.go index ba00bed..3722b9a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,9 @@ package cmd import ( + "fmt" "os" + "strings" "github.com/docker/machine/libmachine/log" "github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit" @@ -41,6 +43,15 @@ func onInit() { } } +func Abort(format string, args ...interface{}) { + msg := fmt.Sprintf(format, args...) + _, _ = os.Stderr.WriteString(msg) + if !strings.HasSuffix(msg, "\n") { + _, _ = os.Stderr.WriteString("\n") + } + os.Exit(1) +} + func Execute() error { return rootCmd.Execute() } diff --git a/main.go b/main.go index 280c3d5..cbced38 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "encoding/json" "fmt" "os" "path/filepath" @@ -25,8 +24,8 @@ import ( "github.com/docker/machine/libmachine/drivers/plugin" "github.com/docker/machine/libmachine/drivers/plugin/localbinary" - mobyhyperkit "github.com/moby/hyperkit/go" "github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd" + "github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd/priv" "github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit" ) @@ -34,75 +33,31 @@ func main() { if syscall.Geteuid() != 0 { executable, err := os.Executable() if err != nil { - fmt.Fprintf(os.Stderr, "cannot determina name of executable: %v", err) - os.Exit(1) + cmd.Abort("Cannot determine name of executable: %v", err) } permErr := "%s needs to run with elevated permissions. " + "Please run the following command, then try again: " + "sudo chown root:wheel %s && sudo chmod u+s %s" - fmt.Fprintf(os.Stderr, permErr, filepath.Base(executable), executable, executable) - os.Exit(1) + cmd.Abort(permErr, filepath.Base(executable), executable, executable) } - if len(os.Args) == 3 && os.Args[1] == "uuid-to-mac-addr" { - mac, err := hyperkit.GetMACAddressFromUUID(os.Args[2]) - if err != nil { - fmt.Fprintf(os.Stderr, "getting MAC address from UUID: %v", err) - os.Exit(1) - } - fmt.Println(mac) - return - } - - if len(os.Args) > 3 && os.Args[1] == "nfs-exports" { - var err error - if os.Args[2] == "add" { - err = hyperkit.AddNFSExports(os.Args[3:]...) - } else if os.Args[2] == "remove" { - err = hyperkit.RemoveNFSExports(os.Args[3:]...) - } else { - err = fmt.Errorf("unknown nfs-export subcommand: %s", os.Args[2]) - } - if err != nil { - fmt.Fprintf(os.Stderr, "nfs-export %s failed: %v", os.Args[2], err) - os.Exit(1) + if len(os.Args) > 1 { + // All of the privileged commands will call os.Exit() and never return + switch os.Args[1] { + case "hyperkit": + priv.Hyperkit() + case "nfs-exports": + priv.NFSExports() + case "uuid-to-mac-addr": + priv.UUIDtoMacAddr() } - return - } - - if len(os.Args) == 5 && os.Args[1] == "hyperkit" { - var h mobyhyperkit.HyperKit - err := json.Unmarshal([]byte(os.Args[2]), &h) - if err != nil { - fmt.Fprintf(os.Stderr, "unmarshaling hyperkit structure failed: %v", err) - os.Exit(1) - } - - var disks []mobyhyperkit.RawDisk - err = json.Unmarshal([]byte(os.Args[3]), &disks) - if err != nil { - fmt.Fprintf(os.Stderr, "unmarshaling hyperkit disks structure failed: %v", err) - os.Exit(1) - } - for _, disk := range disks { - h.Disks = append(h.Disks, &disk) - } - - _, err = h.Start(os.Args[4]) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to start hyperkit: %v", err) - os.Exit(1) - } - fmt.Fprintln(os.Stderr, "Hyperkit started successfully") - os.Exit(0) } // Drop root privileges before running driver mode, or commands via cobra if err := syscall.Setuid(syscall.Getuid()); err != nil { - fmt.Fprintf(os.Stderr, "cannot drop privileges: %v", err) - os.Exit(1) + cmd.Abort("Cannot drop privileges: %v", err) } if os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal { @@ -115,15 +70,19 @@ func main() { // driver, living in a different directory). executable, err := os.Executable() if err != nil { - fmt.Fprintf(os.Stderr, "cannot determine absolute path to current executable: %v", err) - os.Exit(1) + cmd.Abort("Cannot determine absolute path to current executable: %v", err) } executable, err = filepath.EvalSymlinks(executable) if err != nil { - fmt.Fprintf(os.Stderr, "cannot evaluate symlinks in path to current executable: %v", err) - os.Exit(1) + cmd.Abort("Cannot evaluate symlinks in path to current executable: %v", err) + } + err = os.Setenv("PATH", os.ExpandEnv(fmt.Sprintf("%s:$PATH", filepath.Dir(executable)))) + if err != nil { + cmd.Abort("Cannot update PATH: %v", err) } - os.Setenv("PATH", os.ExpandEnv(fmt.Sprintf("%s:$PATH", filepath.Dir(executable)))) - cmd.Execute() + err = cmd.Execute() + if err != nil { + cmd.Abort("Command failed: %v", err) + } }