/* Copyright 2021 The Karmada Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package helper import ( "encoding/json" "k8s.io/klog/v2" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" mcsv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" "github.com/karmada-io/karmada/pkg/util" ) // SetDefaultSpreadConstraints set default spread constraints if both 'SpreadByField' and 'SpreadByLabel' not set. func SetDefaultSpreadConstraints(spreadConstraints []policyv1alpha1.SpreadConstraint) { for i := range spreadConstraints { if len(spreadConstraints[i].SpreadByLabel) == 0 && len(spreadConstraints[i].SpreadByField) == 0 { klog.Infof("Setting default SpreadByField with %s", policyv1alpha1.SpreadByFieldCluster) spreadConstraints[i].SpreadByField = policyv1alpha1.SpreadByFieldCluster } if spreadConstraints[i].MinGroups == 0 { klog.Infof("Setting default MinGroups to 1") spreadConstraints[i].MinGroups = 1 } } } // IsDependentOverridesPresent checks if a PropagationPolicy's dependent OverridePolicy all exist. func IsDependentOverridesPresent(c client.Client, policy *policyv1alpha1.PropagationPolicy) (bool, error) { ns := policy.Namespace for _, override := range policy.Spec.DependentOverrides { exist, err := IsOverridePolicyExist(c, ns, override) if err != nil { return false, err } if !exist { return false, nil } } return true, nil } // IsDependentClusterOverridesPresent checks if a ClusterPropagationPolicy's dependent ClusterOverridePolicy all exist. func IsDependentClusterOverridesPresent(c client.Client, policy *policyv1alpha1.ClusterPropagationPolicy) (bool, error) { for _, override := range policy.Spec.DependentOverrides { exist, err := IsClusterOverridePolicyExist(c, override) if err != nil { return false, err } if !exist { return false, nil } } return true, nil } // ContainsServiceImport Check whether the ResourceSelectors of the policy contain ResourceSelector, and its Kind is ServiceImport. func ContainsServiceImport(resourceSelectors []policyv1alpha1.ResourceSelector) bool { for _, resourceSelector := range resourceSelectors { if resourceSelector.Kind != util.ServiceImportKind { continue } if resourceSelector.APIVersion != mcsv1alpha1.GroupVersion.String() { continue } return true } return false } // IsReplicaDynamicDivided checks if a PropagationPolicy schedules replicas as dynamic. func IsReplicaDynamicDivided(placement *policyv1alpha1.Placement) bool { if placement.ReplicaSchedulingType() != policyv1alpha1.ReplicaSchedulingTypeDivided { return false } strategy := placement.ReplicaScheduling switch strategy.ReplicaDivisionPreference { case policyv1alpha1.ReplicaDivisionPreferenceWeighted: return strategy.WeightPreference != nil && len(strategy.WeightPreference.DynamicWeight) != 0 case policyv1alpha1.ReplicaDivisionPreferenceAggregated: return true default: return false } } // GetAppliedPlacement will get applied placement from annotations. func GetAppliedPlacement(annotations map[string]string) (*policyv1alpha1.Placement, error) { appliedPlacement := util.GetLabelValue(annotations, util.PolicyPlacementAnnotation) if len(appliedPlacement) == 0 { return nil, nil } placement := &policyv1alpha1.Placement{} if err := json.Unmarshal([]byte(appliedPlacement), placement); err != nil { return nil, err } return placement, nil } // SetReplicaDivisionPreferenceWeighted sets the default value of ReplicaDivisionPreference to Weighted func SetReplicaDivisionPreferenceWeighted(placement *policyv1alpha1.Placement) { if placement.ReplicaSchedulingType() != policyv1alpha1.ReplicaSchedulingTypeDivided || placement.ReplicaScheduling.ReplicaDivisionPreference != "" { return } placement.ReplicaScheduling.ReplicaDivisionPreference = policyv1alpha1.ReplicaDivisionPreferenceWeighted } // SetDefaultGracePeriodSeconds sets the default value of GracePeriodSeconds in ApplicationFailoverBehavior func SetDefaultGracePeriodSeconds(behavior *policyv1alpha1.ApplicationFailoverBehavior) { if behavior.PurgeMode == policyv1alpha1.Graciously && behavior.GracePeriodSeconds == nil { behavior.GracePeriodSeconds = ptr.To[int32](600) } }