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