Repository: kmesh-net/kmesh

Issue:
CI Job Disk Free
<!-- Please only use this template for submitting enhancement requests -->

**What would you like to be added**:

We frequently met disk out of use, and this cause ci failure recently.

Please reference 
https://github.com/volcano-sh/volcano/pull/4759 to add disk free to every CI workflow

Discussion:
@hzxuzhonghu: cc @LiZhenCheng9527 

Solution patch:
diff --git a/.github/workflows/e2e-ipv6-istio-1.24.yml b/.github/workflows/e2e-ipv6-istio-1.24.yml
index ecabf761..e198e7ca 100644
--- a/.github/workflows/e2e-ipv6-istio-1.24.yml
+++ b/.github/workflows/e2e-ipv6-istio-1.24.yml
@@ -15,6 +15,17 @@ jobs:
     timeout-minutes: 40
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
     - name: Setup Go
       uses: actions/setup-go@v4.0.0
diff --git a/.github/workflows/e2e-ipv6-istio-1.25.yml b/.github/workflows/e2e-ipv6-istio-1.25.yml
index df9cf9b5..d96bc179 100644
--- a/.github/workflows/e2e-ipv6-istio-1.25.yml
+++ b/.github/workflows/e2e-ipv6-istio-1.25.yml
@@ -15,6 +15,17 @@ jobs:
     timeout-minutes: 40
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
     - name: Setup Go
       uses: actions/setup-go@v4.0.0
diff --git a/.github/workflows/e2e-ipv6-istio-1.26.yml b/.github/workflows/e2e-ipv6-istio-1.26.yml
index 32df3e42..c1987d43 100644
--- a/.github/workflows/e2e-ipv6-istio-1.26.yml
+++ b/.github/workflows/e2e-ipv6-istio-1.26.yml
@@ -15,6 +15,17 @@ jobs:
     timeout-minutes: 40
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
     - name: Setup Go
       uses: actions/setup-go@v4.0.0
diff --git a/.github/workflows/e2e-istio-1.24.yml b/.github/workflows/e2e-istio-1.24.yml
index 228d8a05..44c14187 100644
--- a/.github/workflows/e2e-istio-1.24.yml
+++ b/.github/workflows/e2e-istio-1.24.yml
@@ -15,6 +15,17 @@ jobs:
     timeout-minutes: 40
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
     - name: Setup Go
       uses: actions/setup-go@v4.0.0
diff --git a/.github/workflows/e2e-istio-1.25.yml b/.github/workflows/e2e-istio-1.25.yml
index 45b46c3d..ad377da2 100644
--- a/.github/workflows/e2e-istio-1.25.yml
+++ b/.github/workflows/e2e-istio-1.25.yml
@@ -15,6 +15,17 @@ jobs:
     timeout-minutes: 40
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
     - name: Setup Go
       uses: actions/setup-go@v4.0.0
diff --git a/.github/workflows/e2e-istio-1.26.yml b/.github/workflows/e2e-istio-1.26.yml
index b7c9b8df..b6d435f2 100644
--- a/.github/workflows/e2e-istio-1.26.yml
+++ b/.github/workflows/e2e-istio-1.26.yml
@@ -15,6 +15,17 @@ jobs:
     timeout-minutes: 40
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
     - name: Setup Go
       uses: actions/setup-go@v4.0.0
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 821ad567..9cee2e78 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -20,6 +20,17 @@ jobs:
         go-version: [ '1.23' ]
 
     steps:
+    - name: Free Disk Space
+      uses: jlumbroso/free-disk-space@v1.3.1
+      with:
+        tool-cache: false
+        android: true
+        dotnet: true
+        haskell: true
+        large-packages: true
+        docker-images: true
+        swap-storage: true
+
     - uses: actions/checkout@v3
 
     - name: Setup Go
diff --git a/pkg/controller/workload/workload_processor.go b/pkg/controller/workload/workload_processor.go
index c9bdfcb8..7557d099 100644
--- a/pkg/controller/workload/workload_processor.go
+++ b/pkg/controller/workload/workload_processor.go
@@ -458,8 +458,16 @@ func (p *Processor) handleWorkloadNewBoundServices(workload *workloadapi.Workloa
 				}
 			} else { // locality mode
 				service := p.ServiceCache.GetService(p.hashName.NumToStr(svcUid))
-				if p.locality.LocalityInfo != nil && service != nil {
-					prio := p.locality.CalcLocalityLBPrio(workload, service.LoadBalancing.GetRoutingPreference())
+				if service != nil {
+					var prio uint32
+					if p.locality.LocalityInfo != nil {
+						prio = p.locality.CalcLocalityLBPrio(workload, service.LoadBalancing.GetRoutingPreference())
+					} else {
+						// If locality is not yet initialized, use highest priority (0)
+						// This ensures the workload is added to the endpoint map and will be recalculated
+						// when locality is eventually set
+						prio = 0
+					}
 					if _, err = p.addWorkloadToService(&sk, &sv, workloadId, prio); err != nil {
 						log.Errorf("addWorkloadToService workload %d service %d priority %d failed: %v", workloadId, sk.ServiceId, prio, err)
 						return err



Test patch:
diff --git a/pkg/controller/workload/workload_processor_test.go b/pkg/controller/workload/workload_processor_test.go
index cdabb712..46af4f47 100644
--- a/pkg/controller/workload/workload_processor_test.go
+++ b/pkg/controller/workload/workload_processor_test.go
@@ -784,3 +784,70 @@ func TestUpdateWorkloadInFrontendMap(t *testing.T) {
 		assert.NoError(t, err)
 	})
 }
+
+// TestLocalityLBWithNilLocalityInfo verifies that workloads are correctly added
+// to service endpoints even when LocalityInfo is nil in locality LB mode.
+// This tests the fix for the issue where waypoint addresses were missing in
+// ebpf/endpoints because LocalityInfo was not initialized when workloads from
+// other nodes arrived before any local workload.
+func TestLocalityLBWithNilLocalityInfo(t *testing.T) {
+	workloadMap := bpfcache.NewFakeWorkloadMap(t)
+	defer bpfcache.CleanupFakeWorkloadMap(workloadMap)
+
+	p := NewProcessor(workloadMap)
+
+	// Ensure LocalityInfo is nil (simulating no local workload has been processed yet)
+	assert.Nil(t, p.locality.LocalityInfo)
+
+	res := &service_discovery_v3.DeltaDiscoveryResponse{}
+
+	// Create a service with locality LB (FAILOVER mode, which is the default for waypoints)
+	localityLBScope := []workloadapi.LoadBalancing_Scope{
+		workloadapi.LoadBalancing_REGION,
+		workloadapi.LoadBalancing_ZONE,
+		workloadapi.LoadBalancing_SUBZONE,
+	}
+	localityLoadBalancing := createLoadBalancing(workloadapi.LoadBalancing_FAILOVER, localityLBScope)
+	svc := common.CreateFakeService("svc1", "10.240.10.1", "10.240.10.200", localityLoadBalancing)
+
+	addr := serviceToAddress(svc)
+	res.Resources = append(res.Resources, &service_discovery_v3.Resource{
+		Resource: protoconv.MessageToAny(addr),
+	})
+
+	// Add a workload from a different node (simulating waypoint workload)
+	// This workload arrives before any local workload, so LocalityInfo is still nil
+	wl := createWorkload("waypoint1", "10.244.0.1", "other-node", workloadapi.NetworkMode_STANDARD, createLocality("r1", "z1", "s1"), "svc1")
+	wlAddr := workloadToAddress(wl)
+	res.Resources = append(res.Resources, &service_discovery_v3.Resource{
+		Resource: protoconv.MessageToAny(wlAddr),
+	})
+
+	err := p.handleAddressTypeResponse(res)
+	assert.NoError(t, err)
+
+	// LocalityInfo should still be nil since no local workload was processed
+	assert.Nil(t, p.locality.LocalityInfo)
+
+	// Verify the workload is in the frontend map
+	workloadID := checkFrontEndMap(t, wl.Addresses[0], p)
+
+	// Verify the service is in the frontend map
+	svcID := checkFrontEndMap(t, svc.Addresses[0].Address, p)
+
+	// Verify the endpoint was added to the service
+	// When LocalityInfo is nil, the workload should be added with the highest priority (0)
+	var ek bpfcache.EndpointKey
+	var ev bpfcache.EndpointValue
+	ek.ServiceId = svcID
+	ek.Prio = 0 // highest priority when LocalityInfo is nil
+	ek.BackendIndex = 1
+	err = p.bpf.EndpointLookup(&ek, &ev)
+	assert.NoError(t, err, "Endpoint should exist in endpoint map with highest priority")
+	assert.Equal(t, workloadID, ev.BackendUid)
+
+	// Verify the endpoint count in the service map
+	checkServiceMap(t, p, svcID, svc, 0, 1)
+
+	hashNameClean(p)
+}