in pkg/controllers/hub/trafficmanagerbackend/controller.go [495:564]
func (r *Reconciler) validateAndProcessServiceImportForBackend(ctx context.Context, backend *fleetnetv1beta1.TrafficManagerBackend, serviceImport *fleetnetv1alpha1.ServiceImport) (map[string]desiredEndpoint, map[string]error, error) {
backendKObj := klog.KObj(backend)
serviceImportKObj := klog.KObj(serviceImport)
if len(serviceImport.Status.Clusters) == 0 {
klog.V(2).InfoS("No clusters found in the serviceImport", "trafficManagerBackend", backendKObj, "serviceImport", serviceImportKObj)
// Controller will only create the serviceImport when there is a cluster exposing their services.
// Updating the status will be in a separate call and could fail.
setUnknownCondition(backend, "In the process of exporting the services")
// We don't need to requeue the request and when the serviceImport status is set, the controller will be re-triggered.
return nil, nil, r.updateTrafficManagerBackendStatus(ctx, backend)
}
internalServiceExportList := &fleetnetv1alpha1.InternalServiceExportList{}
namespaceName := types.NamespacedName{Namespace: serviceImport.Namespace, Name: serviceImport.Name}
listOpts := client.MatchingFields{
exportedServiceFieldNamespacedName: namespaceName.String(),
}
if listErr := r.Client.List(ctx, internalServiceExportList, &listOpts); listErr != nil {
klog.ErrorS(listErr, "Failed to list internalServiceExports used by the serviceImport", "trafficManagerBackend", backendKObj, "serviceImport", serviceImportKObj)
setUnknownCondition(backend, fmt.Sprintf("Failed to list the exported service %q: %v", namespaceName, listErr))
if err := r.updateTrafficManagerBackendStatus(ctx, backend); err != nil {
return nil, nil, err
}
return nil, nil, listErr
}
internalServiceExportMap := make(map[string]*fleetnetv1alpha1.InternalServiceExport, len(internalServiceExportList.Items))
for i, export := range internalServiceExportList.Items {
internalServiceExportMap[export.Spec.ServiceReference.ClusterID] = &internalServiceExportList.Items[i]
}
desiredEndpoints := make(map[string]desiredEndpoint, len(serviceImport.Status.Clusters)) // key is the endpoint name
invalidServices := make(map[string]error, len(serviceImport.Status.Clusters)) // key is cluster name
var totalWeight int64
for _, clusterStatus := range serviceImport.Status.Clusters {
internalServiceExport, ok := internalServiceExportMap[clusterStatus.Cluster]
if !ok {
getErr := fmt.Errorf("failed to find the internalServiceExport for the cluster %q", clusterStatus.Cluster)
// Usually controller should update the serviceImport status first before deleting the internalServiceImport.
// It could happen that the current serviceImport has stale information.
// The controller will be re-triggered when the serviceImport is updated.
klog.ErrorS(getErr, "InternalServiceExport not found for the cluster", "trafficManagerBackend", backendKObj, "serviceImport", serviceImportKObj, "clusterID", clusterStatus.Cluster)
setUnknownCondition(backend, fmt.Sprintf("Failed to find the exported service %q for %q: %v", namespaceName, clusterStatus.Cluster, getErr))
return nil, nil, r.updateTrafficManagerBackendStatus(ctx, backend)
}
if err := isValidTrafficManagerEndpoint(internalServiceExport); err != nil {
invalidServices[clusterStatus.Cluster] = err
klog.V(2).InfoS("Invalid service for TrafficManager endpoint", "trafficManagerBackend", backendKObj, "serviceImport", serviceImportKObj, "clusterID", clusterStatus.Cluster, "error", err)
continue
}
endpoint := generateAzureTrafficManagerEndpoint(backend, internalServiceExport)
desiredEndpoints[*endpoint.Name] = desiredEndpoint{
Endpoint: endpoint,
FromCluster: fleetnetv1beta1.FromCluster{
ClusterStatus: fleetnetv1beta1.ClusterStatus{
Cluster: clusterStatus.Cluster,
},
Weight: endpoint.Properties.Weight,
},
}
totalWeight += *endpoint.Properties.Weight
}
for _, dp := range desiredEndpoints {
// Calculate the desired weight for the endpoint as the proportion of the total weight.
desiredWeight := math.Ceil(float64(*backend.Spec.Weight**dp.Endpoint.Properties.Weight) / float64(totalWeight))
dp.Endpoint.Properties.Weight = ptr.To(int64(desiredWeight))
}
klog.V(2).InfoS("Finishing validating services and setup endpoints", "trafficManagerBackend", backendKObj, "serviceImport", serviceImportKObj, "numberOfDesiredEndpoints", len(desiredEndpoints), "numberOfInvalidServices", len(invalidServices), "totalWeight", totalWeight)
return desiredEndpoints, invalidServices, nil
}