2016-06-13 22:52:49 -04:00
|
|
|
package convert
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2016-09-06 14:18:12 -04:00
|
|
|
types "github.com/docker/docker/api/types/swarm"
|
2016-06-13 22:52:49 -04:00
|
|
|
"github.com/docker/docker/pkg/namesgenerator"
|
|
|
|
swarmapi "github.com/docker/swarmkit/api"
|
|
|
|
"github.com/docker/swarmkit/protobuf/ptypes"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ServiceFromGRPC converts a grpc Service to a Service.
|
|
|
|
func ServiceFromGRPC(s swarmapi.Service) types.Service {
|
2016-09-02 17:12:05 -04:00
|
|
|
service := types.Service{
|
|
|
|
ID: s.ID,
|
|
|
|
Spec: *serviceSpecFromGRPC(&s.Spec),
|
|
|
|
PreviousSpec: serviceSpecFromGRPC(s.PreviousSpec),
|
|
|
|
|
|
|
|
Endpoint: endpointFromGRPC(s.Endpoint),
|
|
|
|
}
|
|
|
|
|
|
|
|
// Meta
|
|
|
|
service.Version.Index = s.Meta.Version.Index
|
|
|
|
service.CreatedAt, _ = ptypes.Timestamp(s.Meta.CreatedAt)
|
|
|
|
service.UpdatedAt, _ = ptypes.Timestamp(s.Meta.UpdatedAt)
|
|
|
|
|
|
|
|
// UpdateStatus
|
|
|
|
if s.UpdateStatus != nil {
|
2016-12-01 17:08:06 -05:00
|
|
|
service.UpdateStatus = &types.UpdateStatus{}
|
2016-09-02 17:12:05 -04:00
|
|
|
switch s.UpdateStatus.State {
|
|
|
|
case swarmapi.UpdateStatus_UPDATING:
|
|
|
|
service.UpdateStatus.State = types.UpdateStateUpdating
|
|
|
|
case swarmapi.UpdateStatus_PAUSED:
|
|
|
|
service.UpdateStatus.State = types.UpdateStatePaused
|
|
|
|
case swarmapi.UpdateStatus_COMPLETED:
|
|
|
|
service.UpdateStatus.State = types.UpdateStateCompleted
|
|
|
|
}
|
|
|
|
|
2016-12-01 17:08:06 -05:00
|
|
|
startedAt, _ := ptypes.Timestamp(s.UpdateStatus.StartedAt)
|
|
|
|
if !startedAt.IsZero() {
|
|
|
|
service.UpdateStatus.StartedAt = &startedAt
|
|
|
|
}
|
|
|
|
|
|
|
|
completedAt, _ := ptypes.Timestamp(s.UpdateStatus.CompletedAt)
|
|
|
|
if !completedAt.IsZero() {
|
|
|
|
service.UpdateStatus.CompletedAt = &completedAt
|
|
|
|
}
|
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
service.UpdateStatus.Message = s.UpdateStatus.Message
|
|
|
|
}
|
|
|
|
|
|
|
|
return service
|
|
|
|
}
|
|
|
|
|
|
|
|
func serviceSpecFromGRPC(spec *swarmapi.ServiceSpec) *types.ServiceSpec {
|
|
|
|
if spec == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2016-06-13 22:52:49 -04:00
|
|
|
|
2016-08-23 19:50:15 -04:00
|
|
|
serviceNetworks := make([]types.NetworkAttachmentConfig, 0, len(spec.Networks))
|
2016-06-13 22:52:49 -04:00
|
|
|
for _, n := range spec.Networks {
|
2016-08-23 19:50:15 -04:00
|
|
|
serviceNetworks = append(serviceNetworks, types.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases})
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
2016-08-23 19:50:15 -04:00
|
|
|
|
|
|
|
taskNetworks := make([]types.NetworkAttachmentConfig, 0, len(spec.Task.Networks))
|
|
|
|
for _, n := range spec.Task.Networks {
|
|
|
|
taskNetworks = append(taskNetworks, types.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases})
|
|
|
|
}
|
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
containerConfig := spec.Task.Runtime.(*swarmapi.TaskSpec_Container).Container
|
|
|
|
convertedSpec := &types.ServiceSpec{
|
|
|
|
Annotations: types.Annotations{
|
|
|
|
Name: spec.Annotations.Name,
|
|
|
|
Labels: spec.Annotations.Labels,
|
2016-06-13 22:52:49 -04:00
|
|
|
},
|
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
TaskTemplate: types.TaskSpec{
|
|
|
|
ContainerSpec: containerSpecFromGRPC(containerConfig),
|
|
|
|
Resources: resourcesFromGRPC(spec.Task.Resources),
|
|
|
|
RestartPolicy: restartPolicyFromGRPC(spec.Task.Restart),
|
|
|
|
Placement: placementFromGRPC(spec.Task.Placement),
|
|
|
|
LogDriver: driverFromGRPC(spec.Task.LogDriver),
|
|
|
|
Networks: taskNetworks,
|
2016-10-20 15:04:01 -04:00
|
|
|
ForceUpdate: spec.Task.ForceUpdate,
|
2016-09-02 17:12:05 -04:00
|
|
|
},
|
2016-06-13 22:52:49 -04:00
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
Networks: serviceNetworks,
|
|
|
|
EndpointSpec: endpointSpecFromGRPC(spec.Endpoint),
|
|
|
|
}
|
2016-06-13 22:52:49 -04:00
|
|
|
|
|
|
|
// UpdateConfig
|
2016-09-02 17:12:05 -04:00
|
|
|
if spec.Update != nil {
|
|
|
|
convertedSpec.UpdateConfig = &types.UpdateConfig{
|
|
|
|
Parallelism: spec.Update.Parallelism,
|
|
|
|
MaxFailureRatio: spec.Update.MaxFailureRatio,
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
convertedSpec.UpdateConfig.Delay, _ = ptypes.Duration(&spec.Update.Delay)
|
|
|
|
if spec.Update.Monitor != nil {
|
|
|
|
convertedSpec.UpdateConfig.Monitor, _ = ptypes.Duration(spec.Update.Monitor)
|
|
|
|
}
|
2016-07-22 14:35:51 -04:00
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
switch spec.Update.FailureAction {
|
2016-07-22 14:35:51 -04:00
|
|
|
case swarmapi.UpdateConfig_PAUSE:
|
2016-09-02 17:12:05 -04:00
|
|
|
convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionPause
|
2016-07-22 14:35:51 -04:00
|
|
|
case swarmapi.UpdateConfig_CONTINUE:
|
2016-09-02 17:12:05 -04:00
|
|
|
convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionContinue
|
2016-07-22 14:35:51 -04:00
|
|
|
}
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
|
|
|
|
2016-07-22 14:35:51 -04:00
|
|
|
// Mode
|
2016-09-02 17:12:05 -04:00
|
|
|
switch t := spec.GetMode().(type) {
|
2016-06-13 22:52:49 -04:00
|
|
|
case *swarmapi.ServiceSpec_Global:
|
2016-09-02 17:12:05 -04:00
|
|
|
convertedSpec.Mode.Global = &types.GlobalService{}
|
2016-06-13 22:52:49 -04:00
|
|
|
case *swarmapi.ServiceSpec_Replicated:
|
2016-09-02 17:12:05 -04:00
|
|
|
convertedSpec.Mode.Replicated = &types.ReplicatedService{
|
2016-06-13 22:52:49 -04:00
|
|
|
Replicas: &t.Replicated.Replicas,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-02 17:12:05 -04:00
|
|
|
return convertedSpec
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// ServiceSpecToGRPC converts a ServiceSpec to a grpc ServiceSpec.
|
|
|
|
func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) {
|
|
|
|
name := s.Name
|
|
|
|
if name == "" {
|
|
|
|
name = namesgenerator.GetRandomName(0)
|
|
|
|
}
|
|
|
|
|
2016-08-23 19:50:15 -04:00
|
|
|
serviceNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.Networks))
|
2016-06-13 22:52:49 -04:00
|
|
|
for _, n := range s.Networks {
|
2016-08-23 19:50:15 -04:00
|
|
|
serviceNetworks = append(serviceNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases})
|
|
|
|
}
|
|
|
|
|
|
|
|
taskNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.TaskTemplate.Networks))
|
|
|
|
for _, n := range s.TaskTemplate.Networks {
|
|
|
|
taskNetworks = append(taskNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases})
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
spec := swarmapi.ServiceSpec{
|
|
|
|
Annotations: swarmapi.Annotations{
|
|
|
|
Name: name,
|
|
|
|
Labels: s.Labels,
|
|
|
|
},
|
|
|
|
Task: swarmapi.TaskSpec{
|
2016-10-20 15:04:01 -04:00
|
|
|
Resources: resourcesToGRPC(s.TaskTemplate.Resources),
|
|
|
|
LogDriver: driverToGRPC(s.TaskTemplate.LogDriver),
|
|
|
|
Networks: taskNetworks,
|
|
|
|
ForceUpdate: s.TaskTemplate.ForceUpdate,
|
2016-06-13 22:52:49 -04:00
|
|
|
},
|
2016-08-23 19:50:15 -04:00
|
|
|
Networks: serviceNetworks,
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
containerSpec, err := containerToGRPC(s.TaskTemplate.ContainerSpec)
|
|
|
|
if err != nil {
|
|
|
|
return swarmapi.ServiceSpec{}, err
|
|
|
|
}
|
|
|
|
spec.Task.Runtime = &swarmapi.TaskSpec_Container{Container: containerSpec}
|
|
|
|
|
|
|
|
restartPolicy, err := restartPolicyToGRPC(s.TaskTemplate.RestartPolicy)
|
|
|
|
if err != nil {
|
|
|
|
return swarmapi.ServiceSpec{}, err
|
|
|
|
}
|
|
|
|
spec.Task.Restart = restartPolicy
|
|
|
|
|
|
|
|
if s.TaskTemplate.Placement != nil {
|
|
|
|
spec.Task.Placement = &swarmapi.Placement{
|
|
|
|
Constraints: s.TaskTemplate.Placement.Constraints,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.UpdateConfig != nil {
|
2016-07-22 14:35:51 -04:00
|
|
|
var failureAction swarmapi.UpdateConfig_FailureAction
|
|
|
|
switch s.UpdateConfig.FailureAction {
|
|
|
|
case types.UpdateFailureActionPause, "":
|
|
|
|
failureAction = swarmapi.UpdateConfig_PAUSE
|
|
|
|
case types.UpdateFailureActionContinue:
|
|
|
|
failureAction = swarmapi.UpdateConfig_CONTINUE
|
|
|
|
default:
|
|
|
|
return swarmapi.ServiceSpec{}, fmt.Errorf("unrecongized update failure action %s", s.UpdateConfig.FailureAction)
|
|
|
|
}
|
2016-06-13 22:52:49 -04:00
|
|
|
spec.Update = &swarmapi.UpdateConfig{
|
2016-09-02 17:12:05 -04:00
|
|
|
Parallelism: s.UpdateConfig.Parallelism,
|
|
|
|
Delay: *ptypes.DurationProto(s.UpdateConfig.Delay),
|
|
|
|
FailureAction: failureAction,
|
|
|
|
MaxFailureRatio: s.UpdateConfig.MaxFailureRatio,
|
|
|
|
}
|
|
|
|
if s.UpdateConfig.Monitor != 0 {
|
|
|
|
spec.Update.Monitor = ptypes.DurationProto(s.UpdateConfig.Monitor)
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.EndpointSpec != nil {
|
|
|
|
if s.EndpointSpec.Mode != "" &&
|
|
|
|
s.EndpointSpec.Mode != types.ResolutionModeVIP &&
|
|
|
|
s.EndpointSpec.Mode != types.ResolutionModeDNSRR {
|
|
|
|
return swarmapi.ServiceSpec{}, fmt.Errorf("invalid resolution mode: %q", s.EndpointSpec.Mode)
|
|
|
|
}
|
|
|
|
|
|
|
|
spec.Endpoint = &swarmapi.EndpointSpec{}
|
|
|
|
|
|
|
|
spec.Endpoint.Mode = swarmapi.EndpointSpec_ResolutionMode(swarmapi.EndpointSpec_ResolutionMode_value[strings.ToUpper(string(s.EndpointSpec.Mode))])
|
|
|
|
|
|
|
|
for _, portConfig := range s.EndpointSpec.Ports {
|
|
|
|
spec.Endpoint.Ports = append(spec.Endpoint.Ports, &swarmapi.PortConfig{
|
|
|
|
Name: portConfig.Name,
|
|
|
|
Protocol: swarmapi.PortConfig_Protocol(swarmapi.PortConfig_Protocol_value[strings.ToUpper(string(portConfig.Protocol))]),
|
2016-11-10 15:13:26 -05:00
|
|
|
PublishMode: swarmapi.PortConfig_PublishMode(swarmapi.PortConfig_PublishMode_value[strings.ToUpper(string(portConfig.PublishMode))]),
|
2016-06-13 22:52:49 -04:00
|
|
|
TargetPort: portConfig.TargetPort,
|
|
|
|
PublishedPort: portConfig.PublishedPort,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-16 14:00:16 -04:00
|
|
|
// Mode
|
|
|
|
if s.Mode.Global != nil && s.Mode.Replicated != nil {
|
|
|
|
return swarmapi.ServiceSpec{}, fmt.Errorf("cannot specify both replicated mode and global mode")
|
|
|
|
}
|
|
|
|
|
2016-06-13 22:52:49 -04:00
|
|
|
if s.Mode.Global != nil {
|
|
|
|
spec.Mode = &swarmapi.ServiceSpec_Global{
|
|
|
|
Global: &swarmapi.GlobalService{},
|
|
|
|
}
|
|
|
|
} else if s.Mode.Replicated != nil && s.Mode.Replicated.Replicas != nil {
|
|
|
|
spec.Mode = &swarmapi.ServiceSpec_Replicated{
|
|
|
|
Replicated: &swarmapi.ReplicatedService{Replicas: *s.Mode.Replicated.Replicas},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
spec.Mode = &swarmapi.ServiceSpec_Replicated{
|
|
|
|
Replicated: &swarmapi.ReplicatedService{Replicas: 1},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return spec, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequirements {
|
|
|
|
var resources *types.ResourceRequirements
|
|
|
|
if res != nil {
|
|
|
|
resources = &types.ResourceRequirements{}
|
|
|
|
if res.Limits != nil {
|
|
|
|
resources.Limits = &types.Resources{
|
|
|
|
NanoCPUs: res.Limits.NanoCPUs,
|
|
|
|
MemoryBytes: res.Limits.MemoryBytes,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if res.Reservations != nil {
|
|
|
|
resources.Reservations = &types.Resources{
|
|
|
|
NanoCPUs: res.Reservations.NanoCPUs,
|
|
|
|
MemoryBytes: res.Reservations.MemoryBytes,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resources
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourcesToGRPC(res *types.ResourceRequirements) *swarmapi.ResourceRequirements {
|
|
|
|
var reqs *swarmapi.ResourceRequirements
|
|
|
|
if res != nil {
|
|
|
|
reqs = &swarmapi.ResourceRequirements{}
|
|
|
|
if res.Limits != nil {
|
|
|
|
reqs.Limits = &swarmapi.Resources{
|
|
|
|
NanoCPUs: res.Limits.NanoCPUs,
|
|
|
|
MemoryBytes: res.Limits.MemoryBytes,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if res.Reservations != nil {
|
|
|
|
reqs.Reservations = &swarmapi.Resources{
|
|
|
|
NanoCPUs: res.Reservations.NanoCPUs,
|
|
|
|
MemoryBytes: res.Reservations.MemoryBytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return reqs
|
|
|
|
}
|
|
|
|
|
|
|
|
func restartPolicyFromGRPC(p *swarmapi.RestartPolicy) *types.RestartPolicy {
|
|
|
|
var rp *types.RestartPolicy
|
|
|
|
if p != nil {
|
|
|
|
rp = &types.RestartPolicy{}
|
2016-09-30 03:54:47 -04:00
|
|
|
|
|
|
|
switch p.Condition {
|
|
|
|
case swarmapi.RestartOnNone:
|
|
|
|
rp.Condition = types.RestartPolicyConditionNone
|
|
|
|
case swarmapi.RestartOnFailure:
|
|
|
|
rp.Condition = types.RestartPolicyConditionOnFailure
|
|
|
|
case swarmapi.RestartOnAny:
|
|
|
|
rp.Condition = types.RestartPolicyConditionAny
|
|
|
|
default:
|
|
|
|
rp.Condition = types.RestartPolicyConditionAny
|
|
|
|
}
|
|
|
|
|
2016-06-13 22:52:49 -04:00
|
|
|
if p.Delay != nil {
|
|
|
|
delay, _ := ptypes.Duration(p.Delay)
|
|
|
|
rp.Delay = &delay
|
|
|
|
}
|
|
|
|
if p.Window != nil {
|
|
|
|
window, _ := ptypes.Duration(p.Window)
|
|
|
|
rp.Window = &window
|
|
|
|
}
|
|
|
|
|
|
|
|
rp.MaxAttempts = &p.MaxAttempts
|
|
|
|
}
|
|
|
|
return rp
|
|
|
|
}
|
|
|
|
|
|
|
|
func restartPolicyToGRPC(p *types.RestartPolicy) (*swarmapi.RestartPolicy, error) {
|
|
|
|
var rp *swarmapi.RestartPolicy
|
|
|
|
if p != nil {
|
|
|
|
rp = &swarmapi.RestartPolicy{}
|
2016-09-30 03:54:47 -04:00
|
|
|
|
|
|
|
switch p.Condition {
|
|
|
|
case types.RestartPolicyConditionNone:
|
|
|
|
rp.Condition = swarmapi.RestartOnNone
|
|
|
|
case types.RestartPolicyConditionOnFailure:
|
|
|
|
rp.Condition = swarmapi.RestartOnFailure
|
|
|
|
case types.RestartPolicyConditionAny:
|
|
|
|
rp.Condition = swarmapi.RestartOnAny
|
|
|
|
default:
|
|
|
|
if string(p.Condition) != "" {
|
|
|
|
return nil, fmt.Errorf("invalid RestartCondition: %q", p.Condition)
|
|
|
|
}
|
2016-06-13 22:52:49 -04:00
|
|
|
rp.Condition = swarmapi.RestartOnAny
|
|
|
|
}
|
|
|
|
|
|
|
|
if p.Delay != nil {
|
|
|
|
rp.Delay = ptypes.DurationProto(*p.Delay)
|
|
|
|
}
|
|
|
|
if p.Window != nil {
|
|
|
|
rp.Window = ptypes.DurationProto(*p.Window)
|
|
|
|
}
|
|
|
|
if p.MaxAttempts != nil {
|
|
|
|
rp.MaxAttempts = *p.MaxAttempts
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func placementFromGRPC(p *swarmapi.Placement) *types.Placement {
|
|
|
|
var r *types.Placement
|
|
|
|
if p != nil {
|
|
|
|
r = &types.Placement{}
|
|
|
|
r.Constraints = p.Constraints
|
|
|
|
}
|
|
|
|
|
|
|
|
return r
|
|
|
|
}
|
2016-07-08 21:44:18 -04:00
|
|
|
|
|
|
|
func driverFromGRPC(p *swarmapi.Driver) *types.Driver {
|
|
|
|
if p == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &types.Driver{
|
|
|
|
Name: p.Name,
|
|
|
|
Options: p.Options,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func driverToGRPC(p *types.Driver) *swarmapi.Driver {
|
|
|
|
if p == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &swarmapi.Driver{
|
|
|
|
Name: p.Name,
|
|
|
|
Options: p.Options,
|
|
|
|
}
|
|
|
|
}
|