Merge pull request #36889 from wojtek-t/reuse_fields_and_labels
Automatic merge from submit-queue Reuse fields and labels This should significantly reduce memory allocations in apiserver in large cluster. Explanation: - every kubelet is refreshing watch every 5-10 minutes (this generally is not causing relist - it just renews watch) - that means, in 5000-node cluster, we are issuing ~10 watches per second - since we don't have "watch heartbets", the watch is issued from previously received resourceVersion - to make some assumption, let's assume pods are evenly spread across pods, and writes for them are evenly spread - that means, that a given kubelet is interested in 1 per 5000 pod changes - with that assumption, each watch, has to process 2500 (on average) previous watch events - for each of such even, we are currently computing fields. This PR is fixing this problem.
This commit is contained in:
@@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix,
|
||||
configmap.Strategy,
|
||||
newListFunc,
|
||||
configmap.GetAttrs,
|
||||
storage.NoTriggerPublisher)
|
||||
|
||||
store := ®istry.Store{
|
||||
|
@@ -88,18 +88,20 @@ func ConfigMapToSelectableFields(cfg *api.ConfigMap) fields.Set {
|
||||
return generic.ObjectMetaFieldsSet(&cfg.ObjectMeta, true)
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
cfg, ok := obj.(*api.ConfigMap)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a ConfigMap")
|
||||
}
|
||||
return labels.Set(cfg.ObjectMeta.Labels), ConfigMapToSelectableFields(cfg), nil
|
||||
}
|
||||
|
||||
// MatchConfigMap returns a generic matcher for a given label and field selector.
|
||||
func MatchConfigMap(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
cfg, ok := obj.(*api.ConfigMap)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a ConfigMap")
|
||||
}
|
||||
|
||||
return labels.Set(cfg.ObjectMeta.Labels), ConfigMapToSelectableFields(cfg), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
@@ -69,6 +69,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix,
|
||||
controller.Strategy,
|
||||
newListFunc,
|
||||
controller.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -118,20 +118,23 @@ func ControllerToSelectableFields(controller *api.ReplicationController) fields.
|
||||
return generic.MergeFieldsSets(objectMetaFieldsSet, controllerSpecificFieldsSet)
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
rc, ok := obj.(*api.ReplicationController)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Given object is not a replication controller.")
|
||||
}
|
||||
return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), nil
|
||||
}
|
||||
|
||||
// MatchController is the filter used by the generic etcd backend to route
|
||||
// watch events from etcd to clients of the apiserver only interested in specific
|
||||
// labels/fields.
|
||||
func MatchController(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
rc, ok := obj.(*api.ReplicationController)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Given object is not a replication controller.")
|
||||
}
|
||||
return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix,
|
||||
endpoint.Strategy,
|
||||
newListFunc,
|
||||
endpoint.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -79,27 +79,21 @@ func (endpointsStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
endpoints, ok := obj.(*api.Endpoints)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("invalid object type %#v", obj)
|
||||
}
|
||||
return endpoints.Labels, EndpointsToSelectableFields(endpoints), nil
|
||||
}
|
||||
|
||||
// MatchEndpoints returns a generic matcher for a given label and field selector.
|
||||
func MatchEndpoints(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate {
|
||||
return pkgstorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
endpoints, ok := obj.(*api.Endpoints)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("invalid object type %#v", obj)
|
||||
}
|
||||
|
||||
// Compute fields only if field selectors is non-empty
|
||||
// (otherwise those won't be used).
|
||||
// Those are generally also not needed if label selector does
|
||||
// not match labels, but additional computation of it is expensive.
|
||||
var endpointsFields fields.Set
|
||||
if !field.Empty() {
|
||||
endpointsFields = EndpointsToSelectableFields(endpoints)
|
||||
}
|
||||
return endpoints.Labels, endpointsFields, nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -70,17 +70,20 @@ func (eventStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
event, ok := obj.(*api.Event)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not an event")
|
||||
}
|
||||
return labels.Set(event.Labels), EventToSelectableFields(event), nil
|
||||
}
|
||||
|
||||
func MatchEvent(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
event, ok := obj.(*api.Event)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not an event")
|
||||
}
|
||||
return labels.Set(event.Labels), EventToSelectableFields(event), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix,
|
||||
limitrange.Strategy,
|
||||
newListFunc,
|
||||
limitrange.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -85,16 +85,19 @@ func (limitrangeStrategy) Export(api.Context, runtime.Object, bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
lr, ok := obj.(*api.LimitRange)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a limit range.")
|
||||
}
|
||||
return labels.Set(lr.ObjectMeta.Labels), LimitRangeToSelectableFields(lr), nil
|
||||
}
|
||||
|
||||
func MatchLimitRange(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
lr, ok := obj.(*api.LimitRange)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a limit range.")
|
||||
}
|
||||
return labels.Set(lr.ObjectMeta.Labels), LimitRangeToSelectableFields(lr), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
@@ -60,6 +60,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *FinalizeREST) {
|
||||
prefix,
|
||||
namespace.Strategy,
|
||||
newListFunc,
|
||||
namespace.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -135,18 +135,21 @@ func (namespaceFinalizeStrategy) PrepareForUpdate(ctx api.Context, obj, old runt
|
||||
newNamespace.Status = oldNamespace.Status
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
namespaceObj, ok := obj.(*api.Namespace)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a namespace")
|
||||
}
|
||||
return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), nil
|
||||
}
|
||||
|
||||
// MatchNamespace returns a generic matcher for a given label and field selector.
|
||||
func MatchNamespace(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
namespaceObj, ok := obj.(*api.Namespace)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a namespace")
|
||||
}
|
||||
return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -79,6 +79,7 @@ func NewStorage(opts generic.RESTOptions, kubeletClientConfig client.KubeletClie
|
||||
prefix,
|
||||
node.Strategy,
|
||||
newListFunc,
|
||||
node.GetAttrs,
|
||||
node.NodeNameTriggerFunc)
|
||||
|
||||
store := ®istry.Store{
|
||||
|
@@ -144,27 +144,21 @@ func NodeToSelectableFields(node *api.Node) fields.Set {
|
||||
return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
nodeObj, ok := obj.(*api.Node)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a node")
|
||||
}
|
||||
return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nil
|
||||
}
|
||||
|
||||
// MatchNode returns a generic matcher for a given label and field selector.
|
||||
func MatchNode(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate {
|
||||
return pkgstorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
nodeObj, ok := obj.(*api.Node)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a node")
|
||||
}
|
||||
|
||||
// Compute fields only if field selectors is non-empty
|
||||
// (otherwise those won't be used).
|
||||
// Those are generally also not needed if label selector does
|
||||
// not match labels, but additional computation of it is expensive.
|
||||
var nodeFields fields.Set
|
||||
if !field.Empty() {
|
||||
nodeFields = NodeToSelectableFields(nodeObj)
|
||||
}
|
||||
return labels.Set(nodeObj.ObjectMeta.Labels), nodeFields, nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
IndexFields: []string{"metadata.name"},
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix,
|
||||
persistentvolume.Strategy,
|
||||
newListFunc,
|
||||
persistentvolume.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -95,18 +95,21 @@ func (persistentvolumeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old r
|
||||
return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
persistentvolumeObj, ok := obj.(*api.PersistentVolume)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a persistentvolume")
|
||||
}
|
||||
return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), nil
|
||||
}
|
||||
|
||||
// MatchPersistentVolume returns a generic matcher for a given label and field selector.
|
||||
func MatchPersistentVolumes(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
persistentvolumeObj, ok := obj.(*api.PersistentVolume)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a persistentvolume")
|
||||
}
|
||||
return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix,
|
||||
persistentvolumeclaim.Strategy,
|
||||
newListFunc,
|
||||
persistentvolumeclaim.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -95,18 +95,21 @@ func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx api.Context, obj,
|
||||
return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a persistentvolumeclaim")
|
||||
}
|
||||
return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), nil
|
||||
}
|
||||
|
||||
// MatchPersistentVolumeClaim returns a generic matcher for a given label and field selector.
|
||||
func MatchPersistentVolumeClaim(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a persistentvolumeclaim")
|
||||
}
|
||||
return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -69,6 +69,7 @@ func NewStorage(opts generic.RESTOptions, k client.ConnectionInfoGetter, proxyTr
|
||||
prefix,
|
||||
pod.Strategy,
|
||||
newListFunc,
|
||||
pod.GetAttrs,
|
||||
pod.NodeNameTriggerFunc,
|
||||
)
|
||||
|
||||
|
@@ -155,27 +155,21 @@ func (podStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object
|
||||
return validation.ValidatePodStatusUpdate(obj.(*api.Pod), old.(*api.Pod))
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod, ok := obj.(*api.Pod)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a pod")
|
||||
}
|
||||
return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), nil
|
||||
}
|
||||
|
||||
// MatchPod returns a generic matcher for a given label and field selector.
|
||||
func MatchPod(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod, ok := obj.(*api.Pod)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a pod")
|
||||
}
|
||||
|
||||
// Compute fields only if field selectors is non-empty
|
||||
// (otherwise those won't be used).
|
||||
// Those are generally also not needed if label selector does
|
||||
// not match labels, but additional computation of it is expensive.
|
||||
var podFields fields.Set
|
||||
if !field.Empty() {
|
||||
podFields = PodToSelectableFields(pod)
|
||||
}
|
||||
return labels.Set(pod.ObjectMeta.Labels), podFields, nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
IndexFields: []string{"spec.nodeName"},
|
||||
}
|
||||
}
|
||||
|
@@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix,
|
||||
podtemplate.Strategy,
|
||||
newListFunc,
|
||||
podtemplate.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -86,16 +86,19 @@ func PodTemplateToSelectableFields(podTemplate *api.PodTemplate) fields.Set {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pt, ok := obj.(*api.PodTemplate)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a pod template.")
|
||||
}
|
||||
return labels.Set(pt.ObjectMeta.Labels), PodTemplateToSelectableFields(pt), nil
|
||||
}
|
||||
|
||||
func MatchPodTemplate(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pt, ok := obj.(*api.PodTemplate)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a pod template.")
|
||||
}
|
||||
return labels.Set(pt.ObjectMeta.Labels), PodTemplateToSelectableFields(pt), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix,
|
||||
resourcequota.Strategy,
|
||||
newListFunc,
|
||||
resourcequota.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -98,18 +98,21 @@ func (resourcequotaStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runt
|
||||
return validation.ValidateResourceQuotaStatusUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota))
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
resourcequotaObj, ok := obj.(*api.ResourceQuota)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a resourcequota")
|
||||
}
|
||||
return labels.Set(resourcequotaObj.Labels), ResourceQuotaToSelectableFields(resourcequotaObj), nil
|
||||
}
|
||||
|
||||
// MatchResourceQuota returns a generic matcher for a given label and field selector.
|
||||
func MatchResourceQuota(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
resourcequotaObj, ok := obj.(*api.ResourceQuota)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a resourcequota")
|
||||
}
|
||||
return labels.Set(resourcequotaObj.Labels), ResourceQuotaToSelectableFields(resourcequotaObj), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix,
|
||||
secret.Strategy,
|
||||
newListFunc,
|
||||
secret.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -94,18 +94,21 @@ func (s strategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
secret, ok := obj.(*api.Secret)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a secret")
|
||||
}
|
||||
return labels.Set(secret.Labels), SelectableFields(secret), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
secret, ok := obj.(*api.Secret)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a secret")
|
||||
}
|
||||
return labels.Set(secret.Labels), SelectableFields(secret), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix,
|
||||
service.Strategy,
|
||||
newListFunc,
|
||||
service.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -101,17 +101,20 @@ func (svcStrategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
service, ok := obj.(*api.Service)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Given object is not a service")
|
||||
}
|
||||
return labels.Set(service.ObjectMeta.Labels), ServiceToSelectableFields(service), nil
|
||||
}
|
||||
|
||||
func MatchServices(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
service, ok := obj.(*api.Service)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Given object is not a service")
|
||||
}
|
||||
return labels.Set(service.ObjectMeta.Labels), ServiceToSelectableFields(service), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix,
|
||||
serviceaccount.Strategy,
|
||||
newListFunc,
|
||||
serviceaccount.GetAttrs,
|
||||
storage.NoTriggerPublisher,
|
||||
)
|
||||
|
||||
|
@@ -77,18 +77,21 @@ func (strategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
sa, ok := obj.(*api.ServiceAccount)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a serviceaccount")
|
||||
}
|
||||
return labels.Set(sa.Labels), SelectableFields(sa), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
sa, ok := obj.(*api.ServiceAccount)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a serviceaccount")
|
||||
}
|
||||
return labels.Set(sa.Labels), SelectableFields(sa), nil
|
||||
},
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user