Implement a robust Context.Run().
This helps when composing large applications from separate command structs.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Large-scale composed CLI
|
||||
|
||||
This directory illustrates how a large-scale CLI app could be structured.
|
||||
@@ -0,0 +1,339 @@
|
||||
// nolint
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type AttachCmd struct {
|
||||
DetachKeys string `help:"Override the key sequence for detaching a container"`
|
||||
NoStdin bool `help:"Do not attach STDIN"`
|
||||
SigProxy bool `help:"Proxy all received signals to the process" default:"true"`
|
||||
|
||||
Container string `arg required help:"Container ID to attach to."`
|
||||
}
|
||||
|
||||
func (a *AttachCmd) Run(globals *Globals) error {
|
||||
fmt.Printf("Config: %s\n", globals.Config)
|
||||
fmt.Printf("Attaching to: %v\n", a.Container)
|
||||
fmt.Printf("SigProxy: %v\n", a.SigProxy)
|
||||
return nil
|
||||
}
|
||||
|
||||
type BuildCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *BuildCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type CommitCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *CommitCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type CpCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *CpCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *CreateCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeployCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *DeployCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DiffCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *DiffCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type EventsCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *EventsCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExecCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *ExecCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExportCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *ExportCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type HistoryCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *HistoryCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImagesCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *ImagesCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImportCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *ImportCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type InfoCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *InfoCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type InspectCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *InspectCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type KillCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *KillCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type LoadCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *LoadCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type LoginCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *LoginCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogoutCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *LogoutCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogsCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *LogsCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PauseCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *PauseCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PortCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *PortCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PsCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *PsCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PullCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *PullCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PushCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *PushCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type RenameCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *RenameCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type RestartCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *RestartCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type RmCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *RmCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type RmiCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *RmiCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type RunCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *RunCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type SaveCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *SaveCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type SearchCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *SearchCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type StartCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *StartCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type StatsCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *StatsCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type StopCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *StopCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type TagCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *TagCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type TopCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *TopCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type UnpauseCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *UnpauseCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *UpdateCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type VersionCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *VersionCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type WaitCmd struct {
|
||||
Arg string `arg required`
|
||||
}
|
||||
|
||||
func (cmd *WaitCmd) Run(globals *Globals) error {
|
||||
return nil
|
||||
}
|
||||
+64
-157
@@ -2,177 +2,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
)
|
||||
|
||||
type AttachCmd struct {
|
||||
DetachKeys string `help:"Override the key sequence for detaching a container"`
|
||||
NoStdin bool `help:"Do not attach STDIN"`
|
||||
SigProxy bool `help:"Proxy all received signals to the process" default:"true"`
|
||||
|
||||
Container string `arg required help:"Container ID to attach to."`
|
||||
type Globals struct {
|
||||
Config string `help:"Location of client config files" default:"~/.docker" type:"path"`
|
||||
Debug bool `short:"D" help:"Enable debug mode"`
|
||||
Host []string `short:"H" help:"Daemon socket(s) to connect to"`
|
||||
LogLevel string `short:"l" help:"Set the logging level (debug|info|warn|error|fatal)" default:"info"`
|
||||
TLS bool `help:"Use TLS; implied by --tls-verify"`
|
||||
TLSCACert string `name:"tls-ca-cert" help:"Trust certs signed only by this CA" default:"~/.docker/ca.pem" type:"path"`
|
||||
TLSCert string `help:"Path to TLS certificate file" default:"~/.docker/cert.pem" type:"path"`
|
||||
TLSKey string `help:"Path to TLS key file" default:"~/.docker/key.pem" type:"path"`
|
||||
TLSVerify bool `help:"Use TLS and verify the remote"`
|
||||
}
|
||||
|
||||
func (a *AttachCmd) Run() error {
|
||||
fmt.Printf("Attaching to: %v\n", a.Container)
|
||||
fmt.Printf("SigProxy: %v\n", a.SigProxy)
|
||||
return nil
|
||||
}
|
||||
type CLI struct {
|
||||
Globals
|
||||
VersionFlag bool `name:"version" help:"Print version information and quit"`
|
||||
|
||||
var cli struct {
|
||||
Config string `help:"Location of client config files" default:"~/.docker" type:"path"`
|
||||
Debug bool `short:"D" help:"Enable debug mode"`
|
||||
Host []string `short:"H" help:"Daemon socket(s) to connect to"`
|
||||
LogLevel string `short:"l" help:"Set the logging level (debug|info|warn|error|fatal)" default:"info"`
|
||||
TLS bool `help:"Use TLS; implied by --tlsverify"`
|
||||
TLSCACert string `name:"tls-ca-cert" help:"Trust certs signed only by this CA" default:"~/.docker/ca.pem" type:"path"`
|
||||
TLSCert string `name:"tls-cert" help:"Path to TLS certificate file" default:"~/.docker/cert.pem" type:"path"`
|
||||
TLSKey string `help:"Path to TLS key file" default:"~/.docker/key.pem" type:"path"`
|
||||
TLSVerify bool `help:"Use TLS and verify the remote"`
|
||||
PrintVersion bool `name:"version" help:"Print version information and quit"`
|
||||
|
||||
Attach AttachCmd `cmd help:"Attach local standard input, output, and error streams to a running container"`
|
||||
|
||||
Build struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Build an image from a Dockerfile"`
|
||||
Commit struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Create a new image from a container's changes"`
|
||||
Cp struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Copy files/folders between a container and the local filesystem"`
|
||||
Create struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Create a new container"`
|
||||
Deploy struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Deploy a new stack or update an existing stack"`
|
||||
Diff struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Inspect changes to files or directories on a container's filesystem"`
|
||||
Events struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Get real time events from the server"`
|
||||
Exec struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Run a command in a running container"`
|
||||
Export struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Export a container's filesystem as a tar archive"`
|
||||
History struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Show the history of an image"`
|
||||
Images struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"List images"`
|
||||
Import struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Import the contents from a tarball to create a filesystem image"`
|
||||
Info struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Display system-wide information"`
|
||||
Inspect struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Return low-level information on Docker objects"`
|
||||
Kill struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Kill one or more running containers"`
|
||||
Load struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Load an image from a tar archive or STDIN"`
|
||||
Login struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Log in to a Docker registry"`
|
||||
Logout struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Log out from a Docker registry"`
|
||||
Logs struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Fetch the logs of a container"`
|
||||
Pause struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Pause all processes within one or more containers"`
|
||||
Port struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"List port mappings or a specific mapping for the container"`
|
||||
Ps struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"List containers"`
|
||||
Pull struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Pull an image or a repository from a registry"`
|
||||
Push struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Push an image or a repository to a registry"`
|
||||
Rename struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Rename a container"`
|
||||
Restart struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Restart one or more containers"`
|
||||
Rm struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Remove one or more containers"`
|
||||
Rmi struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Remove one or more images"`
|
||||
Run struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Run a command in a new container"`
|
||||
Save struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Save one or more images to a tar archive (streamed to STDOUT by default)"`
|
||||
Search struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Search the Docker Hub for images"`
|
||||
Start struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Start one or more stopped containers"`
|
||||
Stats struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Display a live stream of container(s) resource usage statistics"`
|
||||
Stop struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Stop one or more running containers"`
|
||||
Tag struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE"`
|
||||
Top struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Display the running processes of a container"`
|
||||
Unpause struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Unpause all processes within one or more containers"`
|
||||
Update struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Update configuration of one or more containers"`
|
||||
Version struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Show the Docker version information"`
|
||||
Wait struct {
|
||||
Arg string `arg required`
|
||||
} `cmd help:"Block until one or more containers stop, then print their exit codes"`
|
||||
Attach AttachCmd `cmd help:"Attach local standard input, output, and error streams to a running container"`
|
||||
Build BuildCmd `cmd help:"Build an image from a Dockerfile"`
|
||||
Commit CommitCmd `cmd help:"Create a new image from a container's changes"`
|
||||
Cp CpCmd `cmd help:"Copy files/folders between a container and the local filesystem"`
|
||||
Create CreateCmd `cmd help:"Create a new container"`
|
||||
Deploy DeployCmd `cmd help:"Deploy a new stack or update an existing stack"`
|
||||
Diff DiffCmd `cmd help:"Inspect changes to files or directories on a container's filesystem"`
|
||||
Events EventsCmd `cmd help:"Get real time events from the server"`
|
||||
Exec ExecCmd `cmd help:"Run a command in a running container"`
|
||||
Export ExportCmd `cmd help:"Export a container's filesystem as a tar archive"`
|
||||
History HistoryCmd `cmd help:"Show the history of an image"`
|
||||
Images ImagesCmd `cmd help:"List images"`
|
||||
Import ImportCmd `cmd help:"Import the contents from a tarball to create a filesystem image"`
|
||||
Info InfoCmd `cmd help:"Display system-wide information"`
|
||||
Inspect InspectCmd `cmd help:"Return low-level information on Docker objects"`
|
||||
Kill KillCmd `cmd help:"Kill one or more running containers"`
|
||||
Load LoadCmd `cmd help:"Load an image from a tar archive or STDIN"`
|
||||
Login LoginCmd `cmd help:"Log in to a Docker registry"`
|
||||
Logout LogoutCmd `cmd help:"Log out from a Docker registry"`
|
||||
Logs LogsCmd `cmd help:"Fetch the logs of a container"`
|
||||
Pause PauseCmd `cmd help:"Pause all processes within one or more containers"`
|
||||
Port PortCmd `cmd help:"List port mappings or a specific mapping for the container"`
|
||||
Ps PsCmd `cmd help:"List containers"`
|
||||
Pull PullCmd `cmd help:"Pull an image or a repository from a registry"`
|
||||
Push PushCmd `cmd help:"Push an image or a repository to a registry"`
|
||||
Rename RenameCmd `cmd help:"Rename a container"`
|
||||
Restart RestartCmd `cmd help:"Restart one or more containers"`
|
||||
Rm RmCmd `cmd help:"Remove one or more containers"`
|
||||
Rmi RmiCmd `cmd help:"Remove one or more images"`
|
||||
Run RunCmd `cmd help:"Run a command in a new container"`
|
||||
Save SaveCmd `cmd help:"Save one or more images to a tar archive (streamed to STDOUT by default)"`
|
||||
Search SearchCmd `cmd help:"Search the Docker Hub for images"`
|
||||
Start StartCmd `cmd help:"Start one or more stopped containers"`
|
||||
Stats StatsCmd `cmd help:"Display a live stream of container(s) resource usage statistics"`
|
||||
Stop StopCmd `cmd help:"Stop one or more running containers"`
|
||||
Tag TagCmd `cmd help:"Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE"`
|
||||
Top TopCmd `cmd help:"Display the running processes of a container"`
|
||||
Unpause UnpauseCmd `cmd help:"Unpause all processes within one or more containers"`
|
||||
Update UpdateCmd `cmd help:"Update configuration of one or more containers"`
|
||||
Version VersionCmd `cmd help:"Show the Docker version information"`
|
||||
Wait WaitCmd `cmd help:"Block until one or more containers stop, then print their exit codes"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd := kong.Parse(&cli,
|
||||
cli := CLI{}
|
||||
parser := kong.Must(&cli,
|
||||
kong.Name("docker"),
|
||||
kong.Description("A self-sufficient runtime for containers"),
|
||||
kong.UsageOnError(),
|
||||
kong.HelpOptions(kong.HelpPrinterOptions{
|
||||
Compact: true,
|
||||
}),
|
||||
//
|
||||
kong.Hook(&cli.VersionFlag, func(ctx *kong.Context, path *kong.Path) error {
|
||||
ctx.App.Printf("1.0.0").Exit(0)
|
||||
return nil
|
||||
}))
|
||||
var err error
|
||||
switch cmd {
|
||||
case "attach <container>":
|
||||
fmt.Println(cli.Config)
|
||||
err = cli.Attach.Run()
|
||||
|
||||
default:
|
||||
panic("unsupported command " + cmd)
|
||||
}
|
||||
kong.FatalIfErrorf(err)
|
||||
err := parser.Run(os.Args[1:], "ofo")
|
||||
parser.FatalIfErrorf(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user