-
Notifications
You must be signed in to change notification settings - Fork 371
/
servicesync.go
145 lines (125 loc) · 5.01 KB
/
servicesync.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package servicesync
import (
"context"
"time"
"github.com/loft-sh/vcluster/pkg/util/translate"
"github.com/loft-sh/vcluster/test/framework"
"github.com/onsi/ginkgo/v2"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
)
var _ = ginkgo.Describe("map services from host to virtual cluster and vice versa", func() {
var (
f *framework.Framework
)
ginkgo.JustBeforeEach(func() {
// use default framework
f = framework.DefaultFramework
})
ginkgo.It("Test service mapping", func() {
ctx := f.Context
// make sure physical service doesn't exist initially
_, err := f.HostClient.CoreV1().Services(f.VclusterNamespace).Get(ctx, "test", metav1.GetOptions{})
framework.ExpectError(err)
_, err = f.HostClient.CoreV1().Services("test").Get(ctx, "test", metav1.GetOptions{})
framework.ExpectError(err)
// make sure virtual service doesn't exist initially
_, err = f.VclusterClient.CoreV1().Services("default").Get(ctx, "test", metav1.GetOptions{})
framework.ExpectError(err)
_, err = f.VclusterClient.CoreV1().Services("test").Get(ctx, "test", metav1.GetOptions{})
framework.ExpectError(err)
// physical -> virtual
testMapping(ctx, f.HostClient, "test", "test", f.VclusterClient, "default", "test", true)
// virtual -> physical
testMapping(ctx, f.VclusterClient, "test", "test", f.HostClient, f.VclusterNamespace, "test", f.MultiNamespaceMode)
})
})
func testMapping(ctx context.Context, fromClient kubernetes.Interface, fromNamespace, fromName string, toClient kubernetes.Interface, toNamespace, toName string, checkEndpoints bool) {
// create physical service
_, _ = fromClient.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: fromName}}, metav1.CreateOptions{})
fromService, err := fromClient.CoreV1().Services(fromNamespace).Create(ctx, &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: fromName,
Namespace: fromNamespace,
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
"test": "test",
},
Ports: []corev1.ServicePort{
{
Name: "custom",
Port: 8080,
Protocol: corev1.ProtocolTCP,
},
},
},
}, metav1.CreateOptions{})
framework.ExpectNoError(err)
// check endpoints?
if checkEndpoints {
// wait for vcluster service
var (
toEndpoints *corev1.Endpoints
toService *corev1.Service
)
waitErr := wait.PollUntilContextTimeout(ctx, time.Millisecond*100, time.Second*10, true, func(ctx context.Context) (done bool, err error) {
toService, err = toClient.CoreV1().Services(toNamespace).Get(ctx, toName, metav1.GetOptions{})
if err != nil {
return false, nil
}
toEndpoints, err = toClient.CoreV1().Endpoints(toNamespace).Get(ctx, toName, metav1.GetOptions{})
if err != nil {
return false, nil
}
return true, nil
})
framework.ExpectNoError(err)
framework.ExpectNoError(waitErr)
// check if endpoints are correct
framework.ExpectEqual(len(toEndpoints.Subsets), 1)
framework.ExpectEqual(len(toEndpoints.Subsets[0].Addresses), 1)
framework.ExpectEqual(toEndpoints.Subsets[0].Addresses[0].IP, fromService.Spec.ClusterIP)
framework.ExpectEqual(len(toService.Spec.Ports), 1)
framework.ExpectEqual(toService.Spec.Ports[0].Name, "custom")
framework.ExpectEqual(toService.Spec.Ports[0].Port, int32(8080))
} else {
// wait for vcluster service
var toService *corev1.Service
waitErr := wait.PollUntilContextTimeout(ctx, time.Millisecond*100, time.Second*10, true, func(ctx context.Context) (done bool, err error) {
toService, err = toClient.CoreV1().Services(toNamespace).Get(ctx, toName, metav1.GetOptions{})
if err != nil {
return false, nil
}
return true, nil
})
framework.ExpectNoError(err)
framework.ExpectNoError(waitErr)
// check if service is correct
framework.ExpectEqual(len(toService.Spec.Ports), 1)
framework.ExpectEqual(toService.Spec.Ports[0].Name, "custom")
framework.ExpectEqual(toService.Spec.Ports[0].Port, int32(8080))
framework.ExpectEqual(len(toService.Spec.Selector), 3)
framework.ExpectEqual(toService.Spec.Selector[translate.NamespaceLabel], fromNamespace)
framework.ExpectEqual(toService.Spec.Selector[translate.MarkerLabel], translate.Suffix)
framework.ExpectEqual(toService.Spec.Selector[translate.ConvertLabelKeyWithPrefix(translate.LabelPrefix, "test")], "test")
}
// check service deletion
err = fromClient.CoreV1().Services(fromNamespace).Delete(ctx, fromService.Name, metav1.DeleteOptions{})
framework.ExpectNoError(err)
// verify service gets deleted in vcluster
waitErr := wait.PollUntilContextTimeout(ctx, time.Millisecond*100, time.Second*10, true, func(ctx context.Context) (done bool, err error) {
_, err = toClient.CoreV1().Services(toNamespace).Get(ctx, toName, metav1.GetOptions{})
if err == nil {
return false, nil
}
_, err = toClient.CoreV1().Endpoints(toNamespace).Get(ctx, toName, metav1.GetOptions{})
if err == nil {
return false, nil
}
return true, nil
})
framework.ExpectNoError(waitErr)
}