@@ -14,13 +14,18 @@ import (
1414 policyv1 "k8s.io/api/policy/v1"
1515 apiextensionshelpers "k8s.io/apiextensions-apiserver/pkg/apihelpers"
1616 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
17+ "k8s.io/apimachinery/pkg/api/meta"
1718 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1819 "k8s.io/apimachinery/pkg/runtime"
1920 "k8s.io/apimachinery/pkg/runtime/schema"
2021 "k8s.io/component-helpers/apps/poddisruptionbudget"
2122 "k8s.io/klog/v2"
2223
24+ fleetnetworkingv1alpha1 "go.goms.io/fleet-networking/api/v1alpha1"
25+ "go.goms.io/fleet-networking/pkg/common/objectmeta"
26+
2327 "go.goms.io/fleet/pkg/utils"
28+ "go.goms.io/fleet/pkg/utils/condition"
2429 "go.goms.io/fleet/pkg/utils/controller"
2530)
2631
@@ -83,6 +88,8 @@ func trackInMemberClusterObjAvailabilityByGVR(
8388 return trackCRDAvailability (inMemberClusterObj )
8489 case utils .PodDisruptionBudgetGVR :
8590 return trackPDBAvailability (inMemberClusterObj )
91+ case utils .ServiceExportGVR :
92+ return trackServiceExportAvailability (inMemberClusterObj )
8693 default :
8794 if isDataResource (* gvr ) {
8895 klog .V (2 ).InfoS ("The object from the member cluster is a data object, consider it to be immediately available" ,
@@ -247,6 +254,44 @@ func trackPDBAvailability(curObj *unstructured.Unstructured) (ManifestProcessing
247254 return ManifestProcessingAvailabilityResultTypeNotYetAvailable , nil
248255}
249256
257+ // trackServiceExportAvailability tracks the availability of a service export in the member cluster.
258+ // It is available if the ServiceExportValid condition is true (will be false if annotation value is invalid).
259+ // If the weight is not 0, ServiceExportValid condition must be true and the ServiceExportConflict condition must be false.
260+ func trackServiceExportAvailability (curObj * unstructured.Unstructured ) (ManifestProcessingAvailabilityResultType , error ) {
261+ var svcExport fleetnetworkingv1alpha1.ServiceExport
262+ if err := runtime .DefaultUnstructuredConverter .FromUnstructured (curObj .Object , & svcExport ); err != nil {
263+ return ManifestProcessingAvailabilityResultTypeFailed , controller .NewUnexpectedBehaviorError (err )
264+ }
265+
266+ // Check if ServiceExport is valid and up to date
267+ svcExportObj := klog .KObj (curObj )
268+ validCond := meta .FindStatusCondition (svcExport .Status .Conditions , string (fleetnetworkingv1alpha1 .ServiceExportValid ))
269+ if ! condition .IsConditionStatusTrue (validCond , svcExport .Generation ) {
270+ klog .V (2 ).InfoS ("Still need to wait for ServiceExport to be valid" , "serviceExport" , svcExportObj , "validCondition" , validCond )
271+ return ManifestProcessingAvailabilityResultTypeNotYetAvailable , nil
272+ }
273+ // Validate annotation weight. Updating the annotation won't change the object generation,
274+ // so the current status is not reliable and need to validate the annotation again here
275+ weight , err := objectmeta .ExtractWeightFromServiceExport (& svcExport )
276+ if err != nil {
277+ klog .Errorf (err .Error (), "ServiceExport has invalid weight" , "serviceExport" , svcExportObj )
278+ return ManifestProcessingAvailabilityResultTypeNotYetAvailable , err
279+ }
280+ if weight != 0 {
281+ // Check conflict condition for non-zero weight
282+ conflictCond := meta .FindStatusCondition (svcExport .Status .Conditions , string (fleetnetworkingv1alpha1 .ServiceExportConflict ))
283+ if ! condition .IsConditionStatusFalse (conflictCond , svcExport .Generation ) {
284+ klog .V (2 ).InfoS ("Still need to wait for ServiceExport to not have conflicts" , "serviceExport" , svcExportObj , "conflictCondition" , conflictCond )
285+ return ManifestProcessingAvailabilityResultTypeNotYetAvailable , nil
286+ }
287+ } else {
288+ klog .V (2 ).InfoS ("Skipping checking the conflict condition for the weight 0" , "serviceExport" , svcExportObj )
289+ }
290+
291+ klog .V (2 ).InfoS ("ServiceExport is available" , "serviceExport" , svcExportObj )
292+ return ManifestProcessingAvailabilityResultTypeAvailable , nil
293+ }
294+
250295// isDataResource checks if the resource is a data resource; such resources are
251296// available immediately after creation.
252297func isDataResource (gvr schema.GroupVersionResource ) bool {
0 commit comments