github.com/kim0/docker@v0.6.2-0.20161130212042-4addda3f07e7/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 TargetPort: portConfig.TargetPort, 203 PublishedPort: portConfig.PublishedPort, 204 }) 205 } 206 } 207 208 // Mode 209 if s.Mode.Global != nil && s.Mode.Replicated != nil { 210 return swarmapi.ServiceSpec{}, fmt.Errorf("cannot specify both replicated mode and global mode") 211 } 212 213 if s.Mode.Global != nil { 214 spec.Mode = &swarmapi.ServiceSpec_Global{ 215 Global: &swarmapi.GlobalService{}, 216 } 217 } else if s.Mode.Replicated != nil && s.Mode.Replicated.Replicas != nil { 218 spec.Mode = &swarmapi.ServiceSpec_Replicated{ 219 Replicated: &swarmapi.ReplicatedService{Replicas: *s.Mode.Replicated.Replicas}, 220 } 221 } else { 222 spec.Mode = &swarmapi.ServiceSpec_Replicated{ 223 Replicated: &swarmapi.ReplicatedService{Replicas: 1}, 224 } 225 } 226 227 return spec, nil 228 } 229 230 func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequirements { 231 var resources *types.ResourceRequirements 232 if res != nil { 233 resources = &types.ResourceRequirements{} 234 if res.Limits != nil { 235 resources.Limits = &types.Resources{ 236 NanoCPUs: res.Limits.NanoCPUs, 237 MemoryBytes: res.Limits.MemoryBytes, 238 } 239 } 240 if res.Reservations != nil { 241 resources.Reservations = &types.Resources{ 242 NanoCPUs: res.Reservations.NanoCPUs, 243 MemoryBytes: res.Reservations.MemoryBytes, 244 } 245 } 246 } 247 248 return resources 249 } 250 251 func resourcesToGRPC(res *types.ResourceRequirements) *swarmapi.ResourceRequirements { 252 var reqs *swarmapi.ResourceRequirements 253 if res != nil { 254 reqs = &swarmapi.ResourceRequirements{} 255 if res.Limits != nil { 256 reqs.Limits = &swarmapi.Resources{ 257 NanoCPUs: res.Limits.NanoCPUs, 258 MemoryBytes: res.Limits.MemoryBytes, 259 } 260 } 261 if res.Reservations != nil { 262 reqs.Reservations = &swarmapi.Resources{ 263 NanoCPUs: res.Reservations.NanoCPUs, 264 MemoryBytes: res.Reservations.MemoryBytes, 265 } 266 267 } 268 } 269 return reqs 270 } 271 272 func restartPolicyFromGRPC(p *swarmapi.RestartPolicy) *types.RestartPolicy { 273 var rp *types.RestartPolicy 274 if p != nil { 275 rp = &types.RestartPolicy{} 276 277 switch p.Condition { 278 case swarmapi.RestartOnNone: 279 rp.Condition = types.RestartPolicyConditionNone 280 case swarmapi.RestartOnFailure: 281 rp.Condition = types.RestartPolicyConditionOnFailure 282 case swarmapi.RestartOnAny: 283 rp.Condition = types.RestartPolicyConditionAny 284 default: 285 rp.Condition = types.RestartPolicyConditionAny 286 } 287 288 if p.Delay != nil { 289 delay, _ := ptypes.Duration(p.Delay) 290 rp.Delay = &delay 291 } 292 if p.Window != nil { 293 window, _ := ptypes.Duration(p.Window) 294 rp.Window = &window 295 } 296 297 rp.MaxAttempts = &p.MaxAttempts 298 } 299 return rp 300 } 301 302 func restartPolicyToGRPC(p *types.RestartPolicy) (*swarmapi.RestartPolicy, error) { 303 var rp *swarmapi.RestartPolicy 304 if p != nil { 305 rp = &swarmapi.RestartPolicy{} 306 307 switch p.Condition { 308 case types.RestartPolicyConditionNone: 309 rp.Condition = swarmapi.RestartOnNone 310 case types.RestartPolicyConditionOnFailure: 311 rp.Condition = swarmapi.RestartOnFailure 312 case types.RestartPolicyConditionAny: 313 rp.Condition = swarmapi.RestartOnAny 314 default: 315 if string(p.Condition) != "" { 316 return nil, fmt.Errorf("invalid RestartCondition: %q", p.Condition) 317 } 318 rp.Condition = swarmapi.RestartOnAny 319 } 320 321 if p.Delay != nil { 322 rp.Delay = ptypes.DurationProto(*p.Delay) 323 } 324 if p.Window != nil { 325 rp.Window = ptypes.DurationProto(*p.Window) 326 } 327 if p.MaxAttempts != nil { 328 rp.MaxAttempts = *p.MaxAttempts 329 330 } 331 } 332 return rp, nil 333 } 334 335 func placementFromGRPC(p *swarmapi.Placement) *types.Placement { 336 var r *types.Placement 337 if p != nil { 338 r = &types.Placement{} 339 r.Constraints = p.Constraints 340 } 341 342 return r 343 } 344 345 func driverFromGRPC(p *swarmapi.Driver) *types.Driver { 346 if p == nil { 347 return nil 348 } 349 350 return &types.Driver{ 351 Name: p.Name, 352 Options: p.Options, 353 } 354 } 355 356 func driverToGRPC(p *types.Driver) *swarmapi.Driver { 357 if p == nil { 358 return nil 359 } 360 361 return &swarmapi.Driver{ 362 Name: p.Name, 363 Options: p.Options, 364 } 365 }