From 9378c05c3726d6eb272f8684fe5cc61ff80363b6 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 12 Aug 2014 10:45:41 -0700 Subject: [PATCH 1/6] Remove nsinit main calling pkg Signed-off-by: Michael Crosby --- nsinit/nsinit/nsinit.go | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 nsinit/nsinit/nsinit.go diff --git a/nsinit/nsinit/nsinit.go b/nsinit/nsinit/nsinit.go deleted file mode 100644 index 816c4da5f..000000000 --- a/nsinit/nsinit/nsinit.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "github.com/docker/libcontainer/nsinit" - -func main() { - nsinit.NsInit() -} From 51e6049226329f4264aa64b704ff00c16891c37c Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 12 Aug 2014 10:46:43 -0700 Subject: [PATCH 2/6] Make nsinit package main only Signed-off-by: Michael Crosby --- nsinit/config.go | 2 +- nsinit/exec.go | 2 +- nsinit/init.go | 2 +- nsinit/{cli.go => main.go} | 4 ++-- nsinit/nsenter.go | 2 +- nsinit/pause.go | 2 +- nsinit/stats.go | 2 +- nsinit/utils.go | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) rename nsinit/{cli.go => main.go} (96%) diff --git a/nsinit/config.go b/nsinit/config.go index 5beb04acb..e1f28fcc8 100644 --- a/nsinit/config.go +++ b/nsinit/config.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "encoding/json" diff --git a/nsinit/exec.go b/nsinit/exec.go index 4a38a61b4..f48ca17b1 100644 --- a/nsinit/exec.go +++ b/nsinit/exec.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "fmt" diff --git a/nsinit/init.go b/nsinit/init.go index e7a96632d..b37519648 100644 --- a/nsinit/init.go +++ b/nsinit/init.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "log" diff --git a/nsinit/cli.go b/nsinit/main.go similarity index 96% rename from nsinit/cli.go rename to nsinit/main.go index c8d153312..25a80b228 100644 --- a/nsinit/cli.go +++ b/nsinit/main.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "log" @@ -26,7 +26,7 @@ func preload(context *cli.Context) error { return nil } -func NsInit() { +func main() { // we need to check our argv 0 for any registred functions to run instead of the // normal cli code path diff --git a/nsinit/nsenter.go b/nsinit/nsenter.go index fabd65e9b..954de9923 100644 --- a/nsinit/nsenter.go +++ b/nsinit/nsenter.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "log" diff --git a/nsinit/pause.go b/nsinit/pause.go index 492a0e858..6744539c6 100644 --- a/nsinit/pause.go +++ b/nsinit/pause.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "log" diff --git a/nsinit/stats.go b/nsinit/stats.go index 3e59305b0..331d27f2c 100644 --- a/nsinit/stats.go +++ b/nsinit/stats.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "encoding/json" diff --git a/nsinit/utils.go b/nsinit/utils.go index 8525ba9a6..44194d885 100644 --- a/nsinit/utils.go +++ b/nsinit/utils.go @@ -1,4 +1,4 @@ -package nsinit +package main import ( "encoding/json" From 70367b2cf3c0e91995054c48650cba62a4945bbf Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 12 Aug 2014 11:43:12 -0700 Subject: [PATCH 3/6] Improve execin to support registering funcs This also changes the functionality of the default exec in to just be an existing func that is called than handles the implementation to exec a user user's process inside the container. This implements this functionallity in nsinit but is a base for how we will be handling these types of features inside docker. Signed-off-by: Michael Crosby --- namespaces/execin.go | 5 ++-- nsinit/exec.go | 6 ++-- nsinit/execfunc.go | 58 ++++++++++++++++++++++++++++++++++++++ nsinit/main.go | 29 +++++++++++++++---- nsinit/nsenter.go | 67 +++++++++++++++++++++++++------------------- nsinit/utils.go | 36 ++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 39 deletions(-) create mode 100644 nsinit/execfunc.go diff --git a/namespaces/execin.go b/namespaces/execin.go index 2ac9dba72..8958332a0 100644 --- a/namespaces/execin.go +++ b/namespaces/execin.go @@ -3,6 +3,7 @@ package namespaces import ( + "fmt" "io" "os" "os/exec" @@ -18,10 +19,10 @@ import ( // ExecIn reexec's the initPath with the argv 0 rewrite to "nsenter" so that it is able to run the // setns code in a single threaded environment joining the existing containers' namespaces. -func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs []string, initPath string, +func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs []string, initPath, action string, stdin io.Reader, stdout, stderr io.Writer, console string, startCallback func(*exec.Cmd)) (int, error) { - args := []string{"nsenter", "--nspid", strconv.Itoa(state.InitPid)} + args := []string{fmt.Sprintf("nsenter-%s", action), "--nspid", strconv.Itoa(state.InitPid)} if console != "" { args = append(args, "--console", console) diff --git a/nsinit/exec.go b/nsinit/exec.go index f48ca17b1..ae3e617b3 100644 --- a/nsinit/exec.go +++ b/nsinit/exec.go @@ -36,7 +36,7 @@ func execAction(context *cli.Context) { } if state != nil { - exitCode, err = startInExistingContainer(container, state, context) + exitCode, err = startInExistingContainer(container, state, "exec", context) } else { exitCode, err = startContainer(container, dataPath, []string(context.Args())) } @@ -52,7 +52,7 @@ func execAction(context *cli.Context) { // with the nsenter argument so that the C code can setns an the namespaces that we require. Then that // code path will drop us into the path that we can do the final setup of the namespace and exec the users // application. -func startInExistingContainer(config *libcontainer.Config, state *libcontainer.State, context *cli.Context) (int, error) { +func startInExistingContainer(config *libcontainer.Config, state *libcontainer.State, action string, context *cli.Context) (int, error) { var ( master *os.File console string @@ -102,7 +102,7 @@ func startInExistingContainer(config *libcontainer.Config, state *libcontainer.S }() } - return namespaces.ExecIn(config, state, context.Args(), os.Args[0], stdin, stdout, stderr, console, startCallback) + return namespaces.ExecIn(config, state, context.Args(), os.Args[0], action, stdin, stdout, stderr, console, startCallback) } // startContainer starts the container. Returns the exit status or -1 and an diff --git a/nsinit/execfunc.go b/nsinit/execfunc.go new file mode 100644 index 000000000..e8fdf8e7a --- /dev/null +++ b/nsinit/execfunc.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "log" + "os" + "text/tabwriter" + + "github.com/codegangsta/cli" + "github.com/docker/libcontainer" +) + +var execFuncCommand = cli.Command{ + Name: "func", + Usage: "execute a registered function inside an existing container", + Action: execFuncAction, + Flags: []cli.Flag{ + cli.BoolFlag{Name: "list", Usage: "list all registered functions"}, + cli.StringFlag{Name: "func", Usage: "function name to exec inside a container"}, + }, +} + +func execFuncAction(context *cli.Context) { + if context.Bool("list") { + w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0) + fmt.Fprint(w, "NAME\tUSAGE\n") + + for k, f := range argvs { + fmt.Fprintf(w, "%s\t%s\n", k, f.Usage) + } + + w.Flush() + + return + } + + var exitCode int + + config, err := loadContainer() + if err != nil { + log.Fatal(err) + } + + // FIXME: remove tty from container config, this should be per process + config.Tty = false + + state, err := libcontainer.GetState(dataPath) + if err != nil { + log.Fatalf("unable to read state.json: %s", err) + } + + exitCode, err = startInExistingContainer(config, state, context.String("func"), context) + if err != nil { + log.Fatal(err) + } + + os.Exit(exitCode) +} diff --git a/nsinit/main.go b/nsinit/main.go index 25a80b228..bd944b82f 100644 --- a/nsinit/main.go +++ b/nsinit/main.go @@ -9,11 +9,19 @@ import ( var ( logPath = os.Getenv("log") - argvs = make(map[string]func()) + argvs = make(map[string]*rFunc) ) func init() { - argvs["nsenter"] = nsenter + argvs["nsenter-exec"] = &rFunc{ + Usage: "execute a process inside an existing container", + Action: nsenterExec, + } + + argvs["nsenter-mknod"] = &rFunc{ + Usage: "mknod a device inside an existing container", + Action: nsenterMknod, + } } func preload(context *cli.Context) error { @@ -26,13 +34,23 @@ func preload(context *cli.Context) error { return nil } +func runFunc(f *rFunc) { + userArgs := findUserArgs() + + config, err := loadConfigFromFd() + if err != nil { + log.Fatalf("unable to receive config from sync pipe: %s", err) + } + + f.Action(config, userArgs) +} + func main() { // we need to check our argv 0 for any registred functions to run instead of the // normal cli code path - - action, exists := argvs[os.Args[0]] + f, exists := argvs[os.Args[0]] if exists { - action() + runFunc(f) return } @@ -56,6 +74,7 @@ func main() { configCommand, pauseCommand, unpauseCommand, + execFuncCommand, } if err := app.Run(os.Args); err != nil { diff --git a/nsinit/nsenter.go b/nsinit/nsenter.go index 954de9923..92c73c74d 100644 --- a/nsinit/nsenter.go +++ b/nsinit/nsenter.go @@ -2,41 +2,50 @@ package main import ( "log" - "os" + "strconv" "github.com/docker/libcontainer" + "github.com/docker/libcontainer/devices" + "github.com/docker/libcontainer/mount/nodes" "github.com/docker/libcontainer/namespaces" _ "github.com/docker/libcontainer/namespaces/nsenter" - "github.com/docker/libcontainer/syncpipe" ) -func findUserArgs() []string { - i := 0 - for _, a := range os.Args { - i++ - - if a == "--" { - break - } - } - - return os.Args[i:] -} - -// this expects that we already have our namespaces setup by the C initializer -// we are expected to finalize the namespace and exec the user's application -func nsenter() { - syncPipe, err := syncpipe.NewSyncPipeFromFd(0, 3) - if err != nil { - log.Fatalf("unable to create sync pipe: %s", err) - } - - var config *libcontainer.Config - if err := syncPipe.ReadFromParent(&config); err != nil { - log.Fatalf("reading container config from parent: %s", err) - } - - if err := namespaces.FinalizeSetns(config, findUserArgs()); err != nil { +// nsenterExec exec's a process inside an existing container +func nsenterExec(config *libcontainer.Config, args []string) { + if err := namespaces.FinalizeSetns(config, args); err != nil { log.Fatalf("failed to nsenter: %s", err) } } + +// nsenterMknod runs mknod inside an existing container +// +// mknod +func nsenterMknod(config *libcontainer.Config, args []string) { + if len(args) != 4 { + log.Fatalf("expected mknod to have 4 arguments not %d", len(args)) + } + + t := rune(args[1][0]) + + major, err := strconv.Atoi(args[2]) + if err != nil { + log.Fatal(err) + } + + minor, err := strconv.Atoi(args[3]) + if err != nil { + log.Fatal(err) + } + + n := &devices.Device{ + Path: args[0], + Type: t, + MajorNumber: int64(major), + MinorNumber: int64(minor), + } + + if err := nodes.CreateDeviceNode("/", n); err != nil { + log.Fatal(err) + } +} diff --git a/nsinit/utils.go b/nsinit/utils.go index 44194d885..0012adccd 100644 --- a/nsinit/utils.go +++ b/nsinit/utils.go @@ -7,8 +7,15 @@ import ( "path/filepath" "github.com/docker/libcontainer" + "github.com/docker/libcontainer/syncpipe" ) +// rFunc is a function registration for calling after an execin +type rFunc struct { + Usage string + Action func(*libcontainer.Config, []string) +} + func loadContainer() (*libcontainer.Config, error) { f, err := os.Open(filepath.Join(dataPath, "container.json")) if err != nil { @@ -44,3 +51,32 @@ func loadContainerFromJson(rawData string) (*libcontainer.Config, error) { return container, nil } + +func findUserArgs() []string { + i := 0 + for _, a := range os.Args { + i++ + + if a == "--" { + break + } + } + + return os.Args[i:] +} + +// loadConfigFromFd loads a container's config from the sync pipe that is provided by +// fd 3 when running a process +func loadConfigFromFd() (*libcontainer.Config, error) { + syncPipe, err := syncpipe.NewSyncPipeFromFd(0, 3) + if err != nil { + return nil, err + } + + var config *libcontainer.Config + if err := syncPipe.ReadFromParent(&config); err != nil { + return nil, err + } + + return config, nil +} From 52ba97e3b1c1dcb5a09fbc974f995aa9c3639381 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 12 Aug 2014 11:52:33 -0700 Subject: [PATCH 4/6] Add ip func example for listing namespace interfaces Signed-off-by: Michael Crosby --- nsinit/main.go | 5 +++++ nsinit/nsenter.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/nsinit/main.go b/nsinit/main.go index bd944b82f..96f37be98 100644 --- a/nsinit/main.go +++ b/nsinit/main.go @@ -22,6 +22,11 @@ func init() { Usage: "mknod a device inside an existing container", Action: nsenterMknod, } + + argvs["nsenter-ip"] = &rFunc{ + Usage: "display the container's network interfaces", + Action: nsenterIp, + } } func preload(context *cli.Context) error { diff --git a/nsinit/nsenter.go b/nsinit/nsenter.go index 92c73c74d..8dc149f4f 100644 --- a/nsinit/nsenter.go +++ b/nsinit/nsenter.go @@ -1,8 +1,13 @@ package main import ( + "fmt" "log" + "net" + "os" "strconv" + "strings" + "text/tabwriter" "github.com/docker/libcontainer" "github.com/docker/libcontainer/devices" @@ -49,3 +54,31 @@ func nsenterMknod(config *libcontainer.Config, args []string) { log.Fatal(err) } } + +// nsenterIp displays the network interfaces inside a container's net namespace +func nsenterIp(config *libcontainer.Config, args []string) { + interfaces, err := net.Interfaces() + if err != nil { + log.Fatal(err) + } + + w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0) + fmt.Fprint(w, "NAME\tMTU\tMAC\tFLAG\tADDRS\n") + + for _, iface := range interfaces { + addrs, err := iface.Addrs() + if err != nil { + log.Fatal(err) + } + + o := []string{} + + for _, a := range addrs { + o = append(o, a.String()) + } + + fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\n", iface.Name, iface.MTU, iface.HardwareAddr, iface.Flags, strings.Join(o, ",")) + } + + w.Flush() +} From 7d1ba0698ffd1e3290fbe1084f183ccb4d657514 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 12 Aug 2014 12:03:53 -0700 Subject: [PATCH 5/6] Cleanup and rename loadContainer to loadConfig Signed-off-by: Michael Crosby --- nsinit/config.go | 2 +- nsinit/exec.go | 2 +- nsinit/execfunc.go | 2 +- nsinit/init.go | 2 +- nsinit/main.go | 21 --------------------- nsinit/pause.go | 2 +- nsinit/stats.go | 2 +- nsinit/utils.go | 34 +++++++++++++++++++++++----------- 8 files changed, 29 insertions(+), 38 deletions(-) diff --git a/nsinit/config.go b/nsinit/config.go index e1f28fcc8..74c7b3c09 100644 --- a/nsinit/config.go +++ b/nsinit/config.go @@ -15,7 +15,7 @@ var configCommand = cli.Command{ } func configAction(context *cli.Context) { - container, err := loadContainer() + container, err := loadConfig() if err != nil { log.Fatal(err) } diff --git a/nsinit/exec.go b/nsinit/exec.go index ae3e617b3..5c734abb0 100644 --- a/nsinit/exec.go +++ b/nsinit/exec.go @@ -25,7 +25,7 @@ var execCommand = cli.Command{ func execAction(context *cli.Context) { var exitCode int - container, err := loadContainer() + container, err := loadConfig() if err != nil { log.Fatal(err) } diff --git a/nsinit/execfunc.go b/nsinit/execfunc.go index e8fdf8e7a..7898d3ace 100644 --- a/nsinit/execfunc.go +++ b/nsinit/execfunc.go @@ -36,7 +36,7 @@ func execFuncAction(context *cli.Context) { var exitCode int - config, err := loadContainer() + config, err := loadConfig() if err != nil { log.Fatal(err) } diff --git a/nsinit/init.go b/nsinit/init.go index b37519648..c091ee109 100644 --- a/nsinit/init.go +++ b/nsinit/init.go @@ -26,7 +26,7 @@ var ( func initAction(context *cli.Context) { runtime.LockOSThread() - container, err := loadContainer() + container, err := loadConfig() if err != nil { log.Fatal(err) } diff --git a/nsinit/main.go b/nsinit/main.go index 96f37be98..18f550dc1 100644 --- a/nsinit/main.go +++ b/nsinit/main.go @@ -29,27 +29,6 @@ func init() { } } -func preload(context *cli.Context) error { - if logPath != "" { - if err := openLog(logPath); err != nil { - return err - } - } - - return nil -} - -func runFunc(f *rFunc) { - userArgs := findUserArgs() - - config, err := loadConfigFromFd() - if err != nil { - log.Fatalf("unable to receive config from sync pipe: %s", err) - } - - f.Action(config, userArgs) -} - func main() { // we need to check our argv 0 for any registred functions to run instead of the // normal cli code path diff --git a/nsinit/pause.go b/nsinit/pause.go index 6744539c6..ada24250c 100644 --- a/nsinit/pause.go +++ b/nsinit/pause.go @@ -34,7 +34,7 @@ func unpauseAction(context *cli.Context) { } func toggle(state cgroups.FreezerState) error { - container, err := loadContainer() + container, err := loadConfig() if err != nil { return err } diff --git a/nsinit/stats.go b/nsinit/stats.go index 331d27f2c..612b4a4ba 100644 --- a/nsinit/stats.go +++ b/nsinit/stats.go @@ -16,7 +16,7 @@ var statsCommand = cli.Command{ } func statsAction(context *cli.Context) { - container, err := loadContainer() + container, err := loadConfig() if err != nil { log.Fatal(err) } diff --git a/nsinit/utils.go b/nsinit/utils.go index 0012adccd..7f5155942 100644 --- a/nsinit/utils.go +++ b/nsinit/utils.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" + "github.com/codegangsta/cli" "github.com/docker/libcontainer" "github.com/docker/libcontainer/syncpipe" ) @@ -16,7 +17,7 @@ type rFunc struct { Action func(*libcontainer.Config, []string) } -func loadContainer() (*libcontainer.Config, error) { +func loadConfig() (*libcontainer.Config, error) { f, err := os.Open(filepath.Join(dataPath, "container.json")) if err != nil { return nil, err @@ -42,16 +43,6 @@ func openLog(name string) error { return nil } -func loadContainerFromJson(rawData string) (*libcontainer.Config, error) { - var container *libcontainer.Config - - if err := json.Unmarshal([]byte(rawData), &container); err != nil { - return nil, err - } - - return container, nil -} - func findUserArgs() []string { i := 0 for _, a := range os.Args { @@ -80,3 +71,24 @@ func loadConfigFromFd() (*libcontainer.Config, error) { return config, nil } + +func preload(context *cli.Context) error { + if logPath != "" { + if err := openLog(logPath); err != nil { + return err + } + } + + return nil +} + +func runFunc(f *rFunc) { + userArgs := findUserArgs() + + config, err := loadConfigFromFd() + if err != nil { + log.Fatalf("unable to receive config from sync pipe: %s", err) + } + + f.Action(config, userArgs) +} From bdafa085aecad7f284c749ffdd961427e8b45353 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 12 Aug 2014 17:33:20 -0700 Subject: [PATCH 6/6] Reuse exec cli function and strip nsenter- from funcs Signed-off-by: Michael Crosby --- nsinit/exec.go | 20 +++++++++++++++- nsinit/execfunc.go | 58 ---------------------------------------------- nsinit/main.go | 10 ++++---- 3 files changed, 24 insertions(+), 64 deletions(-) delete mode 100644 nsinit/execfunc.go diff --git a/nsinit/exec.go b/nsinit/exec.go index 5c734abb0..c46b19178 100644 --- a/nsinit/exec.go +++ b/nsinit/exec.go @@ -8,6 +8,7 @@ import ( "os/exec" "os/signal" "syscall" + "text/tabwriter" "github.com/codegangsta/cli" "github.com/docker/docker/pkg/term" @@ -20,9 +21,26 @@ var execCommand = cli.Command{ Name: "exec", Usage: "execute a new command inside a container", Action: execAction, + Flags: []cli.Flag{ + cli.BoolFlag{Name: "list", Usage: "list all registered exec functions"}, + cli.StringFlag{Name: "func", Value: "exec", Usage: "function name to exec inside a container"}, + }, } func execAction(context *cli.Context) { + if context.Bool("list") { + w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0) + fmt.Fprint(w, "NAME\tUSAGE\n") + + for k, f := range argvs { + fmt.Fprintf(w, "%s\t%s\n", k, f.Usage) + } + + w.Flush() + + return + } + var exitCode int container, err := loadConfig() @@ -36,7 +54,7 @@ func execAction(context *cli.Context) { } if state != nil { - exitCode, err = startInExistingContainer(container, state, "exec", context) + exitCode, err = startInExistingContainer(container, state, context.String("func"), context) } else { exitCode, err = startContainer(container, dataPath, []string(context.Args())) } diff --git a/nsinit/execfunc.go b/nsinit/execfunc.go deleted file mode 100644 index 7898d3ace..000000000 --- a/nsinit/execfunc.go +++ /dev/null @@ -1,58 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - "text/tabwriter" - - "github.com/codegangsta/cli" - "github.com/docker/libcontainer" -) - -var execFuncCommand = cli.Command{ - Name: "func", - Usage: "execute a registered function inside an existing container", - Action: execFuncAction, - Flags: []cli.Flag{ - cli.BoolFlag{Name: "list", Usage: "list all registered functions"}, - cli.StringFlag{Name: "func", Usage: "function name to exec inside a container"}, - }, -} - -func execFuncAction(context *cli.Context) { - if context.Bool("list") { - w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0) - fmt.Fprint(w, "NAME\tUSAGE\n") - - for k, f := range argvs { - fmt.Fprintf(w, "%s\t%s\n", k, f.Usage) - } - - w.Flush() - - return - } - - var exitCode int - - config, err := loadConfig() - if err != nil { - log.Fatal(err) - } - - // FIXME: remove tty from container config, this should be per process - config.Tty = false - - state, err := libcontainer.GetState(dataPath) - if err != nil { - log.Fatalf("unable to read state.json: %s", err) - } - - exitCode, err = startInExistingContainer(config, state, context.String("func"), context) - if err != nil { - log.Fatal(err) - } - - os.Exit(exitCode) -} diff --git a/nsinit/main.go b/nsinit/main.go index 18f550dc1..d65c0140e 100644 --- a/nsinit/main.go +++ b/nsinit/main.go @@ -3,6 +3,7 @@ package main import ( "log" "os" + "strings" "github.com/codegangsta/cli" ) @@ -13,17 +14,17 @@ var ( ) func init() { - argvs["nsenter-exec"] = &rFunc{ + argvs["exec"] = &rFunc{ Usage: "execute a process inside an existing container", Action: nsenterExec, } - argvs["nsenter-mknod"] = &rFunc{ + argvs["mknod"] = &rFunc{ Usage: "mknod a device inside an existing container", Action: nsenterMknod, } - argvs["nsenter-ip"] = &rFunc{ + argvs["ip"] = &rFunc{ Usage: "display the container's network interfaces", Action: nsenterIp, } @@ -32,7 +33,7 @@ func init() { func main() { // we need to check our argv 0 for any registred functions to run instead of the // normal cli code path - f, exists := argvs[os.Args[0]] + f, exists := argvs[strings.TrimPrefix(os.Args[0], "nsenter-")] if exists { runFunc(f) @@ -58,7 +59,6 @@ func main() { configCommand, pauseCommand, unpauseCommand, - execFuncCommand, } if err := app.Run(os.Args); err != nil {