feat: add --cpu, --memory, --privileged, --user options for 'service run'

This commit is contained in:
Pavel Sviderski
2025-04-24 20:30:48 +10:00
parent 72bf34632f
commit 6c2759f315
2 changed files with 28 additions and 4 deletions
+27 -4
View File
@@ -6,6 +6,7 @@ import (
"os" "os"
"strings" "strings"
dockeropts "github.com/docker/cli/opts"
"github.com/docker/compose/v2/pkg/progress" "github.com/docker/compose/v2/pkg/progress"
"github.com/docker/docker/daemon/names" "github.com/docker/docker/daemon/names"
"github.com/psviderski/uncloud/internal/cli" "github.com/psviderski/uncloud/internal/cli"
@@ -17,16 +18,20 @@ import (
type runOptions struct { type runOptions struct {
command []string command []string
cpu dockeropts.NanoCPUs
entrypoint string entrypoint string
entrypointChanged bool entrypointChanged bool
env []string env []string
image string image string
machines []string machines []string
memory dockeropts.MemBytes
mode string mode string
name string name string
privileged bool
publish []string publish []string
pull string pull string
replicas uint replicas uint
user string
volumes []string volumes []string
cluster string cluster string
@@ -52,6 +57,9 @@ func NewRunCommand() *cobra.Command {
}, },
} }
cmd.Flags().VarP(&opts.cpu, "cpu", "",
"Maximum number of CPU cores a service container can use. Fractional values are allowed: "+
"0.5 for half a core or 2.25 for two and a quarter cores.")
cmd.Flags().StringVar(&opts.entrypoint, "entrypoint", "", cmd.Flags().StringVar(&opts.entrypoint, "entrypoint", "",
"Overwrite the default ENTRYPOINT of the image. Pass an empty string \"\" to reset it.") "Overwrite the default ENTRYPOINT of the image. Pass an empty string \"\" to reset it.")
cmd.Flags().StringSliceVarP(&opts.env, "env", "e", nil, cmd.Flags().StringSliceVarP(&opts.env, "env", "e", nil,
@@ -64,8 +72,14 @@ func NewRunCommand() *cobra.Command {
cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil, cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil,
"Placement constraint by machine names, limiting which machines the service can run on. Can be specified "+ "Placement constraint by machine names, limiting which machines the service can run on. Can be specified "+
"multiple times or as a comma-separated list of machine names. (default is any suitable machine)") "multiple times or as a comma-separated list of machine names. (default is any suitable machine)")
cmd.Flags().VarP(&opts.memory, "memory", "",
"Maximum amount of memory a service container can use. Value is a positive integer with optional unit suffix "+
"(b, k, m, g). Default unit is bytes if no suffix specified.\n"+
"Examples: 1073741824, 1024m, 1g (all equal 1 gibibyte)")
cmd.Flags().StringVarP(&opts.name, "name", "n", "", cmd.Flags().StringVarP(&opts.name, "name", "n", "",
"Assign a name to the service. A random name is generated if not specified.") "Assign a name to the service. A random name is generated if not specified.")
cmd.Flags().BoolVar(&opts.privileged, "privileged", false,
"Give extended privileges to service containers. This is a security risk and should be used with caution.")
cmd.Flags().StringSliceVarP(&opts.publish, "publish", "p", nil, cmd.Flags().StringSliceVarP(&opts.publish, "publish", "p", nil,
"Publish a service port to make it accessible outside the cluster. Can be specified multiple times.\n"+ "Publish a service port to make it accessible outside the cluster. Can be specified multiple times.\n"+
"Format: [hostname:][load_balancer_port:]container_port[/protocol] or [host_ip:]:host_port:container_port[/protocol]@host\n"+ "Format: [hostname:][load_balancer_port:]container_port[/protocol] or [host_ip:]:host_port:container_port[/protocol]@host\n"+
@@ -81,6 +95,9 @@ func NewRunCommand() *cobra.Command {
api.PullPolicyAlways, api.PullPolicyMissing, api.PullPolicyNever)) api.PullPolicyAlways, api.PullPolicyMissing, api.PullPolicyNever))
cmd.Flags().UintVar(&opts.replicas, "replicas", 1, cmd.Flags().UintVar(&opts.replicas, "replicas", 1,
"Number of containers to run for the service. Only valid for a replicated service.") "Number of containers to run for the service. Only valid for a replicated service.")
cmd.Flags().StringVarP(&opts.user, "user", "u", "",
"User name or UID and optionally group name or GID used for running the command inside service containers.\n"+
"Format: USER[:GROUP] or UID[:GID]. If not specified, the user is set to the default user of the image.")
cmd.Flags().StringSliceVarP(&opts.volumes, "volume", "v", nil, cmd.Flags().StringSliceVarP(&opts.volumes, "volume", "v", nil,
"Mount a data volume or host path into service containers. Service containers will be scheduled on the machine(s) where\n"+ "Mount a data volume or host path into service containers. Service containers will be scheduled on the machine(s) where\n"+
"the volume is located. Can be specified multiple times.\n"+ "the volume is located. Can be specified multiple times.\n"+
@@ -180,10 +197,16 @@ func prepareServiceSpec(opts runOptions) (api.ServiceSpec, error) {
spec = api.ServiceSpec{ spec = api.ServiceSpec{
Container: api.ContainerSpec{ Container: api.ContainerSpec{
Command: opts.command, Command: opts.command,
Env: env, Env: env,
Image: opts.image, Image: opts.image,
PullPolicy: opts.pull, Privileged: opts.privileged,
PullPolicy: opts.pull,
Resources: api.ContainerResources{
CPU: opts.cpu.Value(),
Memory: opts.memory.Value(),
},
User: opts.user,
VolumeMounts: mounts, VolumeMounts: mounts,
}, },
Mode: opts.mode, Mode: opts.mode,
+1
View File
@@ -67,6 +67,7 @@ func assertContainerMatchesSpec(t *testing.T, ctr api.ServiceContainer, spec api
assert.Equal(t, spec.Container.LogDriver.Name, ctr.HostConfig.LogConfig.Type) assert.Equal(t, spec.Container.LogDriver.Name, ctr.HostConfig.LogConfig.Type)
assert.Equal(t, spec.Container.LogDriver.Options, ctr.HostConfig.LogConfig.Config) assert.Equal(t, spec.Container.LogDriver.Options, ctr.HostConfig.LogConfig.Config)
} }
assert.Equal(t, spec.Container.Privileged, ctr.HostConfig.Privileged)
// Compute resources. // Compute resources.
assert.Equal(t, spec.Container.Resources.CPU, ctr.HostConfig.Resources.NanoCPUs) assert.Equal(t, spec.Container.Resources.CPU, ctr.HostConfig.Resources.NanoCPUs)
assert.Equal(t, spec.Container.Resources.Memory, ctr.HostConfig.Resources.Memory) assert.Equal(t, spec.Container.Resources.Memory, ctr.HostConfig.Resources.Memory)