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