Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.84.1
1.84.3
4 changes: 2 additions & 2 deletions cmd/k8s-operator/ingress-for-pg.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ func (r *HAIngressReconciler) maybeProvision(ctx context.Context, hostname strin
tags = strings.Split(tstr, ",")
}

tsSvcPorts := []string{"443"} // always 443 for Ingress
tsSvcPorts := []string{"tcp:443"} // always 443 for Ingress
if isHTTPEndpointEnabled(ing) {
tsSvcPorts = append(tsSvcPorts, "80")
tsSvcPorts = append(tsSvcPorts, "tcp:80")
}

tsSvc := &tailscale.VIPService{
Expand Down
14 changes: 7 additions & 7 deletions cmd/k8s-operator/ingress-for-pg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func TestIngressPGReconciler(t *testing.T) {
populateTLSSecret(context.Background(), fc, "test-pg", "my-svc.ts.net")
expectReconciled(t, ingPGR, "default", "test-ingress")
verifyServeConfig(t, fc, "svc:my-svc", false)
verifyTailscaleService(t, ft, "svc:my-svc", []string{"443"})
verifyTailscaleService(t, ft, "svc:my-svc", []string{"tcp:443"})
verifyTailscaledConfig(t, fc, []string{"svc:my-svc"})

// Verify that Role and RoleBinding have been created for the first Ingress.
Expand Down Expand Up @@ -130,7 +130,7 @@ func TestIngressPGReconciler(t *testing.T) {
populateTLSSecret(context.Background(), fc, "test-pg", "my-other-svc.ts.net")
expectReconciled(t, ingPGR, "default", "my-other-ingress")
verifyServeConfig(t, fc, "svc:my-other-svc", false)
verifyTailscaleService(t, ft, "svc:my-other-svc", []string{"443"})
verifyTailscaleService(t, ft, "svc:my-other-svc", []string{"tcp:443"})

// Verify that Role and RoleBinding have been created for the first Ingress.
// Do not verify the cert Secret as that was already verified implicitly above.
Expand All @@ -139,7 +139,7 @@ func TestIngressPGReconciler(t *testing.T) {

// Verify first Ingress is still working
verifyServeConfig(t, fc, "svc:my-svc", false)
verifyTailscaleService(t, ft, "svc:my-svc", []string{"443"})
verifyTailscaleService(t, ft, "svc:my-svc", []string{"tcp:443"})

verifyTailscaledConfig(t, fc, []string{"svc:my-svc", "svc:my-other-svc"})

Expand Down Expand Up @@ -244,7 +244,7 @@ func TestIngressPGReconciler_UpdateIngressHostname(t *testing.T) {
populateTLSSecret(context.Background(), fc, "test-pg", "my-svc.ts.net")
expectReconciled(t, ingPGR, "default", "test-ingress")
verifyServeConfig(t, fc, "svc:my-svc", false)
verifyTailscaleService(t, ft, "svc:my-svc", []string{"443"})
verifyTailscaleService(t, ft, "svc:my-svc", []string{"tcp:443"})
verifyTailscaledConfig(t, fc, []string{"svc:my-svc"})

// Update the Ingress hostname and make sure the original Tailscale Service is deleted.
Expand All @@ -255,7 +255,7 @@ func TestIngressPGReconciler_UpdateIngressHostname(t *testing.T) {
populateTLSSecret(context.Background(), fc, "test-pg", "updated-svc.ts.net")
expectReconciled(t, ingPGR, "default", "test-ingress")
verifyServeConfig(t, fc, "svc:updated-svc", false)
verifyTailscaleService(t, ft, "svc:updated-svc", []string{"443"})
verifyTailscaleService(t, ft, "svc:updated-svc", []string{"tcp:443"})
verifyTailscaledConfig(t, fc, []string{"svc:updated-svc"})

_, err := ft.GetVIPService(context.Background(), tailcfg.ServiceName("svc:my-svc"))
Expand Down Expand Up @@ -475,7 +475,7 @@ func TestIngressPGReconciler_HTTPEndpoint(t *testing.T) {
expectReconciled(t, ingPGR, "default", "test-ingress")
populateTLSSecret(context.Background(), fc, "test-pg", "my-svc.ts.net")
expectReconciled(t, ingPGR, "default", "test-ingress")
verifyTailscaleService(t, ft, "svc:my-svc", []string{"80", "443"})
verifyTailscaleService(t, ft, "svc:my-svc", []string{"tcp:80", "tcp:443"})
verifyServeConfig(t, fc, "svc:my-svc", true)

// Verify Ingress status
Expand Down Expand Up @@ -528,7 +528,7 @@ func TestIngressPGReconciler_HTTPEndpoint(t *testing.T) {

// Verify reconciliation after removing HTTP
expectReconciled(t, ingPGR, "default", "test-ingress")
verifyTailscaleService(t, ft, "svc:my-svc", []string{"443"})
verifyTailscaleService(t, ft, "svc:my-svc", []string{"tcp:443"})
verifyServeConfig(t, fc, "svc:my-svc", false)

// Verify Ingress status
Expand Down
15 changes: 10 additions & 5 deletions ipn/ipnlocal/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -6142,17 +6142,17 @@ func (b *LocalBackend) setTCPPortsInterceptedFromNetmapAndPrefsLocked(prefs ipn.
}
}

// Update funnel info in hostinfo and kick off control update if needed.
b.updateIngressLocked()
// Update funnel and service hash info in hostinfo and kick off control update if needed.
b.updateIngressAndServiceHashLocked(prefs)
b.setTCPPortsIntercepted(handlePorts)
b.setVIPServicesTCPPortsInterceptedLocked(vipServicesPorts)
}

// updateIngressLocked updates the hostinfo.WireIngress and hostinfo.IngressEnabled fields and kicks off a Hostinfo
// update if the values have changed.
// updateIngressAndServiceHashLocked updates the hostinfo.ServicesHash, hostinfo.WireIngress and
// hostinfo.IngressEnabled fields and kicks off a Hostinfo update if the values have changed.
//
// b.mu must be held.
func (b *LocalBackend) updateIngressLocked() {
func (b *LocalBackend) updateIngressAndServiceHashLocked(prefs ipn.PrefsView) {
if b.hostinfo == nil {
return
}
Expand All @@ -6167,6 +6167,11 @@ func (b *LocalBackend) updateIngressLocked() {
b.hostinfo.WireIngress = wire
hostInfoChanged = true
}
latestHash := b.vipServiceHash(b.vipServicesFromPrefsLocked(prefs))
if b.hostinfo.ServicesHash != latestHash {
b.hostinfo.ServicesHash = latestHash
hostInfoChanged = true
}
// Kick off a Hostinfo update to control if ingress status has changed.
if hostInfoChanged {
b.goTracker.Go(b.doSetHostinfoFilterServices)
Expand Down
69 changes: 66 additions & 3 deletions ipn/ipnlocal/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5134,10 +5134,17 @@ func TestUpdatePrefsOnSysPolicyChange(t *testing.T) {
}
}

func TestUpdateIngressLocked(t *testing.T) {
func TestUpdateIngressAndServiceHashLocked(t *testing.T) {
prefs := ipn.NewPrefs().View()
previousSC := &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
"svc:abc": {Tun: true},
},
}
tests := []struct {
name string
hi *tailcfg.Hostinfo
hasPreviousSC bool // whether to overwrite the ServeConfig hash in the Hostinfo using previousSC
sc *ipn.ServeConfig
wantIngress bool
wantWireIngress bool
Expand All @@ -5163,6 +5170,16 @@ func TestUpdateIngressLocked(t *testing.T) {
wantWireIngress: false, // implied by wantIngress
wantControlUpdate: true,
},
{
name: "empty_hostinfo_service_configured",
hi: &tailcfg.Hostinfo{},
sc: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
"svc:abc": {Tun: true},
},
},
wantControlUpdate: true,
},
{
name: "empty_hostinfo_funnel_disabled",
hi: &tailcfg.Hostinfo{},
Expand All @@ -5175,7 +5192,7 @@ func TestUpdateIngressLocked(t *testing.T) {
wantControlUpdate: true,
},
{
name: "empty_hostinfo_no_funnel",
name: "empty_hostinfo_no_funnel_no_service",
hi: &tailcfg.Hostinfo{},
sc: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
Expand All @@ -5196,6 +5213,16 @@ func TestUpdateIngressLocked(t *testing.T) {
wantIngress: true,
wantWireIngress: false, // implied by wantIngress
},
{
name: "service_hash_no_change",
hi: &tailcfg.Hostinfo{},
hasPreviousSC: true,
sc: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
"svc:abc": {Tun: true},
},
},
},
{
name: "funnel_disabled_no_change",
hi: &tailcfg.Hostinfo{
Expand All @@ -5208,6 +5235,13 @@ func TestUpdateIngressLocked(t *testing.T) {
},
wantWireIngress: true, // true if there is any AllowFunnel block
},
{
name: "service_got_removed",
hi: &tailcfg.Hostinfo{},
hasPreviousSC: true,
sc: &ipn.ServeConfig{},
wantControlUpdate: true,
},
{
name: "funnel_changes_to_disabled",
hi: &tailcfg.Hostinfo{
Expand Down Expand Up @@ -5235,12 +5269,35 @@ func TestUpdateIngressLocked(t *testing.T) {
wantWireIngress: false, // implied by wantIngress
wantControlUpdate: true,
},
{
name: "both_funnel_and_service_changes",
hi: &tailcfg.Hostinfo{
IngressEnabled: true,
},
sc: &ipn.ServeConfig{
AllowFunnel: map[ipn.HostPort]bool{
"tailnet.xyz:443": false,
},
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
"svc:abc": {Tun: true},
},
},
wantWireIngress: true, // true if there is any AllowFunnel block
wantControlUpdate: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
b := newTestLocalBackend(t)
b.hostinfo = tt.hi
if tt.hasPreviousSC {
b.mu.Lock()
b.serveConfig = previousSC.View()
b.hostinfo.ServicesHash = b.vipServiceHash(b.vipServicesFromPrefsLocked(prefs))
b.mu.Unlock()
}
b.serveConfig = tt.sc.View()
allDone := make(chan bool, 1)
defer b.goTracker.AddDoneCallback(func() {
Expand All @@ -5256,7 +5313,7 @@ func TestUpdateIngressLocked(t *testing.T) {
})()

was := b.goTracker.StartedGoroutines()
b.updateIngressLocked()
b.updateIngressAndServiceHashLocked(prefs)

if tt.hi != nil {
if tt.hi.IngressEnabled != tt.wantIngress {
Expand All @@ -5265,6 +5322,12 @@ func TestUpdateIngressLocked(t *testing.T) {
if tt.hi.WireIngress != tt.wantWireIngress {
t.Errorf("WireIngress = %v, want %v", tt.hi.WireIngress, tt.wantWireIngress)
}
b.mu.Lock()
svcHash := b.vipServiceHash(b.vipServicesFromPrefsLocked(prefs))
b.mu.Unlock()
if tt.hi.ServicesHash != svcHash {
t.Errorf("ServicesHash = %v, want %v", tt.hi.ServicesHash, svcHash)
}
}

startedGoroutine := b.goTracker.StartedGoroutines() != was
Expand Down