|
|
@@ -295,7 +295,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) {
|
|
|
pc := &tsapi.ProxyClass{
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "custom-metadata"},
|
|
|
Spec: tsapi.ProxyClassSpec{StatefulSet: &tsapi.StatefulSet{
|
|
|
- Labels: map[string]string{"foo": "bar"},
|
|
|
+ Labels: tsapi.Labels{"foo": "bar"},
|
|
|
Annotations: map[string]string{"bar.io/foo": "some-val"},
|
|
|
Pod: &tsapi.Pod{Annotations: map[string]string{"foo.io/bar": "some-val"}}}},
|
|
|
}
|
|
|
@@ -424,12 +424,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) {
|
|
|
func TestTailscaleIngressWithServiceMonitor(t *testing.T) {
|
|
|
pc := &tsapi.ProxyClass{
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "metrics", Generation: 1},
|
|
|
- Spec: tsapi.ProxyClassSpec{
|
|
|
- Metrics: &tsapi.Metrics{
|
|
|
- Enable: true,
|
|
|
- ServiceMonitor: &tsapi.ServiceMonitor{Enable: true},
|
|
|
- },
|
|
|
- },
|
|
|
+ Spec: tsapi.ProxyClassSpec{},
|
|
|
Status: tsapi.ProxyClassStatus{
|
|
|
Conditions: []metav1.Condition{{
|
|
|
Status: metav1.ConditionTrue,
|
|
|
@@ -437,32 +432,6 @@ func TestTailscaleIngressWithServiceMonitor(t *testing.T) {
|
|
|
ObservedGeneration: 1,
|
|
|
}}},
|
|
|
}
|
|
|
- crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}}
|
|
|
- tsIngressClass := &networkingv1.IngressClass{ObjectMeta: metav1.ObjectMeta{Name: "tailscale"}, Spec: networkingv1.IngressClassSpec{Controller: "tailscale.com/ts-ingress"}}
|
|
|
- fc := fake.NewClientBuilder().
|
|
|
- WithScheme(tsapi.GlobalScheme).
|
|
|
- WithObjects(pc, tsIngressClass).
|
|
|
- WithStatusSubresource(pc).
|
|
|
- Build()
|
|
|
- ft := &fakeTSClient{}
|
|
|
- fakeTsnetServer := &fakeTSNetServer{certDomains: []string{"foo.com"}}
|
|
|
- zl, err := zap.NewDevelopment()
|
|
|
- if err != nil {
|
|
|
- t.Fatal(err)
|
|
|
- }
|
|
|
- ingR := &IngressReconciler{
|
|
|
- Client: fc,
|
|
|
- ssr: &tailscaleSTSReconciler{
|
|
|
- Client: fc,
|
|
|
- tsClient: ft,
|
|
|
- tsnetServer: fakeTsnetServer,
|
|
|
- defaultTags: []string{"tag:k8s"},
|
|
|
- operatorNamespace: "operator-ns",
|
|
|
- proxyImage: "tailscale/tailscale",
|
|
|
- },
|
|
|
- logger: zl.Sugar(),
|
|
|
- }
|
|
|
- // 1. Enable metrics- expect metrics Service to be created
|
|
|
ing := &networkingv1.Ingress{
|
|
|
TypeMeta: metav1.TypeMeta{Kind: "Ingress", APIVersion: "networking.k8s.io/v1"},
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
@@ -491,8 +460,7 @@ func TestTailscaleIngressWithServiceMonitor(t *testing.T) {
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
- mustCreate(t, fc, ing)
|
|
|
- mustCreate(t, fc, &corev1.Service{
|
|
|
+ svc := &corev1.Service{
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
Name: "test",
|
|
|
Namespace: "default",
|
|
|
@@ -504,11 +472,38 @@ func TestTailscaleIngressWithServiceMonitor(t *testing.T) {
|
|
|
Name: "http"},
|
|
|
},
|
|
|
},
|
|
|
- })
|
|
|
-
|
|
|
+ }
|
|
|
+ crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}}
|
|
|
+ tsIngressClass := &networkingv1.IngressClass{ObjectMeta: metav1.ObjectMeta{Name: "tailscale"}, Spec: networkingv1.IngressClassSpec{Controller: "tailscale.com/ts-ingress"}}
|
|
|
+ fc := fake.NewClientBuilder().
|
|
|
+ WithScheme(tsapi.GlobalScheme).
|
|
|
+ WithObjects(pc, tsIngressClass, ing, svc).
|
|
|
+ WithStatusSubresource(pc).
|
|
|
+ Build()
|
|
|
+ ft := &fakeTSClient{}
|
|
|
+ fakeTsnetServer := &fakeTSNetServer{certDomains: []string{"foo.com"}}
|
|
|
+ zl, err := zap.NewDevelopment()
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ ingR := &IngressReconciler{
|
|
|
+ Client: fc,
|
|
|
+ ssr: &tailscaleSTSReconciler{
|
|
|
+ Client: fc,
|
|
|
+ tsClient: ft,
|
|
|
+ tsnetServer: fakeTsnetServer,
|
|
|
+ defaultTags: []string{"tag:k8s"},
|
|
|
+ operatorNamespace: "operator-ns",
|
|
|
+ proxyImage: "tailscale/tailscale",
|
|
|
+ },
|
|
|
+ logger: zl.Sugar(),
|
|
|
+ }
|
|
|
expectReconciled(t, ingR, "default", "test")
|
|
|
-
|
|
|
fullName, shortName := findGenName(t, fc, "default", "test", "ingress")
|
|
|
+ serveConfig := &ipn.ServeConfig{
|
|
|
+ TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}},
|
|
|
+ Web: map[ipn.HostPort]*ipn.WebServerConfig{"${TS_CERT_DOMAIN}:443": {Handlers: map[string]*ipn.HTTPHandler{"/": {Proxy: "http://1.2.3.4:8080/"}}}},
|
|
|
+ }
|
|
|
opts := configOpts{
|
|
|
stsName: shortName,
|
|
|
secretName: fullName,
|
|
|
@@ -517,27 +512,51 @@ func TestTailscaleIngressWithServiceMonitor(t *testing.T) {
|
|
|
parentType: "ingress",
|
|
|
hostname: "default-test",
|
|
|
app: kubetypes.AppIngressResource,
|
|
|
- enableMetrics: true,
|
|
|
namespaced: true,
|
|
|
proxyType: proxyTypeIngressResource,
|
|
|
+ serveConfig: serveConfig,
|
|
|
+ resourceVersion: "1",
|
|
|
}
|
|
|
- serveConfig := &ipn.ServeConfig{
|
|
|
- TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}},
|
|
|
- Web: map[ipn.HostPort]*ipn.WebServerConfig{"${TS_CERT_DOMAIN}:443": {Handlers: map[string]*ipn.HTTPHandler{"/": {Proxy: "http://1.2.3.4:8080/"}}}},
|
|
|
- }
|
|
|
- opts.serveConfig = serveConfig
|
|
|
|
|
|
- expectEqual(t, fc, expectedSecret(t, fc, opts), nil)
|
|
|
- expectEqual(t, fc, expectedHeadlessService(shortName, "ingress"), nil)
|
|
|
+ // 1. Enable metrics- expect metrics Service to be created
|
|
|
+ mustUpdate(t, fc, "", "metrics", func(proxyClass *tsapi.ProxyClass) {
|
|
|
+ proxyClass.Spec.Metrics = &tsapi.Metrics{Enable: true}
|
|
|
+ })
|
|
|
+ opts.enableMetrics = true
|
|
|
+
|
|
|
+ expectReconciled(t, ingR, "default", "test")
|
|
|
+
|
|
|
expectEqual(t, fc, expectedMetricsService(opts), nil)
|
|
|
- expectEqual(t, fc, expectedSTSUserspace(t, fc, opts), removeHashAnnotation)
|
|
|
+
|
|
|
// 2. Enable ServiceMonitor - should not error when there is no ServiceMonitor CRD in cluster
|
|
|
mustUpdate(t, fc, "", "metrics", func(pc *tsapi.ProxyClass) {
|
|
|
- pc.Spec.Metrics.ServiceMonitor = &tsapi.ServiceMonitor{Enable: true}
|
|
|
+ pc.Spec.Metrics.ServiceMonitor = &tsapi.ServiceMonitor{Enable: true, Labels: tsapi.Labels{"foo": "bar"}}
|
|
|
})
|
|
|
expectReconciled(t, ingR, "default", "test")
|
|
|
+ expectEqual(t, fc, expectedMetricsService(opts), nil)
|
|
|
+
|
|
|
// 3. Create ServiceMonitor CRD and reconcile- ServiceMonitor should get created
|
|
|
mustCreate(t, fc, crd)
|
|
|
expectReconciled(t, ingR, "default", "test")
|
|
|
+ opts.serviceMonitorLabels = tsapi.Labels{"foo": "bar"}
|
|
|
+ expectEqual(t, fc, expectedMetricsService(opts), nil)
|
|
|
+ expectEqualUnstructured(t, fc, expectedServiceMonitor(t, opts))
|
|
|
+
|
|
|
+ // 4. Update ServiceMonitor CRD and reconcile- ServiceMonitor should get updated
|
|
|
+ mustUpdate(t, fc, pc.Namespace, pc.Name, func(proxyClass *tsapi.ProxyClass) {
|
|
|
+ proxyClass.Spec.Metrics.ServiceMonitor.Labels = nil
|
|
|
+ })
|
|
|
+ expectReconciled(t, ingR, "default", "test")
|
|
|
+ opts.serviceMonitorLabels = nil
|
|
|
+ opts.resourceVersion = "2"
|
|
|
+ expectEqual(t, fc, expectedMetricsService(opts), nil)
|
|
|
expectEqualUnstructured(t, fc, expectedServiceMonitor(t, opts))
|
|
|
+
|
|
|
+ // 5. Disable metrics - metrics resources should get deleted.
|
|
|
+ mustUpdate(t, fc, pc.Namespace, pc.Name, func(proxyClass *tsapi.ProxyClass) {
|
|
|
+ proxyClass.Spec.Metrics = nil
|
|
|
+ })
|
|
|
+ expectReconciled(t, ingR, "default", "test")
|
|
|
+ expectMissing[corev1.Service](t, fc, "operator-ns", metricsResourceName(shortName))
|
|
|
+ // ServiceMonitor gets garbage collected when the Service is deleted - we cannot test that here.
|
|
|
}
|