@@ -85,8 +85,7 @@ func Service(
8585 return swarm.ServiceSpec {}, err
8686 }
8787
88- restartPolicy , err := convertRestartPolicy (
89- service .Restart , service .Deploy .RestartPolicy )
88+ restartPolicy , err := convertRestartPolicy (service .Restart , service .Deploy .RestartPolicy )
9089 if err != nil {
9190 return swarm.ServiceSpec {}, err
9291 }
@@ -472,37 +471,58 @@ func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container
472471 }, nil
473472}
474473
475- func convertRestartPolicy (restart string , source * composetypes.RestartPolicy ) (* swarm.RestartPolicy , error ) {
476- // TODO: log if restart is being ignored
477- if source == nil {
478- policy , err := opts .ParseRestartPolicy (restart )
479- if err != nil {
480- return nil , err
481- }
482- switch {
483- case policy .IsNone ():
484- return nil , nil
485- case policy .IsAlways (), policy .IsUnlessStopped ():
486- return & swarm.RestartPolicy {
487- Condition : swarm .RestartPolicyConditionAny ,
488- }, nil
489- case policy .IsOnFailure ():
490- attempts := uint64 (policy .MaximumRetryCount )
491- return & swarm.RestartPolicy {
492- Condition : swarm .RestartPolicyConditionOnFailure ,
493- MaxAttempts : & attempts ,
494- }, nil
495- default :
496- return nil , fmt .Errorf ("unknown restart policy: %s" , restart )
474+ // convertRestartPolicy converts the service's restart-policy. It prefers
475+ // service.deploy.restart_policy, but falls back to parsing the legacy
476+ // service.restart if service.deploy.restart_policy is not set.
477+ func convertRestartPolicy (restart string , restartPolicy * composetypes.RestartPolicy ) (* swarm.RestartPolicy , error ) {
478+ // Use service.deploy.restart_policy, if set.
479+ if restartPolicy != nil {
480+ // TODO: log or error if both "service.restart" and "service.deploy.restartpolicy" are set.
481+ return & swarm.RestartPolicy {
482+ Condition : swarm .RestartPolicyCondition (restartPolicy .Condition ),
483+ Delay : composetypes .ConvertDurationPtr (restartPolicy .Delay ),
484+ MaxAttempts : restartPolicy .MaxAttempts ,
485+ Window : composetypes .ConvertDurationPtr (restartPolicy .Window ),
486+ }, nil
487+ }
488+ if restart == "" {
489+ return nil , nil
490+ }
491+
492+ // Fall back to the legacy service.restart restart-policy.
493+ policy , err := opts .ParseRestartPolicy (restart )
494+ if err != nil {
495+ return nil , err
496+ }
497+ if policy .MaximumRetryCount < 0 {
498+ return nil , errors .New ("invalid restart policy: maximum retry count cannot be negative" )
499+ }
500+ uint64Ptr := func (i int ) * uint64 {
501+ if i <= 0 {
502+ return nil
497503 }
504+ p := uint64 (i )
505+ return & p
498506 }
499507
500- return & swarm.RestartPolicy {
501- Condition : swarm .RestartPolicyCondition (source .Condition ),
502- Delay : composetypes .ConvertDurationPtr (source .Delay ),
503- MaxAttempts : source .MaxAttempts ,
504- Window : composetypes .ConvertDurationPtr (source .Window ),
505- }, nil
508+ switch policy .Name {
509+ case container .RestartPolicyDisabled , "" :
510+ return nil , nil
511+ case container .RestartPolicyAlways , container .RestartPolicyUnlessStopped :
512+ return & swarm.RestartPolicy {
513+ Condition : swarm .RestartPolicyConditionAny ,
514+ MaxAttempts : uint64Ptr (policy .MaximumRetryCount ),
515+ }, nil
516+ case container .RestartPolicyOnFailure :
517+ return & swarm.RestartPolicy {
518+ Condition : swarm .RestartPolicyConditionOnFailure ,
519+ MaxAttempts : uint64Ptr (policy .MaximumRetryCount ),
520+ }, nil
521+ default :
522+ return nil , fmt .Errorf ("invalid restart policy: unknown policy '%s' (must be one of '%s', '%s', '%s', or '%s')" ,
523+ policy .Name , container .RestartPolicyDisabled , container .RestartPolicyAlways , container .RestartPolicyOnFailure , container .RestartPolicyUnlessStopped ,
524+ )
525+ }
506526}
507527
508528func convertUpdateConfig (source * composetypes.UpdateConfig ) * swarm.UpdateConfig {
0 commit comments