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  }