diff --git a/pkg/registry/controller/strategy.go b/pkg/registry/controller/strategy.go index 4989f185fa8..d06c32212ad 100644 --- a/pkg/registry/controller/strategy.go +++ b/pkg/registry/controller/strategy.go @@ -98,12 +98,13 @@ func (rcStrategy) AllowUnconditionalUpdate() bool { return true } -// ControllerToSelectableFields returns a label set that represents the object. +// ControllerToSelectableFields returns a field set that represents the object. func ControllerToSelectableFields(controller *api.ReplicationController) fields.Set { - return fields.Set{ - "metadata.name": controller.Name, + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(controller.ObjectMeta) + controllerSpecificFieldsSet := fields.Set{ "status.replicas": strconv.Itoa(controller.Status.Replicas), } + return generic.MergeFieldsSets(objectMetaFieldsSet, controllerSpecificFieldsSet) } // MatchController is the filter used by the generic etcd backend to route diff --git a/pkg/registry/daemonset/strategy.go b/pkg/registry/daemonset/strategy.go index 3d03802fc80..98152db1b60 100644 --- a/pkg/registry/daemonset/strategy.go +++ b/pkg/registry/daemonset/strategy.go @@ -102,9 +102,7 @@ func (daemonSetStrategy) AllowUnconditionalUpdate() bool { // DaemonSetToSelectableFields returns a field set that represents the object. func DaemonSetToSelectableFields(daemon *extensions.DaemonSet) fields.Set { - return fields.Set{ - "metadata.name": daemon.Name, - } + return generic.ObjectMetaFieldsSet(daemon.ObjectMeta) } // MatchSetDaemon is the filter used by the generic etcd backend to route diff --git a/pkg/registry/deployment/strategy.go b/pkg/registry/deployment/strategy.go index 01b651c08da..9a85d225151 100644 --- a/pkg/registry/deployment/strategy.go +++ b/pkg/registry/deployment/strategy.go @@ -74,9 +74,7 @@ func (deploymentStrategy) AllowUnconditionalUpdate() bool { // DeploymentToSelectableFields returns a field set that represents the object. func DeploymentToSelectableFields(deployment *extensions.Deployment) fields.Set { - return fields.Set{ - "metadata.name": deployment.Name, - } + return generic.ObjectMetaFieldsSet(deployment.ObjectMeta) } // MatchDeployment is the filter used by the generic etcd backend to route diff --git a/pkg/registry/endpoint/strategy.go b/pkg/registry/endpoint/strategy.go index a31b6cb668a..0366d87a557 100644 --- a/pkg/registry/endpoint/strategy.go +++ b/pkg/registry/endpoint/strategy.go @@ -89,7 +89,5 @@ func EndpointsAttributes(obj runtime.Object) (objLabels labels.Set, objFields fi if !ok { return nil, nil, fmt.Errorf("invalid object type %#v", obj) } - return endpoints.Labels, fields.Set{ - "metadata.name": endpoints.Name, - }, nil + return endpoints.Labels, generic.ObjectMetaFieldsSet(endpoints.ObjectMeta), nil } diff --git a/pkg/registry/event/strategy.go b/pkg/registry/event/strategy.go index 8f5e2df558f..9c8f0dc7735 100644 --- a/pkg/registry/event/strategy.go +++ b/pkg/registry/event/strategy.go @@ -79,8 +79,9 @@ func getAttrs(obj runtime.Object) (objLabels labels.Set, objFields fields.Set, e if l == nil { l = labels.Set{} } - return l, fields.Set{ - "metadata.name": event.Name, + + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(event.ObjectMeta) + specificFieldsSet := fields.Set{ "involvedObject.kind": event.InvolvedObject.Kind, "involvedObject.namespace": event.InvolvedObject.Namespace, "involvedObject.name": event.InvolvedObject.Name, @@ -90,5 +91,6 @@ func getAttrs(obj runtime.Object) (objLabels labels.Set, objFields fields.Set, e "involvedObject.fieldPath": event.InvolvedObject.FieldPath, "reason": event.Reason, "source": event.Source.Component, - }, nil + } + return l, generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet), nil } diff --git a/pkg/registry/event/strategy_test.go b/pkg/registry/event/strategy_test.go index 03ebd771db2..7571ca71d53 100644 --- a/pkg/registry/event/strategy_test.go +++ b/pkg/registry/event/strategy_test.go @@ -42,7 +42,10 @@ func testEvent(name string) *api.Event { func TestGetAttrs(t *testing.T) { eventA := &api.Event{ - ObjectMeta: api.ObjectMeta{Name: "f0118"}, + ObjectMeta: api.ObjectMeta{ + Name: "f0118", + Namespace: "default", + }, InvolvedObject: api.ObjectReference{ Kind: "Pod", Name: "foo", @@ -64,6 +67,7 @@ func TestGetAttrs(t *testing.T) { } expect := fields.Set{ "metadata.name": "f0118", + "metadata.namespace": "default", "involvedObject.kind": "Pod", "involvedObject.name": "foo", "involvedObject.namespace": "baz", diff --git a/pkg/registry/generic/matcher.go b/pkg/registry/generic/matcher.go index a7e8705c1c4..16282ea7eb4 100644 --- a/pkg/registry/generic/matcher.go +++ b/pkg/registry/generic/matcher.go @@ -17,6 +17,7 @@ limitations under the License. package generic import ( + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" @@ -25,6 +26,22 @@ import ( // AttrFunc returns label and field sets for List or Watch to compare against, or an error. type AttrFunc func(obj runtime.Object) (label labels.Set, field fields.Set, err error) +// ObjectMetaFieldsSet returns a fields set that represents the ObjectMeta. +func ObjectMetaFieldsSet(objectMeta api.ObjectMeta) fields.Set { + return fields.Set{ + "metadata.name": objectMeta.Name, + "metadata.namespace": objectMeta.Namespace, + } +} + +// MergeFieldsSets merges a fields'set from fragment into the source. +func MergeFieldsSets(source fields.Set, fragment fields.Set) fields.Set { + for k, value := range fragment { + source[k] = value + } + return source +} + // SelectionPredicate implements a generic predicate that can be passed to // GenericRegistry's List or Watch methods. Implements the Matcher interface. type SelectionPredicate struct { diff --git a/pkg/registry/ingress/strategy.go b/pkg/registry/ingress/strategy.go index f6cc8c9d785..95ab183a3e9 100644 --- a/pkg/registry/ingress/strategy.go +++ b/pkg/registry/ingress/strategy.go @@ -93,11 +93,9 @@ func (ingressStrategy) AllowUnconditionalUpdate() bool { return true } -// IngressToSelectableFields returns a label set that represents the object. +// IngressToSelectableFields returns a field set that represents the object. func IngressToSelectableFields(ingress *extensions.Ingress) fields.Set { - return fields.Set{ - "metadata.name": ingress.Name, - } + return generic.ObjectMetaFieldsSet(ingress.ObjectMeta) } // MatchIngress is the filter used by the generic etcd backend to ingress diff --git a/pkg/registry/job/strategy.go b/pkg/registry/job/strategy.go index b6221db434b..0b489332e8f 100644 --- a/pkg/registry/job/strategy.go +++ b/pkg/registry/job/strategy.go @@ -97,10 +97,11 @@ func (jobStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object // JobSelectableFields returns a field set that represents the object for matching purposes. func JobToSelectableFields(job *extensions.Job) fields.Set { - return fields.Set{ - "metadata.name": job.Name, + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(job.ObjectMeta) + specificFieldsSet := fields.Set{ "status.successful": strconv.Itoa(job.Status.Succeeded), } + return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet) } // MatchJob is the filter used by the generic etcd backend to route diff --git a/pkg/registry/namespace/strategy.go b/pkg/registry/namespace/strategy.go index 424684f28c6..f0acec3b1ea 100644 --- a/pkg/registry/namespace/strategy.go +++ b/pkg/registry/namespace/strategy.go @@ -144,10 +144,11 @@ func MatchNamespace(label labels.Selector, field fields.Selector) generic.Matche // NamespaceToSelectableFields returns a label set that represents the object func NamespaceToSelectableFields(namespace *api.Namespace) labels.Set { - return labels.Set{ - "metadata.name": namespace.Name, - "status.phase": string(namespace.Status.Phase), + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(namespace.ObjectMeta) + specificFieldsSet := fields.Set{ + "status.phase": string(namespace.Status.Phase), // This is a bug, but we need to support it for backward compatibility. "name": namespace.Name, } + return labels.Set(generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)) } diff --git a/pkg/registry/persistentvolume/strategy.go b/pkg/registry/persistentvolume/strategy.go index 2def1d0d8b2..9ebb0837a63 100644 --- a/pkg/registry/persistentvolume/strategy.go +++ b/pkg/registry/persistentvolume/strategy.go @@ -104,9 +104,10 @@ func MatchPersistentVolumes(label labels.Selector, field fields.Selector) generi // PersistentVolumeToSelectableFields returns a label set that represents the object func PersistentVolumeToSelectableFields(persistentvolume *api.PersistentVolume) labels.Set { - return labels.Set{ - "metadata.name": persistentvolume.Name, + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(persistentvolume.ObjectMeta) + specificFieldsSet := fields.Set{ // This is a bug, but we need to support it for backward compatibility. "name": persistentvolume.Name, } + return labels.Set(generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)) } diff --git a/pkg/registry/persistentvolumeclaim/strategy.go b/pkg/registry/persistentvolumeclaim/strategy.go index a6185d95d3f..57fc3666e20 100644 --- a/pkg/registry/persistentvolumeclaim/strategy.go +++ b/pkg/registry/persistentvolumeclaim/strategy.go @@ -104,9 +104,10 @@ func MatchPersistentVolumeClaim(label labels.Selector, field fields.Selector) ge // PersistentVolumeClaimToSelectableFields returns a label set that represents the object func PersistentVolumeClaimToSelectableFields(persistentvolumeclaim *api.PersistentVolumeClaim) labels.Set { - return labels.Set{ - "metadata.name": persistentvolumeclaim.Name, + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(persistentvolumeclaim.ObjectMeta) + specificFieldsSet := fields.Set{ // This is a bug, but we need to support it for backward compatibility. "name": persistentvolumeclaim.Name, } + return labels.Set(generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)) } diff --git a/pkg/registry/pod/strategy.go b/pkg/registry/pod/strategy.go index fbb977360d2..4aa57d03d62 100644 --- a/pkg/registry/pod/strategy.go +++ b/pkg/registry/pod/strategy.go @@ -163,14 +163,15 @@ func MatchPod(label labels.Selector, field fields.Selector) generic.Matcher { } } -// PodToSelectableFields returns a label set that represents the object +// PodToSelectableFields returns a field set that represents the object // TODO: fields are not labels, and the validation rules for them do not apply. func PodToSelectableFields(pod *api.Pod) fields.Set { - return fields.Set{ - "metadata.name": pod.Name, + objectMetaFieldsSet := generic.ObjectMetaFieldsSet(pod.ObjectMeta) + podSpecificFieldsSet := fields.Set{ "spec.nodeName": pod.Spec.NodeName, "status.phase": string(pod.Status.Phase), } + return generic.MergeFieldsSets(objectMetaFieldsSet, podSpecificFieldsSet) } // ResourceGetter is an interface for retrieving resources by ResourceLocation. diff --git a/pkg/registry/resourcequota/strategy.go b/pkg/registry/resourcequota/strategy.go index 0c1a8e7b2b6..e6735031040 100644 --- a/pkg/registry/resourcequota/strategy.go +++ b/pkg/registry/resourcequota/strategy.go @@ -107,7 +107,5 @@ func MatchResourceQuota(label labels.Selector, field fields.Selector) generic.Ma // ResourceQuotaToSelectableFields returns a label set that represents the object func ResourceQuotaToSelectableFields(resourcequota *api.ResourceQuota) labels.Set { - return labels.Set{ - "metadata.name": resourcequota.Name, - } + return labels.Set(generic.ObjectMetaFieldsSet(resourcequota.ObjectMeta)) } diff --git a/pkg/registry/serviceaccount/strategy.go b/pkg/registry/serviceaccount/strategy.go index 85a0c493f3f..91778aa3efa 100644 --- a/pkg/registry/serviceaccount/strategy.go +++ b/pkg/registry/serviceaccount/strategy.go @@ -86,7 +86,5 @@ func Matcher(label labels.Selector, field fields.Selector) generic.Matcher { // SelectableFields returns a label set that represents the object func SelectableFields(obj *api.ServiceAccount) labels.Set { - return labels.Set{ - "metadata.name": obj.Name, - } + return labels.Set(generic.ObjectMetaFieldsSet(obj.ObjectMeta)) }