From 3ce9c8be042c4af9200e01d087b7b9cee30b6b0a Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Thu, 5 Dec 2024 16:24:04 +1000 Subject: [PATCH] fix run command, support 1 replica and global mode --- cmd/uncloud/service/run.go | 76 +++++++++++++++++++++++----------- internal/cli/client/service.go | 11 ----- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/cmd/uncloud/service/run.go b/cmd/uncloud/service/run.go index 0beb8fac..95642abd 100644 --- a/cmd/uncloud/service/run.go +++ b/cmd/uncloud/service/run.go @@ -4,61 +4,89 @@ import ( "context" "fmt" "github.com/spf13/cobra" + "uncloud/internal/api" "uncloud/internal/cli" - "uncloud/internal/cli/client" - "uncloud/internal/service" ) +type runOptions struct { + command []string + image string + machine string + mode string + name string + publish []string + + cluster string +} + func NewRunCommand() *cobra.Command { - var ( - cluster string - opts client.ServiceOptions - ) + opts := runOptions{} cmd := &cobra.Command{ - Use: "run IMAGE", + Use: "run IMAGE [COMMAND...]", Short: "Run a service.", - Args: cobra.ExactArgs(1), + Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { uncli := cmd.Context().Value("cli").(*cli.CLI) - opts.Image = args[0] - return runRun(cmd.Context(), uncli, cluster, &opts) + + opts.image = args[0] + if len(args) > 1 { + opts.command = args[1:] + } + + return runRun(cmd.Context(), uncli, opts) }, } - cmd.Flags().StringVarP(&opts.Name, "name", "n", "", - "Assign a name to the service. A random name is generated if not specified.") - cmd.Flags().StringVarP( - &opts.Machine, "machine", "m", "", - "Name or ID of the machine to run the service on. (default is first available)", - ) - cmd.Flags().StringVar(&opts.Mode, "mode", service.ModeReplicated, + // TODO: implement placement constraints and translate --machine to a constraint. + //cmd.Flags().StringVarP( + // &opts.machine, "machine", "m", "", + // "Name or ID of the machine to run the service on. (default is first available)", + //) + cmd.Flags().StringVar(&opts.mode, "mode", api.ServiceModeReplicated, fmt.Sprintf("Replication mode of the service: either %q (a specified number of containers across "+ "the machines) or %q (one container on every machine).", - service.ModeReplicated, service.ModeGlobal)) - cmd.Flags().StringSliceVarP(&opts.Publish, "publish", "p", nil, + api.ServiceModeReplicated, api.ServiceModeGlobal)) + cmd.Flags().StringVarP(&opts.name, "name", "n", "", + "Assign a name to the service. A random name is generated if not specified.") + cmd.Flags().StringSliceVarP(&opts.publish, "publish", "p", nil, "Publish a service port to make it accessible outside the cluster. Can be specified multiple times. "+ "Format: [load_balancer_port:]container_port[/protocol]") + cmd.Flags().StringVarP( - &cluster, "cluster", "c", "", + &opts.cluster, "cluster", "c", "", "Name of the cluster to run the service in. (default is the current cluster)", ) return cmd } -func runRun(ctx context.Context, uncli *cli.CLI, clusterName string, opts *client.ServiceOptions) error { - c, err := uncli.ConnectCluster(ctx, clusterName) +func runRun(ctx context.Context, uncli *cli.CLI, opts runOptions) error { + switch opts.mode { + case "", api.ServiceModeReplicated, api.ServiceModeGlobal: + default: + return fmt.Errorf("invalid replication mode: %q", opts.mode) + } + + c, err := uncli.ConnectCluster(ctx, opts.cluster) if err != nil { return fmt.Errorf("connect to cluster: %w", err) } defer c.Close() - resp, err := c.RunService(ctx, opts) + spec := api.ServiceSpec{ + Container: api.ContainerSpec{ + Command: opts.command, + Image: opts.image, + }, + Mode: opts.mode, + Name: opts.name, + } + resp, err := c.RunService(ctx, spec) if err != nil { return fmt.Errorf("run service: %w", err) } - fmt.Printf("Service %q started on machine %q.\n", resp.Name, resp.MachineName) + fmt.Printf("Service %q started.\n", resp.Name) return nil } diff --git a/internal/cli/client/service.go b/internal/cli/client/service.go index af091bb2..9fe53666 100644 --- a/internal/cli/client/service.go +++ b/internal/cli/client/service.go @@ -21,17 +21,6 @@ import ( "uncloud/internal/secret" ) -// ServiceOptions contains all the options for creating a service. -// TODO: replace with ServiceSpec. -type ServiceOptions struct { - Image string - Name string - Machine string - // Mode is the replication mode of the service. - Mode string - Publish []string -} - type RunServiceResponse struct { ID string Name string