github.com/olljanat/moby@v1.13.1/daemon/cluster/convert/service.go (about) 1 package convert 2 3 import ( 4 "fmt" 5 "strings" 6 7 types "github.com/docker/docker/api/types/swarm" 8 "github.com/docker/docker/pkg/namesgenerator" 9 swarmapi "github.com/docker/swarmkit/api" 10 "github.com/docker/swarmkit/protobuf/ptypes" 11 ) 12 13 // ServiceFromGRPC converts a grpc Service to a Service. 14 func ServiceFromGRPC(s swarmapi.Service) types.Service { 15 service := types.Service{ 16 ID: s.ID, 17 Spec: *serviceSpecFromGRPC(&s.Spec), 18 PreviousSpec: serviceSpecFromGRPC(s.PreviousSpec), 19 20 Endpoint: endpointFromGRPC(s.Endpoint), 21 } 22 23 // Meta 24 service.Version.Index = s.Meta.Version.Index 25 service.CreatedAt, _ = ptypes.Timestamp(s.Meta.CreatedAt) 26 service.UpdatedAt, _ = ptypes.Timestamp(s.Meta.UpdatedAt) 27 28 // UpdateStatus 29 service.UpdateStatus = types.UpdateStatus{} 30 if s.UpdateStatus != nil { 31 switch s.UpdateStatus.State { 32 case swarmapi.UpdateStatus_UPDATING: 33 service.UpdateStatus.State = types.UpdateStateUpdating 34 case swarmapi.UpdateStatus_PAUSED: 35 service.UpdateStatus.State = types.UpdateStatePaused 36 case swarmapi.UpdateStatus_COMPLETED: 37 service.UpdateStatus.State = types.UpdateStateCompleted 38 } 39 40 service.UpdateStatus.StartedAt, _ = ptypes.Timestamp(s.UpdateStatus.StartedAt) 41 service.UpdateStatus.CompletedAt, _ = ptypes.Timestamp(s.UpdateStatus.CompletedAt) 42 service.UpdateStatus.Message = s.UpdateStatus.Message 43 } 44 45 return service 46 } 47 48 func serviceSpecFromGRPC(spec *swarmapi.ServiceSpec) *types.ServiceSpec { 49 if spec == nil { 50 return nil 51 } 52 53 serviceNetworks := make([]types.NetworkAttachmentConfig, 0, len(spec.Networks)) 54 for _, n := range spec.Networks { 55 serviceNetworks = append(serviceNetworks, types.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) 56 } 57 58 taskNetworks := make([]types.NetworkAttachmentConfig, 0, len(spec.Task.Networks)) 59 for _, n := range spec.Task.Networks { 60 taskNetworks = append(taskNetworks, types.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) 61 } 62 63 containerConfig := spec.Task.Runtime.(*swarmapi.TaskSpec_Container).Container 64 convertedSpec := &types.ServiceSpec{ 65 Annotations: types.Annotations{ 66 Name: spec.Annotations.Name, 67 Labels: spec.Annotations.Labels, 68 }, 69 70 TaskTemplate: types.TaskSpec{ 71 ContainerSpec: containerSpecFromGRPC(containerConfig), 72 Resources: resourcesFromGRPC(spec.Task.Resources), 73 RestartPolicy: restartPolicyFromGRPC(spec.Task.Restart), 74 Placement: placementFromGRPC(spec.Task.Placement), 75 LogDriver: driverFromGRPC(spec.Task.LogDriver), 76 Networks: taskNetworks, 77 ForceUpdate: spec.Task.ForceUpdate, 78 }, 79 80 Networks: serviceNetworks, 81 EndpointSpec: endpointSpecFromGRPC(spec.Endpoint), 82 } 83 84 // UpdateConfig 85 if spec.Update != nil { 86 convertedSpec.UpdateConfig = &types.UpdateConfig{ 87 Parallelism: spec.Update.Parallelism, 88 MaxFailureRatio: spec.Update.MaxFailureRatio, 89 } 90 91 convertedSpec.UpdateConfig.Delay, _ = ptypes.Duration(&spec.Update.Delay) 92 if spec.Update.Monitor != nil { 93 convertedSpec.UpdateConfig.Monitor, _ = ptypes.Duration(spec.Update.Monitor) 94 } 95 96 switch spec.Update.FailureAction { 97 case swarmapi.UpdateConfig_PAUSE: 98 convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionPause 99 case swarmapi.UpdateConfig_CONTINUE: 100 convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionContinue 101 } 102 } 103 104 // Mode 105 switch t := spec.GetMode().(type) { 106 case *swarmapi.ServiceSpec_Global: 107 convertedSpec.Mode.Global = &types.GlobalService{} 108 case *swarmapi.ServiceSpec_Replicated: 109 convertedSpec.Mode.Replicated = &types.ReplicatedService{ 110 Replicas: &t.Replicated.Replicas, 111 } 112 } 113 114 return convertedSpec 115 } 116 117 // ServiceSpecToGRPC converts a ServiceSpec to a grpc ServiceSpec. 118 func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) { 119 name := s.Name 120 if name == "" { 121 name = namesgenerator.GetRandomName(0) 122 } 123 124 serviceNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.Networks)) 125 for _, n := range s.Networks { 126 serviceNetworks = append(serviceNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) 127 } 128 129 taskNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.TaskTemplate.Networks)) 130 for _, n := range s.TaskTemplate.Networks { 131 taskNetworks = append(taskNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) 132 } 133 134 spec := swarmapi.ServiceSpec{ 135 Annotations: swarmapi.Annotations{ 136 Name: name, 137 Labels: s.Labels, 138 }, 139 Task: swarmapi.TaskSpec{ 140 Resources: resourcesToGRPC(s.TaskTemplate.Resources), 141 LogDriver: driverToGRPC(s.TaskTemplate.LogDriver), 142 Networks: taskNetworks, 143 ForceUpdate: s.TaskTemplate.ForceUpdate, 144 }, 145 Networks: serviceNetworks, 146 } 147 148 containerSpec, err := containerToGRPC(s.TaskTemplate.ContainerSpec) 149 if err != nil { 150 return swarmapi.ServiceSpec{}, err 151 } 152 spec.Task.Runtime = &swarmapi.TaskSpec_Container{Container: containerSpec} 153 154 restartPolicy, err := restartPolicyToGRPC(s.TaskTemplate.RestartPolicy) 155 if err != nil { 156 return swarmapi.ServiceSpec{}, err 157 } 158 spec.Task.Restart = restartPolicy 159 160 if s.TaskTemplate.Placement != nil { 161 spec.Task.Placement = &swarmapi.Placement{ 162 Constraints: s.TaskTemplate.Placement.Constraints, 163 } 164 } 165 166 if s.UpdateConfig != nil { 167 var failureAction swarmapi.UpdateConfig_FailureAction 168 switch s.UpdateConfig.FailureAction { 169 case types.UpdateFailureActionPause, "": 170 failureAction = swarmapi.UpdateConfig_PAUSE 171 case types.UpdateFailureActionContinue: 172 failureAction = swarmapi.UpdateConfig_CONTINUE 173 default: 174 return swarmapi.ServiceSpec{}, fmt.Errorf("unrecongized update failure action %s", s.UpdateConfig.FailureAction) 175 } 176 spec.Update = &swarmapi.UpdateConfig{ 177 Parallelism: s.UpdateConfig.Parallelism, 178 Delay: *ptypes.DurationProto(s.UpdateConfig.Delay), 179 FailureAction: failureAction, 180 MaxFailureRatio: s.UpdateConfig.MaxFailureRatio, 181 } 182 if s.UpdateConfig.Monitor != 0 { 183 spec.Update.Monitor = ptypes.DurationProto(s.UpdateConfig.Monitor) 184 } 185 } 186 187 if s.EndpointSpec != nil { 188 if s.EndpointSpec.Mode != "" && 189 s.EndpointSpec.Mode != types.ResolutionModeVIP && 190 s.EndpointSpec.Mode != types.ResolutionModeDNSRR { 191 return swarmapi.ServiceSpec{}, fmt.Errorf("invalid resolution mode: %q", s.EndpointSpec.Mode) 192 } 193 194 spec.Endpoint = &swarmapi.EndpointSpec{} 195 196 spec.Endpoint.Mode = swarmapi.EndpointSpec_ResolutionMode(swarmapi.EndpointSpec_ResolutionMode_value[strings.ToUpper(string(s.EndpointSpec.Mode))]) 197 198 for _, portConfig := range s.EndpointSpec.Ports { 199 spec.Endpoint.Ports = append(spec.Endpoint.Ports, &swarmapi.PortConfig{ 200 Name: portConfig.Name, 201 Protocol: swarmapi.PortConfig_Protocol(swarmapi.PortConfig_Protocol_value[strings.ToUpper(string(portConfig.Protocol))]), 202 PublishMode: swarmapi.PortConfig_PublishMode(swarmapi.PortConfig_PublishMode_value[strings.ToUpper(string(portConfig.PublishMode))]), 203 TargetPort: portConfig.TargetPort, 204 PublishedPort: portConfig.PublishedPort, 205 }) 206 } 207 } 208 209 // Mode 210 if s.Mode.Global != nil && s.Mode.Replicated != nil { 211 return swarmapi.ServiceSpec{}, fmt.Errorf("cannot specify both replicated mode and global mode") 212 } 213 214 if s.Mode.Global != nil { 215 spec.Mode = &swarmapi.ServiceSpec_Global{ 216 Global: &swarmapi.GlobalService{}, 217 } 218 } else if s.Mode.Replicated != nil && s.Mode.Replicated.Replicas != nil { 219 spec.Mode = &swarmapi.ServiceSpec_Replicated{ 220 Replicated: &swarmapi.ReplicatedService{Replicas: *s.Mode.Replicated.Replicas}, 221 } 222 } else { 223 spec.Mode = &swarmapi.ServiceSpec_Replicated{ 224 Replicated: &swarmapi.ReplicatedService{Replicas: 1}, 225 } 226 } 227 228 return spec, nil 229 } 230 231 func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequirements { 232 var resources *types.ResourceRequirements 233 if res != nil { 234 resources = &types.ResourceRequirements{} 235 if res.Limits != nil { 236 resources.Limits = &types.Resources{ 237 NanoCPUs: res.Limits.NanoCPUs, 238 MemoryBytes: res.Limits.MemoryBytes, 239 } 240 } 241 if res.Reservations != nil { 242 resources.Reservations = &types.Resources{ 243 NanoCPUs: res.Reservations.NanoCPUs, 244 MemoryBytes: res.Reservations.MemoryBytes, 245 } 246 } 247 } 248 249 return resources 250 } 251 252 func resourcesToGRPC(res *types.ResourceRequirements) *swarmapi.ResourceRequirements { 253 var reqs *swarmapi.ResourceRequirements 254 if res != nil { 255 reqs = &swarmapi.ResourceRequirements{} 256 if res.Limits != nil { 257 reqs.Limits = &swarmapi.Resources{ 258 NanoCPUs: res.Limits.NanoCPUs, 259 MemoryBytes: res.Limits.MemoryBytes, 260 } 261 } 262 if res.Reservations != nil { 263 reqs.Reservations = &swarmapi.Resources{ 264 NanoCPUs: res.Reservations.NanoCPUs, 265 MemoryBytes: res.Reservations.MemoryBytes, 266 } 267 268 } 269 } 270 return reqs 271 } 272 273 func restartPolicyFromGRPC(p *swarmapi.RestartPolicy) *types.RestartPolicy { 274 var rp *types.RestartPolicy 275 if p != nil { 276 rp = &types.RestartPolicy{} 277 278 switch p.Condition { 279 case swarmapi.RestartOnNone: 280 rp.Condition = types.RestartPolicyConditionNone 281 case swarmapi.RestartOnFailure: 282 rp.Condition = types.RestartPolicyConditionOnFailure 283 case swarmapi.RestartOnAny: 284 rp.Condition = types.RestartPolicyConditionAny 285 default: 286 rp.Condition = types.RestartPolicyConditionAny 287 } 288 289 if p.Delay != nil { 290 delay, _ := ptypes.Duration(p.Delay) 291 rp.Delay = &delay 292 } 293 if p.Window != nil { 294 window, _ := ptypes.Duration(p.Window) 295 rp.Window = &window 296 } 297 298 rp.MaxAttempts = &p.MaxAttempts 299 } 300 return rp 301 } 302 303 func restartPolicyToGRPC(p *types.RestartPolicy) (*swarmapi.RestartPolicy, error) { 304 var rp *swarmapi.RestartPolicy 305 if p != nil { 306 rp = &swarmapi.RestartPolicy{} 307 308 switch p.Condition { 309 case types.RestartPolicyConditionNone: 310 rp.Condition = swarmapi.RestartOnNone 311 case types.RestartPolicyConditionOnFailure: 312 rp.Condition = swarmapi.RestartOnFailure 313 case types.RestartPolicyConditionAny: 314 rp.Condition = swarmapi.RestartOnAny 315 default: 316 if string(p.Condition) != "" { 317 return nil, fmt.Errorf("invalid RestartCondition: %q", p.Condition) 318 } 319 rp.Condition = swarmapi.RestartOnAny 320 } 321 322 if p.Delay != nil { 323 rp.Delay = ptypes.DurationProto(*p.Delay) 324 } 325 if p.Window != nil { 326 rp.Window = ptypes.DurationProto(*p.Window) 327 } 328 if p.MaxAttempts != nil { 329 rp.MaxAttempts = *p.MaxAttempts 330 331 } 332 } 333 return rp, nil 334 } 335 336 func placementFromGRPC(p *swarmapi.Placement) *types.Placement { 337 var r *types.Placement 338 if p != nil { 339 r = &types.Placement{} 340 r.Constraints = p.Constraints 341 } 342 343 return r 344 } 345 346 func driverFromGRPC(p *swarmapi.Driver) *types.Driver { 347 if p == nil { 348 return nil 349 } 350 351 return &types.Driver{ 352 Name: p.Name, 353 Options: p.Options, 354 } 355 } 356 357 func driverToGRPC(p *types.Driver) *swarmapi.Driver { 358 if p == nil { 359 return nil 360 } 361 362 return &swarmapi.Driver{ 363 Name: p.Name, 364 Options: p.Options, 365 } 366 }