package search import ( "context" "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" searchapis "github.com/karmada-io/karmada/pkg/apis/search" ) // NewStrategy creates and returns a ResourceRegistry Strategy instance. func NewStrategy(typer runtime.ObjectTyper) Strategy { return Strategy{typer, names.SimpleNameGenerator} } // GetAttrs returns labels.Set, fields.Set, and error in case the given runtime.Object is not a ResourceRegistry. func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { resourceRegistry, ok := obj.(*searchapis.ResourceRegistry) if !ok { return nil, nil, fmt.Errorf("given object is not a ResourceRegistry") } return resourceRegistry.ObjectMeta.Labels, SelectableFields(resourceRegistry), nil } // MatchResourceRegistry is the filter used by the generic etcd backend to watch events // from etcd to clients of the apiserver only interested in specific labels/fields. func MatchResourceRegistry(label labels.Selector, field fields.Selector) storage.SelectionPredicate { return storage.SelectionPredicate{ Label: label, Field: field, GetAttrs: GetAttrs, } } // SelectableFields returns a field set that represents the object. func SelectableFields(obj *searchapis.ResourceRegistry) fields.Set { return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, false) } // Strategy implements behavior for ResourceRegistry. type Strategy struct { runtime.ObjectTyper names.NameGenerator } // NamespaceScoped returns if the object must be in a namespace. func (Strategy) NamespaceScoped() bool { return false } // GetResetFields returns the set of fields that get reset by the strategy // and should not be modified by the user. func (Strategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return map[fieldpath.APIVersion]*fieldpath.Set{ "search.karmada.io/v1alpha1": fieldpath.NewSet( fieldpath.MakePathOrDie("status"), ), } } // PrepareForCreate is invoked on create before validation to normalize the object. func (Strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { } // PrepareForUpdate is invoked on update before validation to normalize the object. func (Strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } // Validate returns an ErrorList with validation errors or nil. func (Strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { // TODO: add validation for ResourceRegistry return field.ErrorList{} } // WarningsOnCreate returns warnings for the creation of the given object. func (Strategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { return nil } // AllowCreateOnUpdate returns true if the object can be created by a PUT. func (Strategy) AllowCreateOnUpdate() bool { return false } // AllowUnconditionalUpdate returns true if the object can be updated // unconditionally (irrespective of the latest resource version), when // there is no resource version specified in the object. func (Strategy) AllowUnconditionalUpdate() bool { return true } // Canonicalize allows an object to be mutated into a canonical form. func (Strategy) Canonicalize(obj runtime.Object) { } // ValidateUpdate is invoked after default fields in the object have been // filled in before the object is persisted. func (Strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { // TODO: add validation for ResourceRegistry return field.ErrorList{} } // WarningsOnUpdate returns warnings for the given update. func (Strategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { return nil } // StatusStrategy implements behavior for ResourceRegistryStatus. type StatusStrategy struct { Strategy } // NewStatusStrategy creates and returns a StatusStrategy instance. func NewStatusStrategy(strategy Strategy) StatusStrategy { return StatusStrategy{strategy} } // GetResetFields returns the set of fields that get reset by the strategy // and should not be modified by the user. func (StatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { return map[fieldpath.APIVersion]*fieldpath.Set{} } // PrepareForUpdate clears fields that are not allowed to be set by end users on update of status func (StatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } // ValidateUpdate is the default update validation for an end user updating status func (StatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return field.ErrorList{} } // WarningsOnUpdate returns warnings for the given update. func (StatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { return nil }