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  }