github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/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  	gogotypes "github.com/gogo/protobuf/types"
    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, _ = gogotypes.TimestampFromProto(s.Meta.CreatedAt)
    26  	service.UpdatedAt, _ = gogotypes.TimestampFromProto(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, _ := gogotypes.TimestampFromProto(s.UpdateStatus.StartedAt)
    41  		if !startedAt.IsZero() {
    42  			service.UpdateStatus.StartedAt = &startedAt
    43  		}
    44  
    45  		completedAt, _ := gogotypes.TimestampFromProto(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: annotationsFromGRPC(spec.Annotations),
    74  		TaskTemplate: types.TaskSpec{
    75  			ContainerSpec: containerSpecFromGRPC(containerConfig),
    76  			Resources:     resourcesFromGRPC(spec.Task.Resources),
    77  			RestartPolicy: restartPolicyFromGRPC(spec.Task.Restart),
    78  			Placement:     placementFromGRPC(spec.Task.Placement),
    79  			LogDriver:     driverFromGRPC(spec.Task.LogDriver),
    80  			Networks:      taskNetworks,
    81  			ForceUpdate:   spec.Task.ForceUpdate,
    82  		},
    83  
    84  		Networks:     serviceNetworks,
    85  		EndpointSpec: endpointSpecFromGRPC(spec.Endpoint),
    86  	}
    87  
    88  	// UpdateConfig
    89  	if spec.Update != nil {
    90  		convertedSpec.UpdateConfig = &types.UpdateConfig{
    91  			Parallelism:     spec.Update.Parallelism,
    92  			MaxFailureRatio: spec.Update.MaxFailureRatio,
    93  		}
    94  
    95  		convertedSpec.UpdateConfig.Delay = spec.Update.Delay
    96  		if spec.Update.Monitor != nil {
    97  			convertedSpec.UpdateConfig.Monitor, _ = gogotypes.DurationFromProto(spec.Update.Monitor)
    98  		}
    99  
   100  		switch spec.Update.FailureAction {
   101  		case swarmapi.UpdateConfig_PAUSE:
   102  			convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionPause
   103  		case swarmapi.UpdateConfig_CONTINUE:
   104  			convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionContinue
   105  		}
   106  	}
   107  
   108  	// Mode
   109  	switch t := spec.GetMode().(type) {
   110  	case *swarmapi.ServiceSpec_Global:
   111  		convertedSpec.Mode.Global = &types.GlobalService{}
   112  	case *swarmapi.ServiceSpec_Replicated:
   113  		convertedSpec.Mode.Replicated = &types.ReplicatedService{
   114  			Replicas: &t.Replicated.Replicas,
   115  		}
   116  	}
   117  
   118  	return convertedSpec
   119  }
   120  
   121  // ServiceSpecToGRPC converts a ServiceSpec to a grpc ServiceSpec.
   122  func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) {
   123  	name := s.Name
   124  	if name == "" {
   125  		name = namesgenerator.GetRandomName(0)
   126  	}
   127  
   128  	serviceNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.Networks))
   129  	for _, n := range s.Networks {
   130  		serviceNetworks = append(serviceNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases})
   131  	}
   132  
   133  	taskNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.TaskTemplate.Networks))
   134  	for _, n := range s.TaskTemplate.Networks {
   135  		taskNetworks = append(taskNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases})
   136  	}
   137  
   138  	spec := swarmapi.ServiceSpec{
   139  		Annotations: swarmapi.Annotations{
   140  			Name:   name,
   141  			Labels: s.Labels,
   142  		},
   143  		Task: swarmapi.TaskSpec{
   144  			Resources:   resourcesToGRPC(s.TaskTemplate.Resources),
   145  			LogDriver:   driverToGRPC(s.TaskTemplate.LogDriver),
   146  			Networks:    taskNetworks,
   147  			ForceUpdate: s.TaskTemplate.ForceUpdate,
   148  		},
   149  		Networks: serviceNetworks,
   150  	}
   151  
   152  	containerSpec, err := containerToGRPC(s.TaskTemplate.ContainerSpec)
   153  	if err != nil {
   154  		return swarmapi.ServiceSpec{}, err
   155  	}
   156  	spec.Task.Runtime = &swarmapi.TaskSpec_Container{Container: containerSpec}
   157  
   158  	restartPolicy, err := restartPolicyToGRPC(s.TaskTemplate.RestartPolicy)
   159  	if err != nil {
   160  		return swarmapi.ServiceSpec{}, err
   161  	}
   162  	spec.Task.Restart = restartPolicy
   163  
   164  	if s.TaskTemplate.Placement != nil {
   165  		spec.Task.Placement = &swarmapi.Placement{
   166  			Constraints: s.TaskTemplate.Placement.Constraints,
   167  		}
   168  	}
   169  
   170  	if s.UpdateConfig != nil {
   171  		var failureAction swarmapi.UpdateConfig_FailureAction
   172  		switch s.UpdateConfig.FailureAction {
   173  		case types.UpdateFailureActionPause, "":
   174  			failureAction = swarmapi.UpdateConfig_PAUSE
   175  		case types.UpdateFailureActionContinue:
   176  			failureAction = swarmapi.UpdateConfig_CONTINUE
   177  		default:
   178  			return swarmapi.ServiceSpec{}, fmt.Errorf("unrecongized update failure action %s", s.UpdateConfig.FailureAction)
   179  		}
   180  		spec.Update = &swarmapi.UpdateConfig{
   181  			Parallelism:     s.UpdateConfig.Parallelism,
   182  			Delay:           s.UpdateConfig.Delay,
   183  			FailureAction:   failureAction,
   184  			MaxFailureRatio: s.UpdateConfig.MaxFailureRatio,
   185  		}
   186  		if s.UpdateConfig.Monitor != 0 {
   187  			spec.Update.Monitor = gogotypes.DurationProto(s.UpdateConfig.Monitor)
   188  		}
   189  	}
   190  
   191  	if s.EndpointSpec != nil {
   192  		if s.EndpointSpec.Mode != "" &&
   193  			s.EndpointSpec.Mode != types.ResolutionModeVIP &&
   194  			s.EndpointSpec.Mode != types.ResolutionModeDNSRR {
   195  			return swarmapi.ServiceSpec{}, fmt.Errorf("invalid resolution mode: %q", s.EndpointSpec.Mode)
   196  		}
   197  
   198  		spec.Endpoint = &swarmapi.EndpointSpec{}
   199  
   200  		spec.Endpoint.Mode = swarmapi.EndpointSpec_ResolutionMode(swarmapi.EndpointSpec_ResolutionMode_value[strings.ToUpper(string(s.EndpointSpec.Mode))])
   201  
   202  		for _, portConfig := range s.EndpointSpec.Ports {
   203  			spec.Endpoint.Ports = append(spec.Endpoint.Ports, &swarmapi.PortConfig{
   204  				Name:          portConfig.Name,
   205  				Protocol:      swarmapi.PortConfig_Protocol(swarmapi.PortConfig_Protocol_value[strings.ToUpper(string(portConfig.Protocol))]),
   206  				PublishMode:   swarmapi.PortConfig_PublishMode(swarmapi.PortConfig_PublishMode_value[strings.ToUpper(string(portConfig.PublishMode))]),
   207  				TargetPort:    portConfig.TargetPort,
   208  				PublishedPort: portConfig.PublishedPort,
   209  			})
   210  		}
   211  	}
   212  
   213  	// Mode
   214  	if s.Mode.Global != nil && s.Mode.Replicated != nil {
   215  		return swarmapi.ServiceSpec{}, fmt.Errorf("cannot specify both replicated mode and global mode")
   216  	}
   217  
   218  	if s.Mode.Global != nil {
   219  		spec.Mode = &swarmapi.ServiceSpec_Global{
   220  			Global: &swarmapi.GlobalService{},
   221  		}
   222  	} else if s.Mode.Replicated != nil && s.Mode.Replicated.Replicas != nil {
   223  		spec.Mode = &swarmapi.ServiceSpec_Replicated{
   224  			Replicated: &swarmapi.ReplicatedService{Replicas: *s.Mode.Replicated.Replicas},
   225  		}
   226  	} else {
   227  		spec.Mode = &swarmapi.ServiceSpec_Replicated{
   228  			Replicated: &swarmapi.ReplicatedService{Replicas: 1},
   229  		}
   230  	}
   231  
   232  	return spec, nil
   233  }
   234  
   235  func annotationsFromGRPC(ann swarmapi.Annotations) types.Annotations {
   236  	a := types.Annotations{
   237  		Name:   ann.Name,
   238  		Labels: ann.Labels,
   239  	}
   240  
   241  	if a.Labels == nil {
   242  		a.Labels = make(map[string]string)
   243  	}
   244  
   245  	return a
   246  }
   247  
   248  func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequirements {
   249  	var resources *types.ResourceRequirements
   250  	if res != nil {
   251  		resources = &types.ResourceRequirements{}
   252  		if res.Limits != nil {
   253  			resources.Limits = &types.Resources{
   254  				NanoCPUs:    res.Limits.NanoCPUs,
   255  				MemoryBytes: res.Limits.MemoryBytes,
   256  			}
   257  		}
   258  		if res.Reservations != nil {
   259  			resources.Reservations = &types.Resources{
   260  				NanoCPUs:    res.Reservations.NanoCPUs,
   261  				MemoryBytes: res.Reservations.MemoryBytes,
   262  			}
   263  		}
   264  	}
   265  
   266  	return resources
   267  }
   268  
   269  func resourcesToGRPC(res *types.ResourceRequirements) *swarmapi.ResourceRequirements {
   270  	var reqs *swarmapi.ResourceRequirements
   271  	if res != nil {
   272  		reqs = &swarmapi.ResourceRequirements{}
   273  		if res.Limits != nil {
   274  			reqs.Limits = &swarmapi.Resources{
   275  				NanoCPUs:    res.Limits.NanoCPUs,
   276  				MemoryBytes: res.Limits.MemoryBytes,
   277  			}
   278  		}
   279  		if res.Reservations != nil {
   280  			reqs.Reservations = &swarmapi.Resources{
   281  				NanoCPUs:    res.Reservations.NanoCPUs,
   282  				MemoryBytes: res.Reservations.MemoryBytes,
   283  			}
   284  
   285  		}
   286  	}
   287  	return reqs
   288  }
   289  
   290  func restartPolicyFromGRPC(p *swarmapi.RestartPolicy) *types.RestartPolicy {
   291  	var rp *types.RestartPolicy
   292  	if p != nil {
   293  		rp = &types.RestartPolicy{}
   294  
   295  		switch p.Condition {
   296  		case swarmapi.RestartOnNone:
   297  			rp.Condition = types.RestartPolicyConditionNone
   298  		case swarmapi.RestartOnFailure:
   299  			rp.Condition = types.RestartPolicyConditionOnFailure
   300  		case swarmapi.RestartOnAny:
   301  			rp.Condition = types.RestartPolicyConditionAny
   302  		default:
   303  			rp.Condition = types.RestartPolicyConditionAny
   304  		}
   305  
   306  		if p.Delay != nil {
   307  			delay, _ := gogotypes.DurationFromProto(p.Delay)
   308  			rp.Delay = &delay
   309  		}
   310  		if p.Window != nil {
   311  			window, _ := gogotypes.DurationFromProto(p.Window)
   312  			rp.Window = &window
   313  		}
   314  
   315  		rp.MaxAttempts = &p.MaxAttempts
   316  	}
   317  	return rp
   318  }
   319  
   320  func restartPolicyToGRPC(p *types.RestartPolicy) (*swarmapi.RestartPolicy, error) {
   321  	var rp *swarmapi.RestartPolicy
   322  	if p != nil {
   323  		rp = &swarmapi.RestartPolicy{}
   324  
   325  		switch p.Condition {
   326  		case types.RestartPolicyConditionNone:
   327  			rp.Condition = swarmapi.RestartOnNone
   328  		case types.RestartPolicyConditionOnFailure:
   329  			rp.Condition = swarmapi.RestartOnFailure
   330  		case types.RestartPolicyConditionAny:
   331  			rp.Condition = swarmapi.RestartOnAny
   332  		default:
   333  			if string(p.Condition) != "" {
   334  				return nil, fmt.Errorf("invalid RestartCondition: %q", p.Condition)
   335  			}
   336  			rp.Condition = swarmapi.RestartOnAny
   337  		}
   338  
   339  		if p.Delay != nil {
   340  			rp.Delay = gogotypes.DurationProto(*p.Delay)
   341  		}
   342  		if p.Window != nil {
   343  			rp.Window = gogotypes.DurationProto(*p.Window)
   344  		}
   345  		if p.MaxAttempts != nil {
   346  			rp.MaxAttempts = *p.MaxAttempts
   347  
   348  		}
   349  	}
   350  	return rp, nil
   351  }
   352  
   353  func placementFromGRPC(p *swarmapi.Placement) *types.Placement {
   354  	var r *types.Placement
   355  	if p != nil {
   356  		r = &types.Placement{}
   357  		r.Constraints = p.Constraints
   358  	}
   359  
   360  	return r
   361  }
   362  
   363  func driverFromGRPC(p *swarmapi.Driver) *types.Driver {
   364  	if p == nil {
   365  		return nil
   366  	}
   367  
   368  	return &types.Driver{
   369  		Name:    p.Name,
   370  		Options: p.Options,
   371  	}
   372  }
   373  
   374  func driverToGRPC(p *types.Driver) *swarmapi.Driver {
   375  	if p == nil {
   376  		return nil
   377  	}
   378  
   379  	return &swarmapi.Driver{
   380  		Name:    p.Name,
   381  		Options: p.Options,
   382  	}
   383  }