mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-25 16:07:24 +00:00
feat: upstream enterprise preview (#1841)
feat: upstream enterprise preview --------- Signed-off-by: Oliver Baehler <oliver@sudo-i.net> Co-authored-by: CorentinPtrl <pitrel.corentin@gmail.com>
This commit is contained in:
co-authored by
CorentinPtrl
parent
7a65ab7afc
commit
cc4fb45d70
@@ -15,7 +15,6 @@ func CombineSelectors(selectors ...labels.Selector) labels.Selector {
|
||||
|
||||
reqs, selectable := sel.Requirements()
|
||||
if !selectable {
|
||||
// Defensive: if selector can't be expressed as requirements, match nothing.
|
||||
return labels.Nothing()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2020-2026 Project Capsule Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package selectors
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/projectcapsule/capsule/pkg/runtime/jsonpath"
|
||||
)
|
||||
|
||||
// +kubebuilder:object:generate=true
|
||||
type SelectorWithFields struct {
|
||||
// Select Items based on their labels.
|
||||
*metav1.LabelSelector `json:",inline"`
|
||||
|
||||
// Additional boolean JSONPath expressions.
|
||||
// All must evaluate to true for this selector to match.
|
||||
// +optional
|
||||
FieldSelectors []string `json:"fieldSelectors,omitempty"`
|
||||
}
|
||||
|
||||
type CompiledSelectorWithFields struct {
|
||||
LabelSelector labels.Selector
|
||||
FieldMatchers []*jsonpath.CompiledJSONPath
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
// match ANY of the provided LabelSelectors. The result is unique by namespace/name.
|
||||
func ListBySelectors[T client.Object](
|
||||
ctx context.Context,
|
||||
c client.Client,
|
||||
c client.Reader,
|
||||
list client.ObjectList,
|
||||
selectors []*metav1.LabelSelector,
|
||||
) ([]T, error) {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2020-2026 Project Capsule Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package selectors
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
// Attempt so verify multiple selector objects against a labels.Set
|
||||
// If selectors are not set, it is always considered a match.
|
||||
func MatchesSelectors(objLabels labels.Set, selectors []metav1.LabelSelector) bool {
|
||||
if len(selectors) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, selector := range selectors {
|
||||
sel, err := metav1.LabelSelectorAsSelector(&selector)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if sel.Matches(objLabels) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Attempt so verify multiple selector objects against a labels.Set
|
||||
// If selectors are not set, it is always considered a match.
|
||||
func MatchesSelector(objLabels labels.Set, selector metav1.LabelSelector) (bool, error) {
|
||||
sel, err := metav1.LabelSelectorAsSelector(&selector)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if sel.Matches(objLabels) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package selectors
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -24,10 +25,10 @@ type NamespaceSelector struct {
|
||||
// GetMatchingNamespaces retrieves the list of namespaces that match the NamespaceSelector.
|
||||
func (s *NamespaceSelector) GetMatchingNamespaces(
|
||||
ctx context.Context,
|
||||
c client.Client,
|
||||
c client.Reader,
|
||||
) ([]corev1.Namespace, error) {
|
||||
if s.LabelSelector == nil {
|
||||
return nil, nil // No namespace selector means all namespaces
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
nsSelector, err := metav1.LabelSelectorAsSelector(s.LabelSelector)
|
||||
@@ -51,6 +52,62 @@ func (s *NamespaceSelector) GetMatchingNamespaces(
|
||||
return matchingNamespaces, nil
|
||||
}
|
||||
|
||||
// Takes a list of NamespaceSelectors and returns unique ordered Namespaces.
|
||||
func GetNamespacesMatchingSelectors(
|
||||
ctx context.Context,
|
||||
c client.Reader,
|
||||
namespaceSelector []NamespaceSelector,
|
||||
) (namespaces []corev1.Namespace, err error) {
|
||||
if len(namespaceSelector) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
byName := make(map[string]corev1.Namespace)
|
||||
|
||||
for _, selector := range namespaceSelector {
|
||||
matches, err := selector.GetMatchingNamespaces(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, ns := range matches {
|
||||
byName[ns.Name] = ns
|
||||
}
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(byName))
|
||||
for name := range byName {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
sort.Strings(names)
|
||||
|
||||
result := make([]corev1.Namespace, 0, len(names))
|
||||
for _, name := range names {
|
||||
result = append(result, byName[name])
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GetNamespacesMatchingSelectorsStrings(
|
||||
ctx context.Context,
|
||||
c client.Reader,
|
||||
namespaceSelector []NamespaceSelector,
|
||||
) ([]string, error) {
|
||||
namespaces, err := GetNamespacesMatchingSelectors(ctx, c, namespaceSelector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]string, 0, len(namespaces))
|
||||
for _, ns := range namespaces {
|
||||
result = append(result, ns.Name)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Selector for resources and their labels or selecting origin namespaces
|
||||
// +kubebuilder:object:generate=true
|
||||
type SelectorWithNamespaceSelector struct {
|
||||
@@ -64,7 +121,7 @@ type SelectorWithNamespaceSelector struct {
|
||||
|
||||
func (s *SelectorWithNamespaceSelector) MatchObjects(
|
||||
ctx context.Context,
|
||||
c client.Client,
|
||||
c client.Reader,
|
||||
objects []metav1.Object,
|
||||
) ([]metav1.Object, error) {
|
||||
if s == nil {
|
||||
|
||||
@@ -31,6 +31,31 @@ func (in *NamespaceSelector) DeepCopy() *NamespaceSelector {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SelectorWithFields) DeepCopyInto(out *SelectorWithFields) {
|
||||
*out = *in
|
||||
if in.LabelSelector != nil {
|
||||
in, out := &in.LabelSelector, &out.LabelSelector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.FieldSelectors != nil {
|
||||
in, out := &in.FieldSelectors, &out.FieldSelectors
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SelectorWithFields.
|
||||
func (in *SelectorWithFields) DeepCopy() *SelectorWithFields {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SelectorWithFields)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SelectorWithNamespaceSelector) DeepCopyInto(out *SelectorWithNamespaceSelector) {
|
||||
*out = *in
|
||||
|
||||
Reference in New Issue
Block a user