Add initial distributor CLI skeleton
This commit is contained in:
36
internal/cli/inspect.go
Normal file
36
internal/cli/inspect.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.maximumdirect.net/eric/distributor/internal/app"
|
||||
)
|
||||
|
||||
func inspectCommand(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
if hasHelp(args) {
|
||||
printInspectHelp(stdout)
|
||||
return exitOK
|
||||
}
|
||||
if len(args) > 1 {
|
||||
fmt.Fprintf(stderr, "%s: inspect accepts at most one path\n", app.Name)
|
||||
return exitUsage
|
||||
}
|
||||
var path string
|
||||
if len(args) == 1 {
|
||||
path = args[0]
|
||||
}
|
||||
if err := app.Inspect(ctx, app.InspectOptions{Path: path}); err != nil {
|
||||
return fail(stderr, err)
|
||||
}
|
||||
return exitOK
|
||||
}
|
||||
|
||||
func printInspectHelp(w io.Writer) {
|
||||
fmt.Fprint(w, `Usage:
|
||||
distributor inspect <path>
|
||||
|
||||
The inspect command is present but bundle inspection is not implemented yet.
|
||||
`)
|
||||
}
|
||||
84
internal/cli/root.go
Normal file
84
internal/cli/root.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/distributor/internal/app"
|
||||
)
|
||||
|
||||
const (
|
||||
exitOK = 0
|
||||
exitError = 1
|
||||
exitUsage = 2
|
||||
)
|
||||
|
||||
func Execute(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
if len(args) == 0 {
|
||||
printRootHelp(stdout)
|
||||
return exitOK
|
||||
}
|
||||
|
||||
switch args[0] {
|
||||
case "-h", "--help", "help":
|
||||
printRootHelp(stdout)
|
||||
return exitOK
|
||||
case "version":
|
||||
return versionCommand(ctx, args[1:], stdout, stderr)
|
||||
case "run":
|
||||
return runCommand(ctx, args[1:], stdout, stderr)
|
||||
case "validate":
|
||||
return validateCommand(ctx, args[1:], stdout, stderr)
|
||||
case "inspect":
|
||||
return inspectCommand(ctx, args[1:], stdout, stderr)
|
||||
default:
|
||||
fmt.Fprintf(stderr, "%s: unknown command %q\n\n", app.Name, args[0])
|
||||
printRootHelp(stderr)
|
||||
return exitUsage
|
||||
}
|
||||
}
|
||||
|
||||
func printRootHelp(w io.Writer) {
|
||||
fmt.Fprintf(w, `%s validates and publishes manifested report bundles.
|
||||
|
||||
Usage:
|
||||
%s <command> [options]
|
||||
|
||||
Commands:
|
||||
version Print version information
|
||||
run Run configured distribution pipelines
|
||||
validate Validate a source bundle or bundle tree
|
||||
inspect Inspect bundles or distributor state
|
||||
|
||||
Use "%s <command> --help" for command-specific help.
|
||||
`, app.Name, app.Name, app.Name)
|
||||
}
|
||||
|
||||
func hasHelp(args []string) bool {
|
||||
for _, arg := range args {
|
||||
if arg == "-h" || arg == "--help" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func fail(stderr io.Writer, err error) int {
|
||||
if errors.Is(err, app.ErrNotImplemented) {
|
||||
fmt.Fprintf(stderr, "%s: %s\n", app.Name, err)
|
||||
return exitError
|
||||
}
|
||||
fmt.Fprintf(stderr, "%s: %s\n", app.Name, err)
|
||||
return exitError
|
||||
}
|
||||
|
||||
func rejectExtraArgs(stderr io.Writer, command string, args []string) bool {
|
||||
if len(args) == 0 {
|
||||
return false
|
||||
}
|
||||
fmt.Fprintf(stderr, "%s: %s does not accept arguments: %s\n", app.Name, command, strings.Join(args, " "))
|
||||
return true
|
||||
}
|
||||
75
internal/cli/root_test.go
Normal file
75
internal/cli/root_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExecuteRootHelp(t *testing.T) {
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := Execute(context.Background(), []string{"--help"}, &stdout, &stderr)
|
||||
|
||||
if code != exitOK {
|
||||
t.Fatalf("exit code = %d, want %d", code, exitOK)
|
||||
}
|
||||
if !strings.Contains(stdout.String(), "Usage:") {
|
||||
t.Fatalf("stdout = %q, want help text", stdout.String())
|
||||
}
|
||||
if stderr.Len() != 0 {
|
||||
t.Fatalf("stderr = %q, want empty", stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteVersion(t *testing.T) {
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := Execute(context.Background(), []string{"version"}, &stdout, &stderr)
|
||||
|
||||
if code != exitOK {
|
||||
t.Fatalf("exit code = %d, want %d", code, exitOK)
|
||||
}
|
||||
if got, want := stdout.String(), "distributor dev\n"; got != want {
|
||||
t.Fatalf("stdout = %q, want %q", got, want)
|
||||
}
|
||||
if stderr.Len() != 0 {
|
||||
t.Fatalf("stderr = %q, want empty", stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceholderCommandsFailClearly(t *testing.T) {
|
||||
tests := []string{"run", "validate", "inspect"}
|
||||
|
||||
for _, command := range tests {
|
||||
t.Run(command, func(t *testing.T) {
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := Execute(context.Background(), []string{command}, &stdout, &stderr)
|
||||
|
||||
if code != exitError {
|
||||
t.Fatalf("exit code = %d, want %d", code, exitError)
|
||||
}
|
||||
if stdout.Len() != 0 {
|
||||
t.Fatalf("stdout = %q, want empty", stdout.String())
|
||||
}
|
||||
if !strings.Contains(stderr.String(), "not implemented") {
|
||||
t.Fatalf("stderr = %q, want not implemented error", stderr.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownCommandIsUsageError(t *testing.T) {
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := Execute(context.Background(), []string{"nope"}, &stdout, &stderr)
|
||||
|
||||
if code != exitUsage {
|
||||
t.Fatalf("exit code = %d, want %d", code, exitUsage)
|
||||
}
|
||||
if !strings.Contains(stderr.String(), "unknown command") {
|
||||
t.Fatalf("stderr = %q, want unknown command error", stderr.String())
|
||||
}
|
||||
}
|
||||
32
internal/cli/run.go
Normal file
32
internal/cli/run.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.maximumdirect.net/eric/distributor/internal/app"
|
||||
)
|
||||
|
||||
func runCommand(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
if hasHelp(args) {
|
||||
printRunHelp(stdout)
|
||||
return exitOK
|
||||
}
|
||||
if len(args) > 0 {
|
||||
fmt.Fprintf(stderr, "%s: run does not accept options yet: %v\n", app.Name, args)
|
||||
return exitUsage
|
||||
}
|
||||
if err := app.Run(ctx, app.RunOptions{}); err != nil {
|
||||
return fail(stderr, err)
|
||||
}
|
||||
return exitOK
|
||||
}
|
||||
|
||||
func printRunHelp(w io.Writer) {
|
||||
fmt.Fprint(w, `Usage:
|
||||
distributor run
|
||||
|
||||
The run command is present but distribution behavior is not implemented yet.
|
||||
`)
|
||||
}
|
||||
36
internal/cli/validate.go
Normal file
36
internal/cli/validate.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.maximumdirect.net/eric/distributor/internal/app"
|
||||
)
|
||||
|
||||
func validateCommand(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
if hasHelp(args) {
|
||||
printValidateHelp(stdout)
|
||||
return exitOK
|
||||
}
|
||||
if len(args) > 1 {
|
||||
fmt.Fprintf(stderr, "%s: validate accepts at most one path\n", app.Name)
|
||||
return exitUsage
|
||||
}
|
||||
var path string
|
||||
if len(args) == 1 {
|
||||
path = args[0]
|
||||
}
|
||||
if err := app.Validate(ctx, app.ValidateOptions{Path: path}); err != nil {
|
||||
return fail(stderr, err)
|
||||
}
|
||||
return exitOK
|
||||
}
|
||||
|
||||
func printValidateHelp(w io.Writer) {
|
||||
fmt.Fprint(w, `Usage:
|
||||
distributor validate <path>
|
||||
|
||||
The validate command is present but bundle validation is not implemented yet.
|
||||
`)
|
||||
}
|
||||
29
internal/cli/version.go
Normal file
29
internal/cli/version.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.maximumdirect.net/eric/distributor/internal/app"
|
||||
)
|
||||
|
||||
func versionCommand(_ context.Context, args []string, stdout, stderr io.Writer) int {
|
||||
if hasHelp(args) {
|
||||
printVersionHelp(stdout)
|
||||
return exitOK
|
||||
}
|
||||
if rejectExtraArgs(stderr, "version", args) {
|
||||
return exitUsage
|
||||
}
|
||||
fmt.Fprintln(stdout, app.VersionString())
|
||||
return exitOK
|
||||
}
|
||||
|
||||
func printVersionHelp(w io.Writer) {
|
||||
fmt.Fprint(w, `Usage:
|
||||
distributor version
|
||||
|
||||
Print version information.
|
||||
`)
|
||||
}
|
||||
Reference in New Issue
Block a user