2018-03-13 13:31:44 -04:00
|
|
|
package kubernetes
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2019-10-30 05:53:39 -04:00
|
|
|
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
2018-12-20 02:45:35 -05:00
|
|
|
"github.com/docker/compose-on-kubernetes/api/labels"
|
2018-03-13 13:31:44 -04:00
|
|
|
"github.com/docker/docker/api/types/swarm"
|
2020-02-22 12:12:14 -05:00
|
|
|
"gotest.tools/v3/assert"
|
2018-03-13 13:31:44 -04:00
|
|
|
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
|
|
|
apiv1 "k8s.io/api/core/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
apimachineryTypes "k8s.io/apimachinery/pkg/types"
|
|
|
|
apimachineryUtil "k8s.io/apimachinery/pkg/util/intstr"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestReplicasConversionNeedsAService(t *testing.T) {
|
|
|
|
replicas := appsv1beta2.ReplicaSetList{
|
|
|
|
Items: []appsv1beta2.ReplicaSet{makeReplicaSet("unknown", 0, 0)},
|
|
|
|
}
|
|
|
|
services := apiv1.ServiceList{}
|
2019-10-23 18:16:35 -04:00
|
|
|
_, err := convertToServices(&replicas, &appsv1beta2.DaemonSetList{}, &services)
|
2018-03-13 13:31:44 -04:00
|
|
|
assert.ErrorContains(t, err, "could not find service")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKubernetesServiceToSwarmServiceConversion(t *testing.T) {
|
|
|
|
testCases := []struct {
|
2019-10-23 18:16:35 -04:00
|
|
|
doc string
|
2018-03-13 13:31:44 -04:00
|
|
|
replicas *appsv1beta2.ReplicaSetList
|
|
|
|
services *apiv1.ServiceList
|
|
|
|
expectedServices []swarm.Service
|
|
|
|
}{
|
|
|
|
{
|
2019-10-23 18:16:35 -04:00
|
|
|
doc: "Match replicas with headless stack services",
|
|
|
|
replicas: &appsv1beta2.ReplicaSetList{
|
2018-03-13 13:31:44 -04:00
|
|
|
Items: []appsv1beta2.ReplicaSet{
|
|
|
|
makeReplicaSet("service1", 2, 5),
|
|
|
|
makeReplicaSet("service2", 3, 3),
|
|
|
|
},
|
|
|
|
},
|
2019-10-23 18:16:35 -04:00
|
|
|
services: &apiv1.ServiceList{
|
2018-03-13 13:31:44 -04:00
|
|
|
Items: []apiv1.Service{
|
|
|
|
makeKubeService("service1", "stack", "uid1", apiv1.ServiceTypeClusterIP, nil),
|
|
|
|
makeKubeService("service2", "stack", "uid2", apiv1.ServiceTypeClusterIP, nil),
|
|
|
|
makeKubeService("service3", "other-stack", "uid2", apiv1.ServiceTypeClusterIP, nil),
|
|
|
|
},
|
|
|
|
},
|
2019-10-23 18:16:35 -04:00
|
|
|
expectedServices: []swarm.Service{
|
2019-10-30 05:53:39 -04:00
|
|
|
makeSwarmService(t, "stack_service1", "uid1", ReplicatedService(5), ServiceStatus(5, 2)),
|
|
|
|
makeSwarmService(t, "stack_service2", "uid2", ReplicatedService(3), ServiceStatus(3, 3)),
|
2018-03-13 13:31:44 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2019-10-23 18:16:35 -04:00
|
|
|
doc: "Headless service and LoadBalancer Service are tied to the same Swarm service",
|
|
|
|
replicas: &appsv1beta2.ReplicaSetList{
|
2018-03-13 13:31:44 -04:00
|
|
|
Items: []appsv1beta2.ReplicaSet{
|
|
|
|
makeReplicaSet("service", 1, 1),
|
|
|
|
},
|
|
|
|
},
|
2019-10-23 18:16:35 -04:00
|
|
|
services: &apiv1.ServiceList{
|
2018-03-13 13:31:44 -04:00
|
|
|
Items: []apiv1.Service{
|
|
|
|
makeKubeService("service", "stack", "uid1", apiv1.ServiceTypeClusterIP, nil),
|
|
|
|
makeKubeService("service-published", "stack", "uid2", apiv1.ServiceTypeLoadBalancer, []apiv1.ServicePort{
|
|
|
|
{
|
|
|
|
Port: 80,
|
|
|
|
TargetPort: apimachineryUtil.FromInt(80),
|
|
|
|
Protocol: apiv1.ProtocolTCP,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2019-10-23 18:16:35 -04:00
|
|
|
expectedServices: []swarm.Service{
|
|
|
|
makeSwarmService(t, "stack_service", "uid1",
|
2019-10-30 05:53:39 -04:00
|
|
|
ReplicatedService(1),
|
|
|
|
ServiceStatus(1, 1),
|
|
|
|
withPort(swarm.PortConfig{
|
2018-03-13 13:31:44 -04:00
|
|
|
PublishMode: swarm.PortConfigPublishModeIngress,
|
|
|
|
PublishedPort: 80,
|
|
|
|
TargetPort: 80,
|
|
|
|
Protocol: swarm.PortConfigProtocolTCP,
|
2019-10-23 18:16:35 -04:00
|
|
|
}),
|
|
|
|
),
|
2018-03-13 13:31:44 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2019-10-23 18:16:35 -04:00
|
|
|
doc: "Headless service and NodePort Service are tied to the same Swarm service",
|
|
|
|
replicas: &appsv1beta2.ReplicaSetList{
|
2018-03-13 13:31:44 -04:00
|
|
|
Items: []appsv1beta2.ReplicaSet{
|
|
|
|
makeReplicaSet("service", 1, 1),
|
|
|
|
},
|
|
|
|
},
|
2019-10-23 18:16:35 -04:00
|
|
|
services: &apiv1.ServiceList{
|
2018-03-13 13:31:44 -04:00
|
|
|
Items: []apiv1.Service{
|
|
|
|
makeKubeService("service", "stack", "uid1", apiv1.ServiceTypeClusterIP, nil),
|
|
|
|
makeKubeService("service-random-ports", "stack", "uid2", apiv1.ServiceTypeNodePort, []apiv1.ServicePort{
|
|
|
|
{
|
|
|
|
Port: 35666,
|
|
|
|
TargetPort: apimachineryUtil.FromInt(80),
|
|
|
|
Protocol: apiv1.ProtocolTCP,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2019-10-23 18:16:35 -04:00
|
|
|
expectedServices: []swarm.Service{
|
|
|
|
makeSwarmService(t, "stack_service", "uid1",
|
2019-10-30 05:53:39 -04:00
|
|
|
ReplicatedService(1),
|
|
|
|
ServiceStatus(1, 1),
|
2019-10-23 18:16:35 -04:00
|
|
|
withPort(swarm.PortConfig{
|
2018-03-13 13:31:44 -04:00
|
|
|
PublishMode: swarm.PortConfigPublishModeHost,
|
|
|
|
PublishedPort: 35666,
|
|
|
|
TargetPort: 80,
|
|
|
|
Protocol: swarm.PortConfigProtocolTCP,
|
2019-10-23 18:16:35 -04:00
|
|
|
}),
|
|
|
|
),
|
2018-03-13 13:31:44 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
2019-10-23 18:16:35 -04:00
|
|
|
tc := tc
|
|
|
|
t.Run(tc.doc, func(t *testing.T) {
|
|
|
|
swarmServices, err := convertToServices(tc.replicas, &appsv1beta2.DaemonSetList{}, tc.services)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.DeepEqual(t, tc.expectedServices, swarmServices)
|
|
|
|
})
|
2018-03-13 13:31:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeReplicaSet(service string, available, replicas int32) appsv1beta2.ReplicaSet {
|
|
|
|
return appsv1beta2.ReplicaSet{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Labels: map[string]string{
|
|
|
|
labels.ForServiceName: service,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Spec: appsv1beta2.ReplicaSetSpec{
|
|
|
|
Template: apiv1.PodTemplateSpec{
|
|
|
|
Spec: apiv1.PodSpec{
|
|
|
|
Containers: []apiv1.Container{
|
|
|
|
{
|
|
|
|
Image: "image",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: appsv1beta2.ReplicaSetStatus{
|
|
|
|
AvailableReplicas: available,
|
|
|
|
Replicas: replicas,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeKubeService(service, stack, uid string, serviceType apiv1.ServiceType, ports []apiv1.ServicePort) apiv1.Service {
|
|
|
|
return apiv1.Service{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Labels: map[string]string{
|
|
|
|
labels.ForStackName: stack,
|
|
|
|
},
|
|
|
|
Name: service,
|
|
|
|
UID: apimachineryTypes.UID(uid),
|
|
|
|
},
|
|
|
|
Spec: apiv1.ServiceSpec{
|
|
|
|
Type: serviceType,
|
|
|
|
Ports: ports,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-30 05:53:39 -04:00
|
|
|
// TODO convertToServices currently doesn't set swarm.EndpointSpec.Ports
|
2019-10-23 18:16:35 -04:00
|
|
|
func withPort(port swarm.PortConfig) func(*swarm.Service) {
|
|
|
|
return func(service *swarm.Service) {
|
|
|
|
if service.Endpoint.Ports == nil {
|
|
|
|
service.Endpoint.Ports = make([]swarm.PortConfig, 0)
|
|
|
|
}
|
|
|
|
service.Endpoint.Ports = append(service.Endpoint.Ports, port)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-30 05:53:39 -04:00
|
|
|
func makeSwarmService(t *testing.T, name, id string, opts ...func(*swarm.Service)) swarm.Service {
|
2019-10-23 18:16:35 -04:00
|
|
|
t.Helper()
|
2019-10-30 05:53:39 -04:00
|
|
|
options := []func(*swarm.Service){ServiceID(id), ServiceName(name), ServiceImage("image")}
|
|
|
|
options = append(options, opts...)
|
|
|
|
return *Service(options...)
|
2018-03-13 13:31:44 -04:00
|
|
|
}
|