156 lines
5.6 KiB
Go
156 lines
5.6 KiB
Go
package helper
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
discoveryv1 "k8s.io/api/discovery/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
"k8s.io/klog/v2"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
|
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
|
"github.com/karmada-io/karmada/pkg/util"
|
|
"github.com/karmada-io/karmada/pkg/util/names"
|
|
)
|
|
|
|
// DenyReasonResourceSelectorsModify constructs a reason indicating that modify ResourceSelectors is not allowed.
|
|
const DenyReasonResourceSelectorsModify = "modify ResourceSelectors is forbidden"
|
|
|
|
// 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
|
|
}
|
|
}
|
|
}
|
|
|
|
// ValidateSpreadConstraint tests if the constraints is valid.
|
|
func ValidateSpreadConstraint(spreadConstraints []policyv1alpha1.SpreadConstraint) error {
|
|
spreadByFields := sets.NewString()
|
|
|
|
for _, constraint := range spreadConstraints {
|
|
// SpreadByField and SpreadByLabel should not co-exist
|
|
if len(constraint.SpreadByField) > 0 && len(constraint.SpreadByLabel) > 0 {
|
|
return fmt.Errorf("invalid constraints: SpreadByLabel(%s) should not co-exist with spreadByField(%s)", constraint.SpreadByLabel, constraint.SpreadByField)
|
|
}
|
|
|
|
// If MaxGroups provided, it should greater or equal than MinGroups.
|
|
if constraint.MaxGroups > 0 && constraint.MaxGroups < constraint.MinGroups {
|
|
return fmt.Errorf("maxGroups(%d) lower than minGroups(%d) is not allowed", constraint.MaxGroups, constraint.MinGroups)
|
|
}
|
|
|
|
if len(constraint.SpreadByField) > 0 {
|
|
spreadByFields.Insert(string(constraint.SpreadByField))
|
|
}
|
|
}
|
|
|
|
if spreadByFields.Len() > 0 {
|
|
// If one of spread constraints are using 'SpreadByField', the 'SpreadByFieldCluster' must be included.
|
|
// For example, when using 'SpreadByFieldRegion' to specify region groups, at the meantime, you must use
|
|
// 'SpreadByFieldCluster' to specify how many clusters should be selected.
|
|
if !spreadByFields.Has(string(policyv1alpha1.SpreadByFieldCluster)) {
|
|
return fmt.Errorf("the cluster spread constraint must be enabled in one of the constraints in case of SpreadByField is enabled")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// GetFollowedResourceSelectorsWhenMatchServiceImport get followed derived-service and endpointSlices resource selectors
|
|
// when policy's ResourceSelectors contains ResourceSelector, whose kind is ServiceImport.
|
|
func GetFollowedResourceSelectorsWhenMatchServiceImport(resourceSelectors []policyv1alpha1.ResourceSelector) []policyv1alpha1.ResourceSelector {
|
|
var addedResourceSelectors []policyv1alpha1.ResourceSelector
|
|
|
|
for _, resourceSelector := range resourceSelectors {
|
|
if resourceSelector.Kind != util.ServiceImportKind {
|
|
continue
|
|
}
|
|
|
|
if resourceSelector.Namespace == "" || resourceSelector.Name == "" {
|
|
continue
|
|
}
|
|
|
|
addedResourceSelectors = append(addedResourceSelectors, GenerateResourceSelectorForServiceImport(resourceSelector)...)
|
|
}
|
|
|
|
return addedResourceSelectors
|
|
}
|
|
|
|
// GenerateResourceSelectorForServiceImport generates resource selectors for ServiceImport.
|
|
func GenerateResourceSelectorForServiceImport(svcImport policyv1alpha1.ResourceSelector) []policyv1alpha1.ResourceSelector {
|
|
derivedServiceName := names.GenerateDerivedServiceName(svcImport.Name)
|
|
return []policyv1alpha1.ResourceSelector{
|
|
{
|
|
APIVersion: "v1",
|
|
Kind: util.ServiceKind,
|
|
Namespace: svcImport.Namespace,
|
|
Name: derivedServiceName,
|
|
},
|
|
{
|
|
APIVersion: "discovery.k8s.io/v1",
|
|
Kind: util.EndpointSliceKind,
|
|
Namespace: svcImport.Namespace,
|
|
LabelSelector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
discoveryv1.LabelServiceName: derivedServiceName,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// IsReplicaDynamicDivided checks if a PropagationPolicy schedules replicas as dynamic.
|
|
func IsReplicaDynamicDivided(strategy *policyv1alpha1.ReplicaSchedulingStrategy) bool {
|
|
if strategy == nil || strategy.ReplicaSchedulingType != policyv1alpha1.ReplicaSchedulingTypeDivided {
|
|
return false
|
|
}
|
|
|
|
switch strategy.ReplicaDivisionPreference {
|
|
case policyv1alpha1.ReplicaDivisionPreferenceWeighted:
|
|
return strategy.WeightPreference != nil && len(strategy.WeightPreference.DynamicWeight) != 0
|
|
case policyv1alpha1.ReplicaDivisionPreferenceAggregated:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|