feat: refactor to ymsctl & yms-daemon
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -33,6 +34,17 @@ const serviceBackend = "backend"
|
||||
func main() {
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
if filepath.Base(os.Args[0]) == "ymsd" {
|
||||
if len(os.Args) != 1 {
|
||||
fmt.Fprintln(os.Stderr, "ymsd does not accept arguments")
|
||||
os.Exit(2)
|
||||
}
|
||||
if err := runServe(ctx); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "ymsd failed:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
os.Exit(run(ctx, os.Args[1:], os.Stdout, os.Stderr))
|
||||
}
|
||||
|
||||
@@ -42,16 +54,6 @@ func run(ctx context.Context, arguments []string, stdout io.Writer, stderr io.Wr
|
||||
return 2
|
||||
}
|
||||
switch arguments[0] {
|
||||
case "serve":
|
||||
if len(arguments) != 1 {
|
||||
fmt.Fprintln(stderr, "serve does not accept arguments")
|
||||
return 2
|
||||
}
|
||||
if err := runServe(ctx); err != nil {
|
||||
fmt.Fprintln(stderr, "yms-daemon serve failed:", err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case "update":
|
||||
request, err := parseUpdateArgs(arguments[1:], stderr)
|
||||
if err != nil {
|
||||
@@ -66,7 +68,7 @@ func run(ctx context.Context, arguments []string, stdout io.Writer, stderr io.Wr
|
||||
}
|
||||
var response daemonapi.Response
|
||||
if request.inputType == daemonapi.InputTypeContainerImage {
|
||||
response, err = daemonclient.UpdateContainerImage(ctx, runtimepaths.Socket, request.service, request.imageReference, progress)
|
||||
response, err = daemonclient.UpdateContainerImage(ctx, runtimepaths.Socket, request.service, request.imageReference, request.startLog, progress)
|
||||
} else {
|
||||
response, err = daemonclient.Update(ctx, runtimepaths.Socket, request.service, request.inputType, request.file, progress)
|
||||
}
|
||||
@@ -74,7 +76,7 @@ func run(ctx context.Context, arguments []string, stdout io.Writer, stderr io.Wr
|
||||
if response.TransactionID != "" {
|
||||
fmt.Fprintf(stderr, "transaction=%s state=%s error=%v\n", response.TransactionID, response.State, err)
|
||||
} else {
|
||||
fmt.Fprintln(stderr, "yms-daemon update failed:", err)
|
||||
fmt.Fprintln(stderr, "ymsctl update failed:", err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
@@ -82,6 +84,12 @@ func run(ctx context.Context, arguments []string, stdout io.Writer, stderr io.Wr
|
||||
fmt.Fprintf(stdout, "transaction=%s state=%s\n", response.TransactionID, response.State)
|
||||
}
|
||||
return 0
|
||||
case "list":
|
||||
if err := runList(ctx, arguments[1:], stdout, stderr); err != nil {
|
||||
fmt.Fprintln(stderr, "ymsctl list failed:", err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case "restart":
|
||||
request, err := parseRestartArgs(arguments[1:], stderr)
|
||||
if err != nil {
|
||||
@@ -99,7 +107,7 @@ func run(ctx context.Context, arguments []string, stdout io.Writer, stderr io.Wr
|
||||
if response.TransactionID != "" {
|
||||
fmt.Fprintf(stderr, "transaction=%s state=%s error=%v\n", response.TransactionID, response.State, err)
|
||||
} else {
|
||||
fmt.Fprintln(stderr, "yms-daemon restart failed:", err)
|
||||
fmt.Fprintln(stderr, "ymsctl restart failed:", err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
@@ -123,6 +131,7 @@ type updateArguments struct {
|
||||
file string
|
||||
imageReference string
|
||||
quite bool
|
||||
startLog bool
|
||||
}
|
||||
|
||||
type restartArguments struct {
|
||||
@@ -138,6 +147,7 @@ func parseUpdateArgs(arguments []string, output io.Writer) (updateArguments, err
|
||||
nativeJAR := flags.String("native-jar", "", "direct native backend JAR path")
|
||||
containerImage := flags.String("container-image", "", "development backend container image reference")
|
||||
quite := flags.Bool("quite", false, "suppress progress and successful result output")
|
||||
noStartLog := flags.Bool("no-start-log", false, "do not print container startup logs")
|
||||
if err := flags.Parse(arguments); err != nil {
|
||||
return updateArguments{}, err
|
||||
}
|
||||
@@ -157,7 +167,10 @@ func parseUpdateArgs(arguments []string, output io.Writer) (updateArguments, err
|
||||
return updateArguments{}, errors.New("exactly one of -f, --native-jar, and --container-image is required; update inputs are mutually exclusive")
|
||||
}
|
||||
if *containerImage != "" {
|
||||
return updateArguments{service: *service, inputType: daemonapi.InputTypeContainerImage, imageReference: *containerImage, quite: *quite}, nil
|
||||
return updateArguments{service: *service, inputType: daemonapi.InputTypeContainerImage, imageReference: *containerImage, quite: *quite, startLog: !*noStartLog}, nil
|
||||
}
|
||||
if *noStartLog {
|
||||
return updateArguments{}, errors.New("--no-start-log requires --container-image")
|
||||
}
|
||||
inputType := daemonapi.InputTypeRepackZIP
|
||||
inputFile := *file
|
||||
@@ -266,11 +279,11 @@ func runServe(ctx context.Context) (result error) {
|
||||
|
||||
func writeUsage(output io.Writer) {
|
||||
fmt.Fprintln(output, "usage:")
|
||||
fmt.Fprintln(output, " yms-daemon serve")
|
||||
fmt.Fprintln(output, " yms-daemon update --service backend -f <repack.zip> [--quite]")
|
||||
fmt.Fprintln(output, " yms-daemon update --service backend --native-jar <backend.jar> [--quite]")
|
||||
fmt.Fprintln(output, " yms-daemon update --service backend --container-image <image-ref> [--quite]")
|
||||
fmt.Fprintln(output, " yms-daemon restart --service backend [--quite]")
|
||||
fmt.Fprintln(output, " ymsctl update --service backend -f <repack.zip> [--quite]")
|
||||
fmt.Fprintln(output, " ymsctl update --service backend --native-jar <backend.jar> [--quite]")
|
||||
fmt.Fprintln(output, " ymsctl update --service backend --container-image <image-ref> [--no-start-log] [--quite]")
|
||||
fmt.Fprintln(output, " ymsctl restart --service backend [--quite]")
|
||||
fmt.Fprintln(output, " ymsctl list [--limit <n>] [--service backend] [--state <state>] [--json]")
|
||||
}
|
||||
|
||||
func writeUpdateProgress(output io.Writer, event daemonapi.Response) {
|
||||
@@ -280,3 +293,38 @@ func writeUpdateProgress(output io.Writer, event daemonapi.Response) {
|
||||
}
|
||||
fmt.Fprintf(output, "%-14s %s\n", state, event.Message)
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, arguments []string, stdout, stderr io.Writer) error {
|
||||
flags := flag.NewFlagSet("list", flag.ContinueOnError)
|
||||
flags.SetOutput(stderr)
|
||||
limit := flags.Int("limit", 20, "maximum number of operations to show")
|
||||
service := flags.String("service", "", "exact service filter")
|
||||
state := flags.String("state", "", "exact transaction state filter")
|
||||
jsonOutput := flags.Bool("json", false, "write stable JSON")
|
||||
if err := flags.Parse(arguments); err != nil {
|
||||
return err
|
||||
}
|
||||
if flags.NArg() != 0 {
|
||||
return errors.New("list does not accept positional arguments")
|
||||
}
|
||||
if *service != "" && *service != serviceBackend {
|
||||
return errors.New("--service currently accepts only backend")
|
||||
}
|
||||
store, err := transaction.OpenStore(ctx, runtimepaths.Database)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.Close()
|
||||
items, err := store.ListRecent(ctx, transaction.ListFilter{Limit: *limit, Service: *service, State: transaction.State(*state)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *jsonOutput {
|
||||
return json.NewEncoder(stdout).Encode(items)
|
||||
}
|
||||
fmt.Fprintln(stdout, "TIME\tTRANSACTION\tSERVICE\tSTATE\tSOURCE")
|
||||
for _, item := range items {
|
||||
fmt.Fprintf(stdout, "%s\t%s\t%s\t%s\t%s\n", item.CreatedAt.Local().Format("2006-01-02 15:04:05"), item.ID, item.Service, item.State, item.Source)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user