cmd/k8s-operator: use correct tailnet client for L7 & L3 ingresses (#18749)

* cmd/k8s-operator: use correct tailnet client for L7 & L3 ingresses

This commit fixes a bug when using multi-tailnet within the operator
to spin up L7 & L3 ingresses where the client used to create the
tailscale services was not switching depending on the tailnet used
by the proxygroup backing the service/ingress.

Updates: https://github.com/tailscale/corp/issues/34561

Signed-off-by: David Bond <davidsbond93@gmail.com>

* cmd/k8s-operator: adding server url to proxygroups when a custom tailnet has been specified

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
(cherry picked from commit 3b21ac5504e713e32dfcd43d9ee21e7e712ac200)

---------

Signed-off-by: David Bond <davidsbond93@gmail.com>
Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
Co-authored-by: chaosinthecrd <tom@tmlabs.co.uk>
This commit is contained in:
David Bond
2026-03-10 10:33:55 +00:00
committed by GitHub
parent 0023f1a969
commit 9522619031
12 changed files with 403 additions and 322 deletions
+63 -42
View File
@@ -28,7 +28,6 @@ import (
"tailscale.com/internal/client/tailscale"
"tailscale.com/ipn"
"tailscale.com/ipn/ipnstate"
tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes"
@@ -562,16 +561,18 @@ func TestIngressPGReconciler_HTTPEndpoint(t *testing.T) {
}
// Add the Tailscale Service to prefs to have the Ingress recognised as ready.
mustCreate(t, fc, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-pg-0",
Namespace: "operator-ns",
Labels: pgSecretLabels("test-pg", kubetypes.LabelSecretTypeState),
},
Data: map[string][]byte{
"_current-profile": []byte("profile-foo"),
"profile-foo": []byte(`{"AdvertiseServices":["svc:my-svc"],"Config":{"NodeID":"node-foo"}}`),
},
mustUpdate(t, fc, "operator-ns", "test-pg-0", func(o *corev1.Secret) {
var p prefs
var err error
if err = json.Unmarshal(o.Data["test"], &p); err != nil {
t.Errorf("failed to unmarshal preferences: %v", err)
}
p.AdvertiseServices = []string{"svc:my-svc"}
o.Data["test"], err = json.Marshal(p)
if err != nil {
t.Errorf("failed to marshal preferences: %v", err)
}
})
// Reconcile and re-fetch Ingress.
@@ -685,17 +686,19 @@ func TestIngressPGReconciler_HTTPRedirect(t *testing.T) {
t.Fatal(err)
}
// Add the Tailscale Service to prefs to have the Ingress recognised as ready
mustCreate(t, fc, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-pg-0",
Namespace: "operator-ns",
Labels: pgSecretLabels("test-pg", kubetypes.LabelSecretTypeState),
},
Data: map[string][]byte{
"_current-profile": []byte("profile-foo"),
"profile-foo": []byte(`{"AdvertiseServices":["svc:my-svc"],"Config":{"NodeID":"node-foo"}}`),
},
// Add the Tailscale Service to prefs to have the Ingress recognised as ready.
mustUpdate(t, fc, "operator-ns", "test-pg-0", func(o *corev1.Secret) {
var p prefs
var err error
if err = json.Unmarshal(o.Data["test"], &p); err != nil {
t.Errorf("failed to unmarshal preferences: %v", err)
}
p.AdvertiseServices = []string{"svc:my-svc"}
o.Data["test"], err = json.Marshal(p)
if err != nil {
t.Errorf("failed to marshal preferences: %v", err)
}
})
// Reconcile and re-fetch Ingress
@@ -818,17 +821,19 @@ func TestIngressPGReconciler_HTTPEndpointAndRedirectConflict(t *testing.T) {
t.Fatal(err)
}
// Add the Tailscale Service to prefs to have the Ingress recognised as ready
mustCreate(t, fc, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-pg-0",
Namespace: "operator-ns",
Labels: pgSecretLabels("test-pg", kubetypes.LabelSecretTypeState),
},
Data: map[string][]byte{
"_current-profile": []byte("profile-foo"),
"profile-foo": []byte(`{"AdvertiseServices":["svc:my-svc"],"Config":{"NodeID":"node-foo"}}`),
},
// Add the Tailscale Service to prefs to have the Ingress recognised as ready.
mustUpdate(t, fc, "operator-ns", "test-pg-0", func(o *corev1.Secret) {
var p prefs
var err error
if err = json.Unmarshal(o.Data["test"], &p); err != nil {
t.Errorf("failed to unmarshal preferences: %v", err)
}
p.AdvertiseServices = []string{"svc:my-svc"}
o.Data["test"], err = json.Marshal(p)
if err != nil {
t.Errorf("failed to marshal preferences: %v", err)
}
})
// Reconcile and re-fetch Ingress
@@ -1109,6 +1114,7 @@ func verifyTailscaledConfig(t *testing.T, fc client.Client, pgName string, expec
func createPGResources(t *testing.T, fc client.Client, pgName string) {
t.Helper()
// Pre-create the ProxyGroup
pg := &tsapi.ProxyGroup{
ObjectMeta: metav1.ObjectMeta{
@@ -1145,6 +1151,30 @@ func createPGResources(t *testing.T, fc client.Client, pgName string) {
},
}
mustCreate(t, fc, pgCfgSecret)
pr := prefs{}
pr.Config.UserProfile.LoginName = "test.ts.net"
pr.Config.NodeID = "test"
p, err := json.Marshal(pr)
if err != nil {
t.Fatalf("marshaling prefs: %v", err)
}
// Pre-create a state secret for the ProxyGroup
pgStateSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: pgStateSecretName(pgName, 0),
Namespace: "operator-ns",
Labels: pgSecretLabels(pgName, kubetypes.LabelSecretTypeState),
},
Data: map[string][]byte{
currentProfileKey: []byte("test"),
"test": p,
},
}
mustCreate(t, fc, pgStateSecret)
pg.Status.Conditions = []metav1.Condition{
{
Type: string(tsapi.ProxyGroupAvailable),
@@ -1179,14 +1209,6 @@ func setupIngressTest(t *testing.T) (*HAIngressReconciler, client.Client, *fakeT
t.Fatal(err)
}
lc := &fakeLocalClient{
status: &ipnstate.Status{
CurrentTailnet: &ipnstate.TailnetStatus{
MagicDNSSuffix: "ts.net",
},
},
}
ingPGR := &HAIngressReconciler{
Client: fc,
tsClient: ft,
@@ -1195,7 +1217,6 @@ func setupIngressTest(t *testing.T) (*HAIngressReconciler, client.Client, *fakeT
tsnetServer: fakeTsnetServer,
logger: zl.Sugar(),
recorder: record.NewFakeRecorder(10),
lc: lc,
ingressClassName: tsIngressClass.Name,
}