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