feat: implement --pull policy for run command: always, missing, never

This commit is contained in:
Pavel Sviderski
2025-03-27 15:06:32 +10:00
parent 7c7530f977
commit 641b11a92d
3 changed files with 34 additions and 7 deletions
+17 -6
View File
@@ -21,6 +21,7 @@ type runOptions struct {
mode string
name string
publish []string
pull string
replicas uint
volumes []string
@@ -50,8 +51,8 @@ func NewRunCommand() *cobra.Command {
cmd.Flags().StringVar(&opts.entrypoint, "entrypoint", "",
"Overwrite the default ENTRYPOINT of the image. Pass an empty string \"\" to reset it.")
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).",
fmt.Sprintf("Replication mode of the service: either '%s' (a specified number of containers across "+
"the machines) or '%s' (one container on every machine).",
api.ServiceModeReplicated, api.ServiceModeGlobal))
cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil,
"Placement constraint by machine name, limiting which machines the service can run on. Can be specified "+
@@ -68,6 +69,9 @@ func NewRunCommand() *cobra.Command {
" -p app.example.com:8080/https Publish port 8080 as HTTPS via load balancer with custom hostname\n"+
" -p 9000:8080 Publish port 8080 as TCP port 9000 via load balancer\n"+
" -p 53:5353/udp@host Bind UDP port 5353 to host port 53")
cmd.Flags().StringVar(&opts.pull, "pull", api.PullPolicyMissing,
fmt.Sprintf("Pull image from the registry before running service containers ('%s', '%s', '%s').",
api.PullPolicyAlways, api.PullPolicyMissing, api.PullPolicyNever))
cmd.Flags().UintVar(&opts.replicas, "replicas", 1,
"Number of containers to run for the service. Only valid for a replicated service.")
cmd.Flags().StringSliceVarP(&opts.volumes, "volume", "v", nil,
@@ -86,7 +90,13 @@ func run(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)
return fmt.Errorf("invalid replication mode: '%s'", opts.mode)
}
switch opts.pull {
case api.PullPolicyAlways, api.PullPolicyMissing, api.PullPolicyNever:
default:
return fmt.Errorf("invalid pull policy: '%s'", opts.pull)
}
var machineFilter deploy.MachineFilter
@@ -124,9 +134,10 @@ func run(ctx context.Context, uncli *cli.CLI, opts runOptions) error {
spec := api.ServiceSpec{
Container: api.ContainerSpec{
Command: opts.command,
Image: opts.image,
Volumes: opts.volumes,
Command: opts.command,
Image: opts.image,
PullPolicy: opts.pull,
Volumes: opts.volumes,
},
Mode: opts.mode,
Name: opts.name,
+16 -1
View File
@@ -110,10 +110,25 @@ func (cli *Client) CreateContainer(
pw := progress.ContextWriter(ctx)
eventID := fmt.Sprintf("Container %s on %s", containerName, machine.Machine.Name)
pw.Event(progress.CreatingEvent(eventID))
if spec.Container.PullPolicy == api.PullPolicyAlways {
if err = cli.pullImageWithProgress(ctx, config.Image, machine.Machine.Name, eventID); err != nil {
return resp, err
}
}
resp, err = cli.Docker.CreateContainer(ctx, config, hostConfig, netConfig, nil, containerName)
if err != nil {
switch spec.Container.PullPolicy {
case api.PullPolicyAlways, api.PullPolicyNever:
return resp, err
case api.PullPolicyMissing:
default:
return resp, fmt.Errorf("unsupported pull policy: '%s'", spec.Container.PullPolicy)
}
// Not found error is expected if the image is missing.
if !dockerclient.IsErrNotFound(err) {
return resp, err
}
+1
View File
@@ -48,6 +48,7 @@ func (s *RollingStrategy) Plan(
// planReplicated creates a plan for a replicated service deployment.
// For replicated services, we want to maintain a specific number of containers (replicas) across the available machines
// in the cluster.
// TODO: schedule containers only on machines that contain the image if pull policy is set to 'never'.
func (s *RollingStrategy) planReplicated(
ctx context.Context, cli api.MachineClient, svc *api.Service, spec api.ServiceSpec,
) (Plan, error) {