github.com/AliyunContainerService/cli@v0.0.0-20181009023821-814ced4b30d0/cli/command/stack/kubernetes/conversion_test.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/docker/cli/cli/command/formatter"
     7  	"github.com/docker/cli/kubernetes/labels"
     8  	"github.com/docker/docker/api/types/swarm"
     9  	"gotest.tools/assert"
    10  	appsv1beta2 "k8s.io/api/apps/v1beta2"
    11  	apiv1 "k8s.io/api/core/v1"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	apimachineryTypes "k8s.io/apimachinery/pkg/types"
    14  	apimachineryUtil "k8s.io/apimachinery/pkg/util/intstr"
    15  )
    16  
    17  func TestReplicasConversionNeedsAService(t *testing.T) {
    18  	replicas := appsv1beta2.ReplicaSetList{
    19  		Items: []appsv1beta2.ReplicaSet{makeReplicaSet("unknown", 0, 0)},
    20  	}
    21  	services := apiv1.ServiceList{}
    22  	_, _, err := convertToServices(&replicas, &appsv1beta2.DaemonSetList{}, &services)
    23  	assert.ErrorContains(t, err, "could not find service")
    24  }
    25  
    26  func TestKubernetesServiceToSwarmServiceConversion(t *testing.T) {
    27  	testCases := []struct {
    28  		replicas         *appsv1beta2.ReplicaSetList
    29  		services         *apiv1.ServiceList
    30  		expectedServices []swarm.Service
    31  		expectedListInfo map[string]formatter.ServiceListInfo
    32  	}{
    33  		// Match replicas with headless stack services
    34  		{
    35  			&appsv1beta2.ReplicaSetList{
    36  				Items: []appsv1beta2.ReplicaSet{
    37  					makeReplicaSet("service1", 2, 5),
    38  					makeReplicaSet("service2", 3, 3),
    39  				},
    40  			},
    41  			&apiv1.ServiceList{
    42  				Items: []apiv1.Service{
    43  					makeKubeService("service1", "stack", "uid1", apiv1.ServiceTypeClusterIP, nil),
    44  					makeKubeService("service2", "stack", "uid2", apiv1.ServiceTypeClusterIP, nil),
    45  					makeKubeService("service3", "other-stack", "uid2", apiv1.ServiceTypeClusterIP, nil),
    46  				},
    47  			},
    48  			[]swarm.Service{
    49  				makeSwarmService("stack_service1", "uid1", nil),
    50  				makeSwarmService("stack_service2", "uid2", nil),
    51  			},
    52  			map[string]formatter.ServiceListInfo{
    53  				"uid1": {Mode: "replicated", Replicas: "2/5"},
    54  				"uid2": {Mode: "replicated", Replicas: "3/3"},
    55  			},
    56  		},
    57  		// Headless service and LoadBalancer Service are tied to the same Swarm service
    58  		{
    59  			&appsv1beta2.ReplicaSetList{
    60  				Items: []appsv1beta2.ReplicaSet{
    61  					makeReplicaSet("service", 1, 1),
    62  				},
    63  			},
    64  			&apiv1.ServiceList{
    65  				Items: []apiv1.Service{
    66  					makeKubeService("service", "stack", "uid1", apiv1.ServiceTypeClusterIP, nil),
    67  					makeKubeService("service-published", "stack", "uid2", apiv1.ServiceTypeLoadBalancer, []apiv1.ServicePort{
    68  						{
    69  							Port:       80,
    70  							TargetPort: apimachineryUtil.FromInt(80),
    71  							Protocol:   apiv1.ProtocolTCP,
    72  						},
    73  					}),
    74  				},
    75  			},
    76  			[]swarm.Service{
    77  				makeSwarmService("stack_service", "uid1", []swarm.PortConfig{
    78  					{
    79  						PublishMode:   swarm.PortConfigPublishModeIngress,
    80  						PublishedPort: 80,
    81  						TargetPort:    80,
    82  						Protocol:      swarm.PortConfigProtocolTCP,
    83  					},
    84  				}),
    85  			},
    86  			map[string]formatter.ServiceListInfo{
    87  				"uid1": {Mode: "replicated", Replicas: "1/1"},
    88  			},
    89  		},
    90  		// Headless service and NodePort Service are tied to the same Swarm service
    91  
    92  		{
    93  			&appsv1beta2.ReplicaSetList{
    94  				Items: []appsv1beta2.ReplicaSet{
    95  					makeReplicaSet("service", 1, 1),
    96  				},
    97  			},
    98  			&apiv1.ServiceList{
    99  				Items: []apiv1.Service{
   100  					makeKubeService("service", "stack", "uid1", apiv1.ServiceTypeClusterIP, nil),
   101  					makeKubeService("service-random-ports", "stack", "uid2", apiv1.ServiceTypeNodePort, []apiv1.ServicePort{
   102  						{
   103  							Port:       35666,
   104  							TargetPort: apimachineryUtil.FromInt(80),
   105  							Protocol:   apiv1.ProtocolTCP,
   106  						},
   107  					}),
   108  				},
   109  			},
   110  			[]swarm.Service{
   111  				makeSwarmService("stack_service", "uid1", []swarm.PortConfig{
   112  					{
   113  						PublishMode:   swarm.PortConfigPublishModeHost,
   114  						PublishedPort: 35666,
   115  						TargetPort:    80,
   116  						Protocol:      swarm.PortConfigProtocolTCP,
   117  					},
   118  				}),
   119  			},
   120  			map[string]formatter.ServiceListInfo{
   121  				"uid1": {Mode: "replicated", Replicas: "1/1"},
   122  			},
   123  		},
   124  	}
   125  
   126  	for _, tc := range testCases {
   127  		swarmServices, listInfo, err := convertToServices(tc.replicas, &appsv1beta2.DaemonSetList{}, tc.services)
   128  		assert.NilError(t, err)
   129  		assert.DeepEqual(t, tc.expectedServices, swarmServices)
   130  		assert.DeepEqual(t, tc.expectedListInfo, listInfo)
   131  	}
   132  }
   133  
   134  func makeReplicaSet(service string, available, replicas int32) appsv1beta2.ReplicaSet {
   135  	return appsv1beta2.ReplicaSet{
   136  		ObjectMeta: metav1.ObjectMeta{
   137  			Labels: map[string]string{
   138  				labels.ForServiceName: service,
   139  			},
   140  		},
   141  		Spec: appsv1beta2.ReplicaSetSpec{
   142  			Template: apiv1.PodTemplateSpec{
   143  				Spec: apiv1.PodSpec{
   144  					Containers: []apiv1.Container{
   145  						{
   146  							Image: "image",
   147  						},
   148  					},
   149  				},
   150  			},
   151  		},
   152  		Status: appsv1beta2.ReplicaSetStatus{
   153  			AvailableReplicas: available,
   154  			Replicas:          replicas,
   155  		},
   156  	}
   157  }
   158  
   159  func makeKubeService(service, stack, uid string, serviceType apiv1.ServiceType, ports []apiv1.ServicePort) apiv1.Service {
   160  	return apiv1.Service{
   161  		ObjectMeta: metav1.ObjectMeta{
   162  			Labels: map[string]string{
   163  				labels.ForStackName: stack,
   164  			},
   165  			Name: service,
   166  			UID:  apimachineryTypes.UID(uid),
   167  		},
   168  		Spec: apiv1.ServiceSpec{
   169  			Type:  serviceType,
   170  			Ports: ports,
   171  		},
   172  	}
   173  }
   174  
   175  func makeSwarmService(service, id string, ports []swarm.PortConfig) swarm.Service {
   176  	return swarm.Service{
   177  		ID: id,
   178  		Spec: swarm.ServiceSpec{
   179  			Annotations: swarm.Annotations{
   180  				Name: service,
   181  			},
   182  			TaskTemplate: swarm.TaskSpec{
   183  				ContainerSpec: &swarm.ContainerSpec{
   184  					Image: "image",
   185  				},
   186  			},
   187  		},
   188  		Endpoint: swarm.Endpoint{
   189  			Ports: ports,
   190  		},
   191  	}
   192  }