mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
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:
commit
cd560926bd
@ -40,8 +40,15 @@ func NewREST(config *storagebackend.Config, storageDecorator generic.StorageDeco
|
|||||||
newListFunc := func() runtime.Object { return &testgroup.TestTypeList{} }
|
newListFunc := func() runtime.Object { return &testgroup.TestTypeList{} }
|
||||||
// Usually you should reuse your RESTCreateStrategy.
|
// Usually you should reuse your RESTCreateStrategy.
|
||||||
strategy := &NotNamespaceScoped{}
|
strategy := &NotNamespaceScoped{}
|
||||||
|
getAttrs := func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
testObj, ok := obj.(*testgroup.TestType)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a TestType")
|
||||||
|
}
|
||||||
|
return labels.Set(testObj.Labels), nil, nil
|
||||||
|
}
|
||||||
storageInterface, _ := storageDecorator(
|
storageInterface, _ := storageDecorator(
|
||||||
config, 100, &testgroup.TestType{}, prefix, strategy, newListFunc, storage.NoTriggerPublisher)
|
config, 100, &testgroup.TestType{}, prefix, strategy, newListFunc, getAttrs, storage.NoTriggerPublisher)
|
||||||
store := ®istry.Store{
|
store := ®istry.Store{
|
||||||
NewFunc: func() runtime.Object { return &testgroup.TestType{} },
|
NewFunc: func() runtime.Object { return &testgroup.TestType{} },
|
||||||
// NewListFunc returns an object capable of storing results of an etcd list.
|
// NewListFunc returns an object capable of storing results of an etcd list.
|
||||||
|
@ -56,6 +56,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
cluster.Strategy,
|
cluster.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
cluster.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,17 +45,20 @@ func ClusterToSelectableFields(cluster *federation.Cluster) fields.Set {
|
|||||||
return generic.ObjectMetaFieldsSet(&cluster.ObjectMeta, false)
|
return generic.ObjectMetaFieldsSet(&cluster.ObjectMeta, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
cluster, ok := obj.(*federation.Cluster)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a cluster.")
|
||||||
|
}
|
||||||
|
return labels.Set(cluster.ObjectMeta.Labels), ClusterToSelectableFields(cluster), nil
|
||||||
|
}
|
||||||
|
|
||||||
func MatchCluster(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchCluster(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
cluster, ok := obj.(*federation.Cluster)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a cluster.")
|
|
||||||
}
|
|
||||||
return labels.Set(cluster.ObjectMeta.Labels), ClusterToSelectableFields(cluster), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
petset.Strategy,
|
petset.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
petset.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,19 +102,22 @@ func StatefulSetToSelectableFields(statefulSet *apps.StatefulSet) fields.Set {
|
|||||||
return generic.ObjectMetaFieldsSet(&statefulSet.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&statefulSet.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
statefulSet, ok := obj.(*apps.StatefulSet)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not an StatefulSet.")
|
||||||
|
}
|
||||||
|
return labels.Set(statefulSet.ObjectMeta.Labels), StatefulSetToSelectableFields(statefulSet), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchStatefulSet is the filter used by the generic etcd backend to watch events
|
// MatchStatefulSet 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.
|
// from etcd to clients of the apiserver only interested in specific labels/fields.
|
||||||
func MatchStatefulSet(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchStatefulSet(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
statefulSet, ok := obj.(*apps.StatefulSet)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not an StatefulSet.")
|
|
||||||
}
|
|
||||||
return labels.Set(statefulSet.ObjectMeta.Labels), StatefulSetToSelectableFields(statefulSet), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
horizontalpodautoscaler.Strategy,
|
horizontalpodautoscaler.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
horizontalpodautoscaler.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,17 +88,20 @@ func AutoscalerToSelectableFields(hpa *autoscaling.HorizontalPodAutoscaler) fiel
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
hpa, ok := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a horizontal pod autoscaler.")
|
||||||
|
}
|
||||||
|
return labels.Set(hpa.ObjectMeta.Labels), AutoscalerToSelectableFields(hpa), nil
|
||||||
|
}
|
||||||
|
|
||||||
func MatchAutoscaler(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchAutoscaler(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
hpa, ok := obj.(*autoscaling.HorizontalPodAutoscaler)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a horizontal pod autoscaler.")
|
|
||||||
}
|
|
||||||
return labels.Set(hpa.ObjectMeta.Labels), AutoscalerToSelectableFields(hpa), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
cronjob.Strategy,
|
cronjob.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
cronjob.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,19 +102,22 @@ func CronJobToSelectableFields(scheduledJob *batch.CronJob) fields.Set {
|
|||||||
return generic.ObjectMetaFieldsSet(&scheduledJob.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&scheduledJob.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
scheduledJob, ok := obj.(*batch.CronJob)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("Given object is not a scheduled job.")
|
||||||
|
}
|
||||||
|
return labels.Set(scheduledJob.ObjectMeta.Labels), CronJobToSelectableFields(scheduledJob), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchCronJob is the filter used by the generic etcd backend to route
|
// MatchCronJob is the filter used by the generic etcd backend to route
|
||||||
// watch events from etcd to clients of the apiserver only interested in specific
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchCronJob(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchCronJob(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
scheduledJob, ok := obj.(*batch.CronJob)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("Given object is not a scheduled job.")
|
|
||||||
}
|
|
||||||
return labels.Set(scheduledJob.ObjectMeta.Labels), CronJobToSelectableFields(scheduledJob), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
job.Strategy,
|
job.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
job.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -164,19 +164,22 @@ func JobToSelectableFields(job *batch.Job) fields.Set {
|
|||||||
return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
|
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) {
|
||||||
|
job, ok := obj.(*batch.Job)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("Given object is not a job.")
|
||||||
|
}
|
||||||
|
return labels.Set(job.ObjectMeta.Labels), JobToSelectableFields(job), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchJob is the filter used by the generic etcd backend to route
|
// MatchJob is the filter used by the generic etcd backend to route
|
||||||
// watch events from etcd to clients of the apiserver only interested in specific
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchJob(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchJob(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
job, ok := obj.(*batch.Job)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("Given object is not a job.")
|
|
||||||
}
|
|
||||||
return labels.Set(job.ObjectMeta.Labels), JobToSelectableFields(job), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *ApprovalREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
csrregistry.Strategy,
|
csrregistry.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
csrregistry.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -168,18 +168,21 @@ func (csrApprovalStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Obje
|
|||||||
return validation.ValidateCertificateSigningRequestUpdate(obj.(*certificates.CertificateSigningRequest), old.(*certificates.CertificateSigningRequest))
|
return validation.ValidateCertificateSigningRequestUpdate(obj.(*certificates.CertificateSigningRequest), old.(*certificates.CertificateSigningRequest))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.(*certificates.CertificateSigningRequest)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a CertificateSigningRequest")
|
||||||
|
}
|
||||||
|
return labels.Set(sa.Labels), SelectableFields(sa), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
sa, ok := obj.(*certificates.CertificateSigningRequest)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a CertificateSigningRequest")
|
|
||||||
}
|
|
||||||
return labels.Set(sa.Labels), SelectableFields(sa), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
configmap.Strategy,
|
configmap.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
configmap.GetAttrs,
|
||||||
storage.NoTriggerPublisher)
|
storage.NoTriggerPublisher)
|
||||||
|
|
||||||
store := ®istry.Store{
|
store := ®istry.Store{
|
||||||
|
@ -88,18 +88,20 @@ func ConfigMapToSelectableFields(cfg *api.ConfigMap) fields.Set {
|
|||||||
return generic.ObjectMetaFieldsSet(&cfg.ObjectMeta, true)
|
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.
|
// MatchConfigMap returns a generic matcher for a given label and field selector.
|
||||||
func MatchConfigMap(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchConfigMap(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
controller.Strategy,
|
controller.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
controller.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -118,20 +118,23 @@ func ControllerToSelectableFields(controller *api.ReplicationController) fields.
|
|||||||
return generic.MergeFieldsSets(objectMetaFieldsSet, controllerSpecificFieldsSet)
|
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
|
// 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
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchController(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchController(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
endpoint.Strategy,
|
endpoint.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
endpoint.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,27 +79,21 @@ func (endpointsStrategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
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.
|
// MatchEndpoints returns a generic matcher for a given label and field selector.
|
||||||
func MatchEndpoints(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate {
|
func MatchEndpoints(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate {
|
||||||
return pkgstorage.SelectionPredicate{
|
return pkgstorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,17 +70,20 @@ func (eventStrategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
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 {
|
func MatchEvent(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
event, ok := obj.(*api.Event)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not an event")
|
|
||||||
}
|
|
||||||
return labels.Set(event.Labels), EventToSelectableFields(event), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
limitrange.Strategy,
|
limitrange.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
limitrange.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -85,16 +85,19 @@ func (limitrangeStrategy) Export(api.Context, runtime.Object, bool) error {
|
|||||||
return nil
|
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 {
|
func MatchLimitRange(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *FinalizeREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
namespace.Strategy,
|
namespace.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
namespace.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -135,18 +135,21 @@ func (namespaceFinalizeStrategy) PrepareForUpdate(ctx api.Context, obj, old runt
|
|||||||
newNamespace.Status = oldNamespace.Status
|
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.
|
// MatchNamespace returns a generic matcher for a given label and field selector.
|
||||||
func MatchNamespace(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchNamespace(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
namespaceObj, ok := obj.(*api.Namespace)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a namespace")
|
|
||||||
}
|
|
||||||
return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ func NewStorage(opts generic.RESTOptions, kubeletClientConfig client.KubeletClie
|
|||||||
prefix,
|
prefix,
|
||||||
node.Strategy,
|
node.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
node.GetAttrs,
|
||||||
node.NodeNameTriggerFunc)
|
node.NodeNameTriggerFunc)
|
||||||
|
|
||||||
store := ®istry.Store{
|
store := ®istry.Store{
|
||||||
|
@ -144,27 +144,21 @@ func NodeToSelectableFields(node *api.Node) fields.Set {
|
|||||||
return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
|
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.
|
// MatchNode returns a generic matcher for a given label and field selector.
|
||||||
func MatchNode(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate {
|
func MatchNode(label labels.Selector, field fields.Selector) pkgstorage.SelectionPredicate {
|
||||||
return pkgstorage.SelectionPredicate{
|
return pkgstorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
IndexFields: []string{"metadata.name"},
|
IndexFields: []string{"metadata.name"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
persistentvolume.Strategy,
|
persistentvolume.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
persistentvolume.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,18 +95,21 @@ func (persistentvolumeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old r
|
|||||||
return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))
|
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.
|
// MatchPersistentVolume returns a generic matcher for a given label and field selector.
|
||||||
func MatchPersistentVolumes(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchPersistentVolumes(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
persistentvolumeObj, ok := obj.(*api.PersistentVolume)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a persistentvolume")
|
|
||||||
}
|
|
||||||
return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
persistentvolumeclaim.Strategy,
|
persistentvolumeclaim.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
persistentvolumeclaim.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,18 +95,21 @@ func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx api.Context, obj,
|
|||||||
return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))
|
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.
|
// MatchPersistentVolumeClaim returns a generic matcher for a given label and field selector.
|
||||||
func MatchPersistentVolumeClaim(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchPersistentVolumeClaim(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a persistentvolumeclaim")
|
|
||||||
}
|
|
||||||
return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ func NewStorage(opts generic.RESTOptions, k client.ConnectionInfoGetter, proxyTr
|
|||||||
prefix,
|
prefix,
|
||||||
pod.Strategy,
|
pod.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
pod.GetAttrs,
|
||||||
pod.NodeNameTriggerFunc,
|
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))
|
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.
|
// MatchPod returns a generic matcher for a given label and field selector.
|
||||||
func MatchPod(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchPod(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
IndexFields: []string{"spec.nodeName"},
|
IndexFields: []string{"spec.nodeName"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
podtemplate.Strategy,
|
podtemplate.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
podtemplate.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,16 +86,19 @@ func PodTemplateToSelectableFields(podTemplate *api.PodTemplate) fields.Set {
|
|||||||
return nil
|
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 {
|
func MatchPodTemplate(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
resourcequota.Strategy,
|
resourcequota.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
resourcequota.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -98,18 +98,21 @@ func (resourcequotaStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runt
|
|||||||
return validation.ValidateResourceQuotaStatusUpdate(obj.(*api.ResourceQuota), old.(*api.ResourceQuota))
|
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.
|
// MatchResourceQuota returns a generic matcher for a given label and field selector.
|
||||||
func MatchResourceQuota(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchResourceQuota(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
resourcequotaObj, ok := obj.(*api.ResourceQuota)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a resourcequota")
|
|
||||||
}
|
|
||||||
return labels.Set(resourcequotaObj.Labels), ResourceQuotaToSelectableFields(resourcequotaObj), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
secret.Strategy,
|
secret.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
secret.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -94,18 +94,21 @@ func (s strategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
|||||||
return nil
|
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.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
secret, ok := obj.(*api.Secret)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a secret")
|
|
||||||
}
|
|
||||||
return labels.Set(secret.Labels), SelectableFields(secret), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
service.Strategy,
|
service.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
service.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,17 +101,20 @@ func (svcStrategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
|||||||
return nil
|
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 {
|
func MatchServices(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
serviceaccount.Strategy,
|
serviceaccount.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
serviceaccount.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,18 +77,21 @@ func (strategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
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.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
sa, ok := obj.(*api.ServiceAccount)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a serviceaccount")
|
|
||||||
}
|
|
||||||
return labels.Set(sa.Labels), SelectableFields(sa), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
daemonset.Strategy,
|
daemonset.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
daemonset.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -110,20 +110,23 @@ func DaemonSetToSelectableFields(daemon *extensions.DaemonSet) fields.Set {
|
|||||||
return generic.ObjectMetaFieldsSet(&daemon.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&daemon.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
ds, ok := obj.(*extensions.DaemonSet)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a ds.")
|
||||||
|
}
|
||||||
|
return labels.Set(ds.ObjectMeta.Labels), DaemonSetToSelectableFields(ds), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchSetDaemon is the filter used by the generic etcd backend to route
|
// MatchSetDaemon is the filter used by the generic etcd backend to route
|
||||||
// watch events from etcd to clients of the apiserver only interested in specific
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchDaemonSet(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchDaemonSet(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
ds, ok := obj.(*extensions.DaemonSet)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a ds.")
|
|
||||||
}
|
|
||||||
return labels.Set(ds.ObjectMeta.Labels), DaemonSetToSelectableFields(ds), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *RollbackREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
deployment.Strategy,
|
deployment.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
deployment.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -128,19 +128,22 @@ func DeploymentToSelectableFields(deployment *extensions.Deployment) fields.Set
|
|||||||
return generic.ObjectMetaFieldsSet(&deployment.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&deployment.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
deployment, ok := obj.(*extensions.Deployment)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a deployment.")
|
||||||
|
}
|
||||||
|
return labels.Set(deployment.ObjectMeta.Labels), DeploymentToSelectableFields(deployment), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchDeployment is the filter used by the generic etcd backend to route
|
// MatchDeployment is the filter used by the generic etcd backend to route
|
||||||
// watch events from etcd to clients of the apiserver only interested in specific
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchDeployment(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchDeployment(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
deployment, ok := obj.(*extensions.Deployment)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a deployment.")
|
|
||||||
}
|
|
||||||
return labels.Set(deployment.ObjectMeta.Labels), DeploymentToSelectableFields(deployment), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
ingress.Strategy,
|
ingress.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
ingress.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -103,20 +103,23 @@ func IngressToSelectableFields(ingress *extensions.Ingress) fields.Set {
|
|||||||
return generic.ObjectMetaFieldsSet(&ingress.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&ingress.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
ingress, ok := obj.(*extensions.Ingress)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("Given object is not an Ingress.")
|
||||||
|
}
|
||||||
|
return labels.Set(ingress.ObjectMeta.Labels), IngressToSelectableFields(ingress), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchIngress is the filter used by the generic etcd backend to ingress
|
// MatchIngress is the filter used by the generic etcd backend to ingress
|
||||||
// watch events from etcd to clients of the apiserver only interested in specific
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchIngress(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchIngress(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
ingress, ok := obj.(*extensions.Ingress)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("Given object is not an Ingress.")
|
|
||||||
}
|
|
||||||
return labels.Set(ingress.ObjectMeta.Labels), IngressToSelectableFields(ingress), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
networkpolicy.Strategy,
|
networkpolicy.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
networkpolicy.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -96,18 +96,21 @@ func NetworkPolicyToSelectableFields(networkPolicy *extensions.NetworkPolicy) fi
|
|||||||
return generic.ObjectMetaFieldsSet(&networkPolicy.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&networkPolicy.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
networkPolicy, ok := obj.(*extensions.NetworkPolicy)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a NetworkPolicy.")
|
||||||
|
}
|
||||||
|
return labels.Set(networkPolicy.ObjectMeta.Labels), NetworkPolicyToSelectableFields(networkPolicy), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchNetworkPolicy is the filter used by the generic etcd backend to watch events
|
// MatchNetworkPolicy 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.
|
// from etcd to clients of the apiserver only interested in specific labels/fields.
|
||||||
func MatchNetworkPolicy(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchNetworkPolicy(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
networkPolicy, ok := obj.(*extensions.NetworkPolicy)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a NetworkPolicy.")
|
|
||||||
}
|
|
||||||
return labels.Set(networkPolicy.ObjectMeta.Labels), NetworkPolicyToSelectableFields(networkPolicy), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
podsecuritypolicy.Strategy,
|
podsecuritypolicy.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
podsecuritypolicy.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,18 +74,21 @@ func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.E
|
|||||||
return validation.ValidatePodSecurityPolicyUpdate(old.(*extensions.PodSecurityPolicy), obj.(*extensions.PodSecurityPolicy))
|
return validation.ValidatePodSecurityPolicyUpdate(old.(*extensions.PodSecurityPolicy), obj.(*extensions.PodSecurityPolicy))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
psp, ok := obj.(*extensions.PodSecurityPolicy)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a pod security policy.")
|
||||||
|
}
|
||||||
|
return labels.Set(psp.ObjectMeta.Labels), PodSecurityPolicyToSelectableFields(psp), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func MatchPodSecurityPolicy(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchPodSecurityPolicy(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
psp, ok := obj.(*extensions.PodSecurityPolicy)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a pod security policy.")
|
|
||||||
}
|
|
||||||
return labels.Set(psp.ObjectMeta.Labels), PodSecurityPolicyToSelectableFields(psp), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
replicaset.Strategy,
|
replicaset.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
replicaset.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -119,20 +119,23 @@ func ReplicaSetToSelectableFields(rs *extensions.ReplicaSet) fields.Set {
|
|||||||
return generic.MergeFieldsSets(objectMetaFieldsSet, rsSpecificFieldsSet)
|
return generic.MergeFieldsSets(objectMetaFieldsSet, rsSpecificFieldsSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
rs, ok := obj.(*extensions.ReplicaSet)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("Given object is not a ReplicaSet.")
|
||||||
|
}
|
||||||
|
return labels.Set(rs.ObjectMeta.Labels), ReplicaSetToSelectableFields(rs), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchReplicaSet is the filter used by the generic etcd backend to route
|
// MatchReplicaSet is the filter used by the generic etcd backend to route
|
||||||
// watch events from etcd to clients of the apiserver only interested in specific
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
// labels/fields.
|
// labels/fields.
|
||||||
func MatchReplicaSet(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchReplicaSet(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
rs, ok := obj.(*extensions.ReplicaSet)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("Given object is not a ReplicaSet.")
|
|
||||||
}
|
|
||||||
return labels.Set(rs.ObjectMeta.Labels), ReplicaSetToSelectableFields(rs), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,18 +77,21 @@ func (strategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
tpr, ok := obj.(*extensions.ThirdPartyResource)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a ThirdPartyResource")
|
||||||
|
}
|
||||||
|
return labels.Set(tpr.Labels), SelectableFields(tpr), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
tpr, ok := obj.(*extensions.ThirdPartyResource)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a ThirdPartyResource")
|
|
||||||
}
|
|
||||||
return labels.Set(tpr.Labels), SelectableFields(tpr), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,18 +74,21 @@ func (strategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
tprd, ok := obj.(*extensions.ThirdPartyResourceData)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a ThirdPartyResourceData")
|
||||||
|
}
|
||||||
|
return labels.Set(tprd.Labels), SelectableFields(tprd), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
tprd, ok := obj.(*extensions.ThirdPartyResourceData)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a ThirdPartyResourceData")
|
|
||||||
}
|
|
||||||
return labels.Set(tprd.Labels), SelectableFields(tprd), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ go_library(
|
|||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/rest:go_default_library",
|
"//pkg/api/rest:go_default_library",
|
||||||
"//pkg/fields:go_default_library",
|
"//pkg/fields:go_default_library",
|
||||||
|
"//pkg/labels:go_default_library",
|
||||||
"//pkg/runtime:go_default_library",
|
"//pkg/runtime:go_default_library",
|
||||||
"//pkg/storage:go_default_library",
|
"//pkg/storage:go_default_library",
|
||||||
"//pkg/storage/storagebackend:go_default_library",
|
"//pkg/storage/storagebackend:go_default_library",
|
||||||
|
@ -18,6 +18,8 @@ package registry
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api/rest"
|
"k8s.io/kubernetes/pkg/api/rest"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/storage"
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
@ -34,6 +36,7 @@ func StorageWithCacher(
|
|||||||
resourcePrefix string,
|
resourcePrefix string,
|
||||||
scopeStrategy rest.NamespaceScopedStrategy,
|
scopeStrategy rest.NamespaceScopedStrategy,
|
||||||
newListFunc func() runtime.Object,
|
newListFunc func() runtime.Object,
|
||||||
|
getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error),
|
||||||
triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
|
triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
|
||||||
|
|
||||||
s, d := generic.NewRawStorage(storageConfig)
|
s, d := generic.NewRawStorage(storageConfig)
|
||||||
@ -46,6 +49,7 @@ func StorageWithCacher(
|
|||||||
Type: objectType,
|
Type: objectType,
|
||||||
ResourcePrefix: resourcePrefix,
|
ResourcePrefix: resourcePrefix,
|
||||||
NewListFunc: newListFunc,
|
NewListFunc: newListFunc,
|
||||||
|
GetAttrsFunc: getAttrsFunc,
|
||||||
TriggerPublisherFunc: triggerFunc,
|
TriggerPublisherFunc: triggerFunc,
|
||||||
Codec: storageConfig.Codec,
|
Codec: storageConfig.Codec,
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,11 @@ func NewTestGenericStoreRegistry(t *testing.T) (factory.DestroyFunc, *Store) {
|
|||||||
return newTestGenericStoreRegistry(t, false)
|
return newTestGenericStoreRegistry(t, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getPodAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
pod := obj.(*api.Pod)
|
||||||
|
return labels.Set{"name": pod.ObjectMeta.Name}, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// matchPodName returns selection predicate that matches any pod with name in the set.
|
// matchPodName returns selection predicate that matches any pod with name in the set.
|
||||||
// Makes testing simpler.
|
// Makes testing simpler.
|
||||||
func matchPodName(names ...string) storage.SelectionPredicate {
|
func matchPodName(names ...string) storage.SelectionPredicate {
|
||||||
@ -113,12 +118,9 @@ func matchPodName(names ...string) storage.SelectionPredicate {
|
|||||||
panic("Labels requirement must validate successfully")
|
panic("Labels requirement must validate successfully")
|
||||||
}
|
}
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: labels.Everything().Add(*l),
|
Label: labels.Everything().Add(*l),
|
||||||
Field: fields.Everything(),
|
Field: fields.Everything(),
|
||||||
GetAttrs: func(obj runtime.Object) (label labels.Set, field fields.Set, err error) {
|
GetAttrs: getPodAttrs,
|
||||||
pod := obj.(*api.Pod)
|
|
||||||
return labels.Set{"name": pod.ObjectMeta.Name}, nil, nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1249,6 +1251,7 @@ func newTestGenericStoreRegistry(t *testing.T, hasCacheEnabled bool) (factory.De
|
|||||||
Type: &api.Pod{},
|
Type: &api.Pod{},
|
||||||
ResourcePrefix: podPrefix,
|
ResourcePrefix: podPrefix,
|
||||||
KeyFunc: func(obj runtime.Object) (string, error) { return storage.NoNamespaceKeyFunc(podPrefix, obj) },
|
KeyFunc: func(obj runtime.Object) (string, error) { return storage.NoNamespaceKeyFunc(podPrefix, obj) },
|
||||||
|
GetAttrsFunc: getPodAttrs,
|
||||||
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
||||||
Codec: sc.Codec,
|
Codec: sc.Codec,
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ package generic
|
|||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/kubernetes/pkg/api/rest"
|
"k8s.io/kubernetes/pkg/api/rest"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/storage"
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
||||||
@ -34,6 +36,7 @@ type StorageDecorator func(
|
|||||||
resourcePrefix string,
|
resourcePrefix string,
|
||||||
scopeStrategy rest.NamespaceScopedStrategy,
|
scopeStrategy rest.NamespaceScopedStrategy,
|
||||||
newListFunc func() runtime.Object,
|
newListFunc func() runtime.Object,
|
||||||
|
getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error),
|
||||||
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc)
|
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc)
|
||||||
|
|
||||||
// Returns given 'storageInterface' without any decoration.
|
// Returns given 'storageInterface' without any decoration.
|
||||||
@ -44,6 +47,7 @@ func UndecoratedStorage(
|
|||||||
resourcePrefix string,
|
resourcePrefix string,
|
||||||
scopeStrategy rest.NamespaceScopedStrategy,
|
scopeStrategy rest.NamespaceScopedStrategy,
|
||||||
newListFunc func() runtime.Object,
|
newListFunc func() runtime.Object,
|
||||||
|
getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error),
|
||||||
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
|
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
|
||||||
return NewRawStorage(config)
|
return NewRawStorage(config)
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||||||
prefix,
|
prefix,
|
||||||
poddisruptionbudget.Strategy,
|
poddisruptionbudget.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
poddisruptionbudget.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,19 +102,22 @@ func PodDisruptionBudgetToSelectableFields(podDisruptionBudget *policy.PodDisrup
|
|||||||
return generic.ObjectMetaFieldsSet(&podDisruptionBudget.ObjectMeta, true)
|
return generic.ObjectMetaFieldsSet(&podDisruptionBudget.ObjectMeta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
podDisruptionBudget, ok := obj.(*policy.PodDisruptionBudget)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not a PodDisruptionBudget.")
|
||||||
|
}
|
||||||
|
return labels.Set(podDisruptionBudget.ObjectMeta.Labels), PodDisruptionBudgetToSelectableFields(podDisruptionBudget), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchPodDisruptionBudget is the filter used by the generic etcd backend to watch events
|
// MatchPodDisruptionBudget 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.
|
// from etcd to clients of the apiserver only interested in specific labels/fields.
|
||||||
func MatchPodDisruptionBudget(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
func MatchPodDisruptionBudget(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||||
return storage.SelectionPredicate{
|
return storage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
podDisruptionBudget, ok := obj.(*policy.PodDisruptionBudget)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a PodDisruptionBudget.")
|
|
||||||
}
|
|
||||||
return labels.Set(podDisruptionBudget.ObjectMeta.Labels), PodDisruptionBudgetToSelectableFields(podDisruptionBudget), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
clusterrole.Strategy,
|
clusterrole.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
clusterrole.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,18 +101,21 @@ func (s strategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
role, ok := obj.(*rbac.ClusterRole)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a ClusterRole")
|
||||||
|
}
|
||||||
|
return labels.Set(role.Labels), SelectableFields(role), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
role, ok := obj.(*rbac.ClusterRole)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a ClusterRole")
|
|
||||||
}
|
|
||||||
return labels.Set(role.Labels), SelectableFields(role), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
clusterrolebinding.Strategy,
|
clusterrolebinding.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
clusterrolebinding.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,18 +101,21 @@ func (s strategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
roleBinding, ok := obj.(*rbac.ClusterRoleBinding)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a ClusterRoleBinding")
|
||||||
|
}
|
||||||
|
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
roleBinding, ok := obj.(*rbac.ClusterRoleBinding)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a ClusterRoleBinding")
|
|
||||||
}
|
|
||||||
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
role.Strategy,
|
role.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
role.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,18 +101,21 @@ func (s strategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
role, ok := obj.(*rbac.Role)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a Role")
|
||||||
|
}
|
||||||
|
return labels.Set(role.Labels), SelectableFields(role), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
role, ok := obj.(*rbac.Role)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a Role")
|
|
||||||
}
|
|
||||||
return labels.Set(role.Labels), SelectableFields(role), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
rolebinding.Strategy,
|
rolebinding.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
rolebinding.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,18 +101,21 @@ func (s strategy) Export(ctx api.Context, obj runtime.Object, exact bool) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
roleBinding, ok := obj.(*rbac.RoleBinding)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("not a RoleBinding")
|
||||||
|
}
|
||||||
|
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Matcher returns a generic matcher for a given label and field selector.
|
// Matcher returns a generic matcher for a given label and field selector.
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
roleBinding, ok := obj.(*rbac.RoleBinding)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("not a RoleBinding")
|
|
||||||
}
|
|
||||||
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
|||||||
prefix,
|
prefix,
|
||||||
storageclass.Strategy,
|
storageclass.Strategy,
|
||||||
newListFunc,
|
newListFunc,
|
||||||
|
storageclass.GetAttrs,
|
||||||
storage.NoTriggerPublisher,
|
storage.NoTriggerPublisher,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,19 +77,21 @@ func (storageClassStrategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
|
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
cls, ok := obj.(*storage.StorageClass)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("given object is not of type StorageClass")
|
||||||
|
}
|
||||||
|
return labels.Set(cls.ObjectMeta.Labels), StorageClassToSelectableFields(cls), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MatchStorageClass returns a generic matcher for a given label and field selector.
|
// MatchStorageClass returns a generic matcher for a given label and field selector.
|
||||||
func MatchStorageClasses(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
func MatchStorageClasses(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||||
return apistorage.SelectionPredicate{
|
return apistorage.SelectionPredicate{
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: GetAttrs,
|
||||||
cls, ok := obj.(*storage.StorageClass)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not of type StorageClass")
|
|
||||||
}
|
|
||||||
|
|
||||||
return labels.Set(cls.ObjectMeta.Labels), StorageClassToSelectableFields(cls), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ go_test(
|
|||||||
"//pkg/api/unversioned:go_default_library",
|
"//pkg/api/unversioned:go_default_library",
|
||||||
"//pkg/fields:go_default_library",
|
"//pkg/fields:go_default_library",
|
||||||
"//pkg/labels:go_default_library",
|
"//pkg/labels:go_default_library",
|
||||||
|
"//pkg/registry/core/pod:go_default_library",
|
||||||
"//pkg/runtime:go_default_library",
|
"//pkg/runtime:go_default_library",
|
||||||
"//pkg/storage:go_default_library",
|
"//pkg/storage:go_default_library",
|
||||||
"//pkg/storage/etcd:go_default_library",
|
"//pkg/storage/etcd:go_default_library",
|
||||||
|
@ -31,6 +31,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/cache"
|
"k8s.io/kubernetes/pkg/client/cache"
|
||||||
"k8s.io/kubernetes/pkg/conversion"
|
"k8s.io/kubernetes/pkg/conversion"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util"
|
"k8s.io/kubernetes/pkg/util"
|
||||||
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
|
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
|
||||||
@ -60,6 +62,9 @@ type CacherConfig struct {
|
|||||||
// KeyFunc is used to get a key in the underyling storage for a given object.
|
// KeyFunc is used to get a key in the underyling storage for a given object.
|
||||||
KeyFunc func(runtime.Object) (string, error)
|
KeyFunc func(runtime.Object) (string, error)
|
||||||
|
|
||||||
|
// GetAttrsFunc is used to get object labels and fields.
|
||||||
|
GetAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error)
|
||||||
|
|
||||||
// TriggerPublisherFunc is used for optimizing amount of watchers that
|
// TriggerPublisherFunc is used for optimizing amount of watchers that
|
||||||
// needs to process an incoming event.
|
// needs to process an incoming event.
|
||||||
TriggerPublisherFunc TriggerPublisherFunc
|
TriggerPublisherFunc TriggerPublisherFunc
|
||||||
@ -126,7 +131,7 @@ func (i *indexedWatchers) terminateAll(objectType reflect.Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type filterObjectFunc func(string, runtime.Object) bool
|
type watchFilterFunc func(string, labels.Set, fields.Set) bool
|
||||||
|
|
||||||
// Cacher is responsible for serving WATCH and LIST requests for a given
|
// Cacher is responsible for serving WATCH and LIST requests for a given
|
||||||
// resource from its internal cache and updating its cache in the background
|
// resource from its internal cache and updating its cache in the background
|
||||||
@ -183,7 +188,7 @@ type Cacher struct {
|
|||||||
// internal cache and updating its cache in the background based on the given
|
// internal cache and updating its cache in the background based on the given
|
||||||
// configuration.
|
// configuration.
|
||||||
func NewCacherFromConfig(config CacherConfig) *Cacher {
|
func NewCacherFromConfig(config CacherConfig) *Cacher {
|
||||||
watchCache := newWatchCache(config.CacheCapacity, config.KeyFunc)
|
watchCache := newWatchCache(config.CacheCapacity, config.KeyFunc, config.GetAttrsFunc)
|
||||||
listerWatcher := newCacherListerWatcher(config.Storage, config.ResourcePrefix, config.NewListFunc)
|
listerWatcher := newCacherListerWatcher(config.Storage, config.ResourcePrefix, config.NewListFunc)
|
||||||
|
|
||||||
// Give this error when it is constructed rather than when you get the
|
// Give this error when it is constructed rather than when you get the
|
||||||
@ -327,7 +332,7 @@ func (c *Cacher) Watch(ctx context.Context, key string, resourceVersion string,
|
|||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
forget := forgetWatcher(c, c.watcherIdx, triggerValue, triggerSupported)
|
forget := forgetWatcher(c, c.watcherIdx, triggerValue, triggerSupported)
|
||||||
watcher := newCacheWatcher(watchRV, chanSize, initEvents, filterFunction(key, pred), forget)
|
watcher := newCacheWatcher(watchRV, chanSize, initEvents, watchFilterFunction(key, pred), forget)
|
||||||
|
|
||||||
c.watchers.addWatcher(watcher, c.watcherIdx, triggerValue, triggerSupported)
|
c.watchers.addWatcher(watcher, c.watcherIdx, triggerValue, triggerSupported)
|
||||||
c.watcherIdx++
|
c.watcherIdx++
|
||||||
@ -599,7 +604,7 @@ func forgetWatcher(c *Cacher, index int, triggerValue string, triggerSupported b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterFunction(key string, p SelectionPredicate) filterObjectFunc {
|
func filterFunction(key string, p SelectionPredicate) func(string, runtime.Object) bool {
|
||||||
f := SimpleFilter(p)
|
f := SimpleFilter(p)
|
||||||
filterFunc := func(objKey string, obj runtime.Object) bool {
|
filterFunc := func(objKey string, obj runtime.Object) bool {
|
||||||
if !hasPathPrefix(objKey, key) {
|
if !hasPathPrefix(objKey, key) {
|
||||||
@ -610,6 +615,16 @@ func filterFunction(key string, p SelectionPredicate) filterObjectFunc {
|
|||||||
return filterFunc
|
return filterFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func watchFilterFunction(key string, p SelectionPredicate) watchFilterFunc {
|
||||||
|
filterFunc := func(objKey string, label labels.Set, field fields.Set) bool {
|
||||||
|
if !hasPathPrefix(objKey, key) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return p.MatchesLabelsAndFields(label, field)
|
||||||
|
}
|
||||||
|
return filterFunc
|
||||||
|
}
|
||||||
|
|
||||||
// Returns resource version to which the underlying cache is synced.
|
// Returns resource version to which the underlying cache is synced.
|
||||||
func (c *Cacher) LastSyncResourceVersion() (uint64, error) {
|
func (c *Cacher) LastSyncResourceVersion() (uint64, error) {
|
||||||
c.ready.wait()
|
c.ready.wait()
|
||||||
@ -696,12 +711,12 @@ type cacheWatcher struct {
|
|||||||
sync.Mutex
|
sync.Mutex
|
||||||
input chan watchCacheEvent
|
input chan watchCacheEvent
|
||||||
result chan watch.Event
|
result chan watch.Event
|
||||||
filter filterObjectFunc
|
filter watchFilterFunc
|
||||||
stopped bool
|
stopped bool
|
||||||
forget func(bool)
|
forget func(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCacheWatcher(resourceVersion uint64, chanSize int, initEvents []watchCacheEvent, filter filterObjectFunc, forget func(bool)) *cacheWatcher {
|
func newCacheWatcher(resourceVersion uint64, chanSize int, initEvents []watchCacheEvent, filter watchFilterFunc, forget func(bool)) *cacheWatcher {
|
||||||
watcher := &cacheWatcher{
|
watcher := &cacheWatcher{
|
||||||
input: make(chan watchCacheEvent, chanSize),
|
input: make(chan watchCacheEvent, chanSize),
|
||||||
result: make(chan watch.Event, chanSize),
|
result: make(chan watch.Event, chanSize),
|
||||||
@ -779,10 +794,10 @@ func (c *cacheWatcher) add(event *watchCacheEvent, timeout *time.Duration) {
|
|||||||
|
|
||||||
// NOTE: sendWatchCacheEvent is assumed to not modify <event> !!!
|
// NOTE: sendWatchCacheEvent is assumed to not modify <event> !!!
|
||||||
func (c *cacheWatcher) sendWatchCacheEvent(event *watchCacheEvent) {
|
func (c *cacheWatcher) sendWatchCacheEvent(event *watchCacheEvent) {
|
||||||
curObjPasses := event.Type != watch.Deleted && c.filter(event.Key, event.Object)
|
curObjPasses := event.Type != watch.Deleted && c.filter(event.Key, event.ObjLabels, event.ObjFields)
|
||||||
oldObjPasses := false
|
oldObjPasses := false
|
||||||
if event.PrevObject != nil {
|
if event.PrevObject != nil {
|
||||||
oldObjPasses = c.filter(event.Key, event.PrevObject)
|
oldObjPasses = c.filter(event.Key, event.PrevObjLabels, event.PrevObjFields)
|
||||||
}
|
}
|
||||||
if !curObjPasses && !oldObjPasses {
|
if !curObjPasses && !oldObjPasses {
|
||||||
// Watcher is not interested in that object.
|
// Watcher is not interested in that object.
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
corepod "k8s.io/kubernetes/pkg/registry/core/pod"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/storage"
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
|
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
|
||||||
@ -60,6 +61,7 @@ func newTestCacher(s storage.Interface, cap int) *storage.Cacher {
|
|||||||
Type: &api.Pod{},
|
Type: &api.Pod{},
|
||||||
ResourcePrefix: prefix,
|
ResourcePrefix: prefix,
|
||||||
KeyFunc: func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) },
|
KeyFunc: func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) },
|
||||||
|
GetAttrsFunc: corepod.GetAttrs,
|
||||||
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
||||||
Codec: testapi.Default.Codec(),
|
Codec: testapi.Default.Codec(),
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,25 @@ func (s *SelectionPredicate) Matches(obj runtime.Object) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
matched := s.Label.Matches(labels)
|
matched := s.Label.Matches(labels)
|
||||||
if s.Field != nil {
|
if matched && s.Field != nil {
|
||||||
matched = (matched && s.Field.Matches(fields))
|
matched = (matched && s.Field.Matches(fields))
|
||||||
}
|
}
|
||||||
return matched, nil
|
return matched, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchesLabelsAndFields returns true if the given labels and fields
|
||||||
|
// match s.Label and s.Field.
|
||||||
|
func (s *SelectionPredicate) MatchesLabelsAndFields(l labels.Set, f fields.Set) bool {
|
||||||
|
if s.Label.Empty() && s.Field.Empty() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
matched := s.Label.Matches(l)
|
||||||
|
if matched && s.Field != nil {
|
||||||
|
matched = (matched && s.Field.Matches(f))
|
||||||
|
}
|
||||||
|
return matched
|
||||||
|
}
|
||||||
|
|
||||||
// MatchesSingle will return (name, true) if and only if s.Field matches on the object's
|
// MatchesSingle will return (name, true) if and only if s.Field matches on the object's
|
||||||
// name.
|
// name.
|
||||||
func (s *SelectionPredicate) MatchesSingle() (string, bool) {
|
func (s *SelectionPredicate) MatchesSingle() (string, bool) {
|
||||||
|
@ -26,6 +26,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/api/meta"
|
"k8s.io/kubernetes/pkg/api/meta"
|
||||||
"k8s.io/kubernetes/pkg/client/cache"
|
"k8s.io/kubernetes/pkg/client/cache"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util"
|
"k8s.io/kubernetes/pkg/util"
|
||||||
"k8s.io/kubernetes/pkg/util/clock"
|
"k8s.io/kubernetes/pkg/util/clock"
|
||||||
@ -45,7 +47,11 @@ const (
|
|||||||
type watchCacheEvent struct {
|
type watchCacheEvent struct {
|
||||||
Type watch.EventType
|
Type watch.EventType
|
||||||
Object runtime.Object
|
Object runtime.Object
|
||||||
|
ObjLabels labels.Set
|
||||||
|
ObjFields fields.Set
|
||||||
PrevObject runtime.Object
|
PrevObject runtime.Object
|
||||||
|
PrevObjLabels labels.Set
|
||||||
|
PrevObjFields fields.Set
|
||||||
Key string
|
Key string
|
||||||
ResourceVersion uint64
|
ResourceVersion uint64
|
||||||
}
|
}
|
||||||
@ -93,6 +99,9 @@ type watchCache struct {
|
|||||||
// keyFunc is used to get a key in the underlying storage for a given object.
|
// keyFunc is used to get a key in the underlying storage for a given object.
|
||||||
keyFunc func(runtime.Object) (string, error)
|
keyFunc func(runtime.Object) (string, error)
|
||||||
|
|
||||||
|
// getAttrsFunc is used to get labels and fields of an object.
|
||||||
|
getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error)
|
||||||
|
|
||||||
// cache is used a cyclic buffer - its first element (with the smallest
|
// cache is used a cyclic buffer - its first element (with the smallest
|
||||||
// resourceVersion) is defined by startIndex, its last element is defined
|
// resourceVersion) is defined by startIndex, its last element is defined
|
||||||
// by endIndex (if cache is full it will be startIndex + capacity).
|
// by endIndex (if cache is full it will be startIndex + capacity).
|
||||||
@ -122,10 +131,14 @@ type watchCache struct {
|
|||||||
clock clock.Clock
|
clock clock.Clock
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWatchCache(capacity int, keyFunc func(runtime.Object) (string, error)) *watchCache {
|
func newWatchCache(
|
||||||
|
capacity int,
|
||||||
|
keyFunc func(runtime.Object) (string, error),
|
||||||
|
getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error)) *watchCache {
|
||||||
wc := &watchCache{
|
wc := &watchCache{
|
||||||
capacity: capacity,
|
capacity: capacity,
|
||||||
keyFunc: keyFunc,
|
keyFunc: keyFunc,
|
||||||
|
getAttrsFunc: getAttrsFunc,
|
||||||
cache: make([]watchCacheElement, capacity),
|
cache: make([]watchCacheElement, capacity),
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
endIndex: 0,
|
endIndex: 0,
|
||||||
@ -213,14 +226,28 @@ func (w *watchCache) processEvent(event watch.Event, resourceVersion uint64, upd
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
objLabels, objFields, err := w.getAttrsFunc(event.Object)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
var prevObject runtime.Object
|
var prevObject runtime.Object
|
||||||
|
var prevObjLabels labels.Set
|
||||||
|
var prevObjFields fields.Set
|
||||||
if exists {
|
if exists {
|
||||||
prevObject = previous.(*storeElement).Object
|
prevObject = previous.(*storeElement).Object
|
||||||
|
prevObjLabels, prevObjFields, err = w.getAttrsFunc(prevObject)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
watchCacheEvent := watchCacheEvent{
|
watchCacheEvent := watchCacheEvent{
|
||||||
Type: event.Type,
|
Type: event.Type,
|
||||||
Object: event.Object,
|
Object: event.Object,
|
||||||
|
ObjLabels: objLabels,
|
||||||
|
ObjFields: objFields,
|
||||||
PrevObject: prevObject,
|
PrevObject: prevObject,
|
||||||
|
PrevObjLabels: prevObjLabels,
|
||||||
|
PrevObjFields: prevObjFields,
|
||||||
Key: key,
|
Key: key,
|
||||||
ResourceVersion: resourceVersion,
|
ResourceVersion: resourceVersion,
|
||||||
}
|
}
|
||||||
@ -394,9 +421,15 @@ func (w *watchCache) GetAllEventsSinceThreadUnsafe(resourceVersion uint64) ([]wa
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("not a storeElement: %v", elem)
|
return nil, fmt.Errorf("not a storeElement: %v", elem)
|
||||||
}
|
}
|
||||||
|
objLabels, objFields, err := w.getAttrsFunc(elem.Object)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
result[i] = watchCacheEvent{
|
result[i] = watchCacheEvent{
|
||||||
Type: watch.Added,
|
Type: watch.Added,
|
||||||
Object: elem.Object,
|
Object: elem.Object,
|
||||||
|
ObjLabels: objLabels,
|
||||||
|
ObjFields: objFields,
|
||||||
Key: elem.Key,
|
Key: elem.Key,
|
||||||
ResourceVersion: w.resourceVersion,
|
ResourceVersion: w.resourceVersion,
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/cache"
|
"k8s.io/kubernetes/pkg/client/cache"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util/clock"
|
"k8s.io/kubernetes/pkg/util/clock"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
@ -48,7 +50,10 @@ func newTestWatchCache(capacity int) *watchCache {
|
|||||||
keyFunc := func(obj runtime.Object) (string, error) {
|
keyFunc := func(obj runtime.Object) (string, error) {
|
||||||
return NamespaceKeyFunc("prefix", obj)
|
return NamespaceKeyFunc("prefix", obj)
|
||||||
}
|
}
|
||||||
wc := newWatchCache(capacity, keyFunc)
|
getAttrsFunc := func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
wc := newWatchCache(capacity, keyFunc, getAttrsFunc)
|
||||||
wc.clock = clock.NewFakeClock(time.Now())
|
wc.clock = clock.NewFakeClock(time.Now())
|
||||||
return wc
|
return wc
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user