diff --git a/pkg/client/listers/apps/internalversion/BUILD b/pkg/client/listers/apps/internalversion/BUILD index e898fe0e227..055e081477f 100644 --- a/pkg/client/listers/apps/internalversion/BUILD +++ b/pkg/client/listers/apps/internalversion/BUILD @@ -12,12 +12,15 @@ go_library( srcs = [ "expansion_generated.go", "statefulset.go", + "statefulset_expansion.go", ], tags = ["automanaged"], deps = [ + "//pkg/api:go_default_library", "//pkg/apis/apps:go_default_library", "//pkg/client/cache:go_default_library", "//vendor:k8s.io/apimachinery/pkg/api/errors", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/labels", ], ) diff --git a/pkg/client/listers/apps/internalversion/expansion_generated.go b/pkg/client/listers/apps/internalversion/expansion_generated.go index 6c420b4e128..f0badbce040 100644 --- a/pkg/client/listers/apps/internalversion/expansion_generated.go +++ b/pkg/client/listers/apps/internalversion/expansion_generated.go @@ -17,11 +17,3 @@ limitations under the License. // This file was automatically generated by lister-gen with arguments: --input-dirs=[k8s.io/kubernetes/pkg/api,k8s.io/kubernetes/pkg/api/v1,k8s.io/kubernetes/pkg/apis/abac,k8s.io/kubernetes/pkg/apis/abac/v0,k8s.io/kubernetes/pkg/apis/abac/v1beta1,k8s.io/kubernetes/pkg/apis/apps,k8s.io/kubernetes/pkg/apis/apps/v1beta1,k8s.io/kubernetes/pkg/apis/authentication,k8s.io/kubernetes/pkg/apis/authentication/v1beta1,k8s.io/kubernetes/pkg/apis/authorization,k8s.io/kubernetes/pkg/apis/authorization/v1beta1,k8s.io/kubernetes/pkg/apis/autoscaling,k8s.io/kubernetes/pkg/apis/autoscaling/v1,k8s.io/kubernetes/pkg/apis/batch,k8s.io/kubernetes/pkg/apis/batch/v1,k8s.io/kubernetes/pkg/apis/batch/v2alpha1,k8s.io/kubernetes/pkg/apis/certificates,k8s.io/kubernetes/pkg/apis/certificates/v1beta1,k8s.io/kubernetes/pkg/apis/componentconfig,k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1,k8s.io/kubernetes/pkg/apis/extensions,k8s.io/kubernetes/pkg/apis/extensions/v1beta1,k8s.io/kubernetes/pkg/apis/imagepolicy,k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1,k8s.io/kubernetes/pkg/apis/policy,k8s.io/kubernetes/pkg/apis/policy/v1alpha1,k8s.io/kubernetes/pkg/apis/policy/v1beta1,k8s.io/kubernetes/pkg/apis/rbac,k8s.io/kubernetes/pkg/apis/rbac/v1alpha1,k8s.io/kubernetes/pkg/apis/rbac/v1beta1,k8s.io/kubernetes/pkg/apis/storage,k8s.io/kubernetes/pkg/apis/storage/v1beta1] package internalversion - -// StatefulSetListerExpansion allows custom methods to be added to -// StatefulSetLister. -type StatefulSetListerExpansion interface{} - -// StatefulSetNamespaceListerExpansion allows custom methods to be added to -// StatefulSetNamespaeLister. -type StatefulSetNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/apps/internalversion/statefulset_expansion.go b/pkg/client/listers/apps/internalversion/statefulset_expansion.go new file mode 100644 index 00000000000..0b58cf6a817 --- /dev/null +++ b/pkg/client/listers/apps/internalversion/statefulset_expansion.go @@ -0,0 +1,75 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/apps" +) + +// StatefulSetListerExpansion allows custom methods to be added to +// StatefulSetLister. +type StatefulSetListerExpansion interface { + GetPodStatefulSets(pod *api.Pod) ([]*apps.StatefulSet, error) +} + +// StatefulSetNamespaceListerExpansion allows custom methods to be added to +// StatefulSetNamespaeLister. +type StatefulSetNamespaceListerExpansion interface{} + +// GetPodStatefulSets returns a list of StatefulSets managing a pod. Returns an error only if no matching StatefulSets are found. +func (s *statefulSetLister) GetPodStatefulSets(pod *api.Pod) ([]*apps.StatefulSet, error) { + var selector labels.Selector + var ps *apps.StatefulSet + + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no StatefulSets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.StatefulSets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var psList []*apps.StatefulSet + for i := range list { + ps = list[i] + if ps.Namespace != pod.Namespace { + continue + } + selector, err = metav1.LabelSelectorAsSelector(ps.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid selector: %v", err) + } + + // If a StatefulSet with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + psList = append(psList, ps) + } + + if len(psList) == 0 { + return nil, fmt.Errorf("could not find StatefulSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return psList, nil +} diff --git a/pkg/client/listers/apps/v1beta1/BUILD b/pkg/client/listers/apps/v1beta1/BUILD index f891b7d784d..47ce22e40c1 100644 --- a/pkg/client/listers/apps/v1beta1/BUILD +++ b/pkg/client/listers/apps/v1beta1/BUILD @@ -12,13 +12,16 @@ go_library( srcs = [ "expansion_generated.go", "statefulset.go", + "statefulset_expansion.go", ], tags = ["automanaged"], deps = [ + "//pkg/api/v1:go_default_library", "//pkg/apis/apps:go_default_library", "//pkg/apis/apps/v1beta1:go_default_library", "//pkg/client/cache:go_default_library", "//vendor:k8s.io/apimachinery/pkg/api/errors", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/labels", ], ) diff --git a/pkg/client/listers/apps/v1beta1/expansion_generated.go b/pkg/client/listers/apps/v1beta1/expansion_generated.go index 8db64323ea1..292e200e175 100644 --- a/pkg/client/listers/apps/v1beta1/expansion_generated.go +++ b/pkg/client/listers/apps/v1beta1/expansion_generated.go @@ -17,11 +17,3 @@ limitations under the License. // This file was automatically generated by lister-gen with arguments: --input-dirs=[k8s.io/kubernetes/pkg/api,k8s.io/kubernetes/pkg/api/v1,k8s.io/kubernetes/pkg/apis/abac,k8s.io/kubernetes/pkg/apis/abac/v0,k8s.io/kubernetes/pkg/apis/abac/v1beta1,k8s.io/kubernetes/pkg/apis/apps,k8s.io/kubernetes/pkg/apis/apps/v1beta1,k8s.io/kubernetes/pkg/apis/authentication,k8s.io/kubernetes/pkg/apis/authentication/v1beta1,k8s.io/kubernetes/pkg/apis/authorization,k8s.io/kubernetes/pkg/apis/authorization/v1beta1,k8s.io/kubernetes/pkg/apis/autoscaling,k8s.io/kubernetes/pkg/apis/autoscaling/v1,k8s.io/kubernetes/pkg/apis/batch,k8s.io/kubernetes/pkg/apis/batch/v1,k8s.io/kubernetes/pkg/apis/batch/v2alpha1,k8s.io/kubernetes/pkg/apis/certificates,k8s.io/kubernetes/pkg/apis/certificates/v1beta1,k8s.io/kubernetes/pkg/apis/componentconfig,k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1,k8s.io/kubernetes/pkg/apis/extensions,k8s.io/kubernetes/pkg/apis/extensions/v1beta1,k8s.io/kubernetes/pkg/apis/imagepolicy,k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1,k8s.io/kubernetes/pkg/apis/policy,k8s.io/kubernetes/pkg/apis/policy/v1alpha1,k8s.io/kubernetes/pkg/apis/policy/v1beta1,k8s.io/kubernetes/pkg/apis/rbac,k8s.io/kubernetes/pkg/apis/rbac/v1alpha1,k8s.io/kubernetes/pkg/apis/rbac/v1beta1,k8s.io/kubernetes/pkg/apis/storage,k8s.io/kubernetes/pkg/apis/storage/v1beta1] package v1beta1 - -// StatefulSetListerExpansion allows custom methods to be added to -// StatefulSetLister. -type StatefulSetListerExpansion interface{} - -// StatefulSetNamespaceListerExpansion allows custom methods to be added to -// StatefulSetNamespaeLister. -type StatefulSetNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/apps/v1beta1/statefulset_expansion.go b/pkg/client/listers/apps/v1beta1/statefulset_expansion.go new file mode 100644 index 00000000000..e032ae227f3 --- /dev/null +++ b/pkg/client/listers/apps/v1beta1/statefulset_expansion.go @@ -0,0 +1,75 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" + apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1" +) + +// StatefulSetListerExpansion allows custom methods to be added to +// StatefulSetLister. +type StatefulSetListerExpansion interface { + GetPodStatefulSets(pod *v1.Pod) ([]*apps.StatefulSet, error) +} + +// StatefulSetNamespaceListerExpansion allows custom methods to be added to +// StatefulSetNamespaeLister. +type StatefulSetNamespaceListerExpansion interface{} + +// GetPodStatefulSets returns a list of StatefulSets managing a pod. Returns an error only if no matching StatefulSets are found. +func (s *statefulSetLister) GetPodStatefulSets(pod *v1.Pod) ([]*apps.StatefulSet, error) { + var selector labels.Selector + var ps *apps.StatefulSet + + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no StatefulSets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.StatefulSets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var psList []*apps.StatefulSet + for i := range list { + ps = list[i] + if ps.Namespace != pod.Namespace { + continue + } + selector, err = metav1.LabelSelectorAsSelector(ps.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid selector: %v", err) + } + + // If a StatefulSet with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + psList = append(psList, ps) + } + + if len(psList) == 0 { + return nil, fmt.Errorf("could not find StatefulSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return psList, nil +} diff --git a/pkg/client/listers/core/internalversion/BUILD b/pkg/client/listers/core/internalversion/BUILD index 0ba0b0fdc6c..a48ad46689f 100644 --- a/pkg/client/listers/core/internalversion/BUILD +++ b/pkg/client/listers/core/internalversion/BUILD @@ -18,14 +18,17 @@ go_library( "limitrange.go", "namespace.go", "node.go", + "node_expansion.go", "persistentvolume.go", "persistentvolumeclaim.go", "pod.go", "podtemplate.go", "replicationcontroller.go", + "replicationcontroller_expansion.go", "resourcequota.go", "secret.go", "service.go", + "service_expansion.go", "serviceaccount.go", ], tags = ["automanaged"], diff --git a/pkg/client/listers/core/internalversion/expansion_generated.go b/pkg/client/listers/core/internalversion/expansion_generated.go index b088b7b04ff..188f3dc8eb8 100644 --- a/pkg/client/listers/core/internalversion/expansion_generated.go +++ b/pkg/client/listers/core/internalversion/expansion_generated.go @@ -58,10 +58,6 @@ type LimitRangeNamespaceListerExpansion interface{} // NamespaceLister. type NamespaceListerExpansion interface{} -// NodeListerExpansion allows custom methods to be added to -// NodeLister. -type NodeListerExpansion interface{} - // PersistentVolumeListerExpansion allows custom methods to be added to // PersistentVolumeLister. type PersistentVolumeListerExpansion interface{} @@ -90,14 +86,6 @@ type PodTemplateListerExpansion interface{} // PodTemplateNamespaeLister. type PodTemplateNamespaceListerExpansion interface{} -// ReplicationControllerListerExpansion allows custom methods to be added to -// ReplicationControllerLister. -type ReplicationControllerListerExpansion interface{} - -// ReplicationControllerNamespaceListerExpansion allows custom methods to be added to -// ReplicationControllerNamespaeLister. -type ReplicationControllerNamespaceListerExpansion interface{} - // ResourceQuotaListerExpansion allows custom methods to be added to // ResourceQuotaLister. type ResourceQuotaListerExpansion interface{} @@ -114,14 +102,6 @@ type SecretListerExpansion interface{} // SecretNamespaeLister. type SecretNamespaceListerExpansion interface{} -// ServiceListerExpansion allows custom methods to be added to -// ServiceLister. -type ServiceListerExpansion interface{} - -// ServiceNamespaceListerExpansion allows custom methods to be added to -// ServiceNamespaeLister. -type ServiceNamespaceListerExpansion interface{} - // ServiceAccountListerExpansion allows custom methods to be added to // ServiceAccountLister. type ServiceAccountListerExpansion interface{} diff --git a/pkg/client/listers/core/internalversion/node_expansion.go b/pkg/client/listers/core/internalversion/node_expansion.go new file mode 100644 index 00000000000..465c59e3ba2 --- /dev/null +++ b/pkg/client/listers/core/internalversion/node_expansion.go @@ -0,0 +1,48 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" +) + +// NodeConditionPredicate is a function that indicates whether the given node's conditions meet +// some set of criteria defined by the function. +type NodeConditionPredicate func(node *api.Node) bool + +// NodeListerExpansion allows custom methods to be added to +// NodeLister. +type NodeListerExpansion interface { + ListWithPredicate(predicate NodeConditionPredicate) ([]*api.Node, error) +} + +func (l *nodeLister) ListWithPredicate(predicate NodeConditionPredicate) ([]*api.Node, error) { + nodes, err := l.List(labels.Everything()) + if err != nil { + return nil, err + } + + var filtered []*api.Node + for i := range nodes { + if predicate(nodes[i]) { + filtered = append(filtered, nodes[i]) + } + } + + return filtered, nil +} diff --git a/pkg/client/listers/core/internalversion/replicationcontroller_expansion.go b/pkg/client/listers/core/internalversion/replicationcontroller_expansion.go new file mode 100644 index 00000000000..e9070bd5abf --- /dev/null +++ b/pkg/client/listers/core/internalversion/replicationcontroller_expansion.go @@ -0,0 +1,64 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" +) + +// ReplicationControllerListerExpansion allows custom methods to be added to +// ReplicationControllerLister. +type ReplicationControllerListerExpansion interface { + GetPodControllers(pod *api.Pod) ([]*api.ReplicationController, error) +} + +// ReplicationControllerNamespaceListerExpansion allows custom methods to be added to +// ReplicationControllerNamespaeLister. +type ReplicationControllerNamespaceListerExpansion interface{} + +// GetPodControllers returns a list of replication controllers managing a pod. Returns an error only if no matching controllers are found. +func (s *replicationControllerLister) GetPodControllers(pod *api.Pod) ([]*api.ReplicationController, error) { + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no controllers found for pod %v because it has no labels", pod.Name) + } + + items, err := s.ReplicationControllers(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var controllers []*api.ReplicationController + for i := range items { + rc := items[i] + selector := labels.Set(rc.Spec.Selector).AsSelectorPreValidated() + + // If an rc with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + controllers = append(controllers, rc) + } + + if len(controllers) == 0 { + return nil, fmt.Errorf("could not find controller for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return controllers, nil +} diff --git a/pkg/client/listers/core/internalversion/service_expansion.go b/pkg/client/listers/core/internalversion/service_expansion.go new file mode 100644 index 00000000000..a12824716b7 --- /dev/null +++ b/pkg/client/listers/core/internalversion/service_expansion.go @@ -0,0 +1,56 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" +) + +// ServiceListerExpansion allows custom methods to be added to +// ServiceLister. +type ServiceListerExpansion interface { + GetPodServices(pod *api.Pod) ([]*api.Service, error) +} + +// ServiceNamespaceListerExpansion allows custom methods to be added to +// ServiceNamespaeLister. +type ServiceNamespaceListerExpansion interface{} + +// TODO: Move this back to scheduler as a helper function that takes a Store, +// rather than a method of ServiceLister. +func (s *serviceLister) GetPodServices(pod *api.Pod) ([]*api.Service, error) { + allServices, err := s.Services(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var services []*api.Service + for i := range allServices { + service := allServices[i] + if service.Spec.Selector == nil { + // services with nil selectors match nothing, not everything. + continue + } + selector := labels.Set(service.Spec.Selector).AsSelectorPreValidated() + if selector.Matches(labels.Set(pod.Labels)) { + services = append(services, service) + } + } + + return services, nil +} diff --git a/pkg/client/listers/core/v1/BUILD b/pkg/client/listers/core/v1/BUILD index 6b65275e16d..ca069605d25 100644 --- a/pkg/client/listers/core/v1/BUILD +++ b/pkg/client/listers/core/v1/BUILD @@ -18,14 +18,17 @@ go_library( "limitrange.go", "namespace.go", "node.go", + "node_expansion.go", "persistentvolume.go", "persistentvolumeclaim.go", "pod.go", "podtemplate.go", "replicationcontroller.go", + "replicationcontroller_expansion.go", "resourcequota.go", "secret.go", "service.go", + "service_expansion.go", "serviceaccount.go", ], tags = ["automanaged"], diff --git a/pkg/client/listers/core/v1/expansion_generated.go b/pkg/client/listers/core/v1/expansion_generated.go index 6e49f91165f..f2eba834ce3 100644 --- a/pkg/client/listers/core/v1/expansion_generated.go +++ b/pkg/client/listers/core/v1/expansion_generated.go @@ -58,10 +58,6 @@ type LimitRangeNamespaceListerExpansion interface{} // NamespaceLister. type NamespaceListerExpansion interface{} -// NodeListerExpansion allows custom methods to be added to -// NodeLister. -type NodeListerExpansion interface{} - // PersistentVolumeListerExpansion allows custom methods to be added to // PersistentVolumeLister. type PersistentVolumeListerExpansion interface{} @@ -90,14 +86,6 @@ type PodTemplateListerExpansion interface{} // PodTemplateNamespaeLister. type PodTemplateNamespaceListerExpansion interface{} -// ReplicationControllerListerExpansion allows custom methods to be added to -// ReplicationControllerLister. -type ReplicationControllerListerExpansion interface{} - -// ReplicationControllerNamespaceListerExpansion allows custom methods to be added to -// ReplicationControllerNamespaeLister. -type ReplicationControllerNamespaceListerExpansion interface{} - // ResourceQuotaListerExpansion allows custom methods to be added to // ResourceQuotaLister. type ResourceQuotaListerExpansion interface{} @@ -114,14 +102,6 @@ type SecretListerExpansion interface{} // SecretNamespaeLister. type SecretNamespaceListerExpansion interface{} -// ServiceListerExpansion allows custom methods to be added to -// ServiceLister. -type ServiceListerExpansion interface{} - -// ServiceNamespaceListerExpansion allows custom methods to be added to -// ServiceNamespaeLister. -type ServiceNamespaceListerExpansion interface{} - // ServiceAccountListerExpansion allows custom methods to be added to // ServiceAccountLister. type ServiceAccountListerExpansion interface{} diff --git a/pkg/client/listers/core/v1/node_expansion.go b/pkg/client/listers/core/v1/node_expansion.go new file mode 100644 index 00000000000..be1ac843b90 --- /dev/null +++ b/pkg/client/listers/core/v1/node_expansion.go @@ -0,0 +1,48 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" +) + +// NodeConditionPredicate is a function that indicates whether the given node's conditions meet +// some set of criteria defined by the function. +type NodeConditionPredicate func(node *v1.Node) bool + +// NodeListerExpansion allows custom methods to be added to +// NodeLister. +type NodeListerExpansion interface { + ListWithPredicate(predicate NodeConditionPredicate) ([]*v1.Node, error) +} + +func (l *nodeLister) ListWithPredicate(predicate NodeConditionPredicate) ([]*v1.Node, error) { + nodes, err := l.List(labels.Everything()) + if err != nil { + return nil, err + } + + var filtered []*v1.Node + for i := range nodes { + if predicate(nodes[i]) { + filtered = append(filtered, nodes[i]) + } + } + + return filtered, nil +} diff --git a/pkg/client/listers/core/v1/replicationcontroller_expansion.go b/pkg/client/listers/core/v1/replicationcontroller_expansion.go new file mode 100644 index 00000000000..aa5202d5e42 --- /dev/null +++ b/pkg/client/listers/core/v1/replicationcontroller_expansion.go @@ -0,0 +1,64 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" +) + +// ReplicationControllerListerExpansion allows custom methods to be added to +// ReplicationControllerLister. +type ReplicationControllerListerExpansion interface { + GetPodControllers(pod *v1.Pod) ([]*v1.ReplicationController, error) +} + +// ReplicationControllerNamespaceListerExpansion allows custom methods to be added to +// ReplicationControllerNamespaeLister. +type ReplicationControllerNamespaceListerExpansion interface{} + +// GetPodControllers returns a list of replication controllers managing a pod. Returns an error only if no matching controllers are found. +func (s *replicationControllerLister) GetPodControllers(pod *v1.Pod) ([]*v1.ReplicationController, error) { + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no controllers found for pod %v because it has no labels", pod.Name) + } + + items, err := s.ReplicationControllers(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var controllers []*v1.ReplicationController + for i := range items { + rc := items[i] + selector := labels.Set(rc.Spec.Selector).AsSelectorPreValidated() + + // If an rc with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + controllers = append(controllers, rc) + } + + if len(controllers) == 0 { + return nil, fmt.Errorf("could not find controller for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return controllers, nil +} diff --git a/pkg/client/listers/core/v1/service_expansion.go b/pkg/client/listers/core/v1/service_expansion.go new file mode 100644 index 00000000000..2f04b488c50 --- /dev/null +++ b/pkg/client/listers/core/v1/service_expansion.go @@ -0,0 +1,56 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" +) + +// ServiceListerExpansion allows custom methods to be added to +// ServiceLister. +type ServiceListerExpansion interface { + GetPodServices(pod *v1.Pod) ([]*v1.Service, error) +} + +// ServiceNamespaceListerExpansion allows custom methods to be added to +// ServiceNamespaeLister. +type ServiceNamespaceListerExpansion interface{} + +// TODO: Move this back to scheduler as a helper function that takes a Store, +// rather than a method of ServiceLister. +func (s *serviceLister) GetPodServices(pod *v1.Pod) ([]*v1.Service, error) { + allServices, err := s.Services(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var services []*v1.Service + for i := range allServices { + service := allServices[i] + if service.Spec.Selector == nil { + // services with nil selectors match nothing, not everything. + continue + } + selector := labels.Set(service.Spec.Selector).AsSelectorPreValidated() + if selector.Matches(labels.Set(pod.Labels)) { + services = append(services, service) + } + } + + return services, nil +} diff --git a/pkg/client/listers/extensions/internalversion/BUILD b/pkg/client/listers/extensions/internalversion/BUILD index 077c14b92d2..aa47da0053f 100644 --- a/pkg/client/listers/extensions/internalversion/BUILD +++ b/pkg/client/listers/extensions/internalversion/BUILD @@ -5,23 +5,28 @@ licenses(["notice"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( name = "go_default_library", srcs = [ "daemonset.go", + "daemonset_expansion.go", "deployment.go", + "deployment_expansion.go", "expansion_generated.go", "ingress.go", "networkpolicy.go", "podsecuritypolicy.go", "replicaset.go", + "replicaset_expansion.go", "scale.go", "thirdpartyresource.go", ], tags = ["automanaged"], deps = [ + "//pkg/api:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/client/cache:go_default_library", "//vendor:k8s.io/apimachinery/pkg/api/errors", @@ -42,3 +47,18 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["daemonset_expansion_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//pkg/api:go_default_library", + "//pkg/apis/extensions:go_default_library", + "//pkg/client/cache:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apimachinery/pkg/labels", + "//vendor:k8s.io/apimachinery/pkg/util/sets", + ], +) diff --git a/pkg/client/listers/extensions/internalversion/daemonset_expansion.go b/pkg/client/listers/extensions/internalversion/daemonset_expansion.go new file mode 100644 index 00000000000..c5073f3bca6 --- /dev/null +++ b/pkg/client/listers/extensions/internalversion/daemonset_expansion.go @@ -0,0 +1,77 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +// DaemonSetListerExpansion allows custom methods to be added to +// DaemonSetLister. +type DaemonSetListerExpansion interface { + GetPodDaemonSets(pod *api.Pod) ([]*extensions.DaemonSet, error) +} + +// DaemonSetNamespaceListerExpansion allows custom methods to be added to +// DaemonSetNamespaeLister. +type DaemonSetNamespaceListerExpansion interface{} + +// GetPodDaemonSets returns a list of daemon sets managing a pod. +// Returns an error if and only if no matching daemon sets are found. +func (s *daemonSetLister) GetPodDaemonSets(pod *api.Pod) ([]*extensions.DaemonSet, error) { + var selector labels.Selector + var daemonSet *extensions.DaemonSet + + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no daemon sets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.DaemonSets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var daemonSets []*extensions.DaemonSet + for i := range list { + daemonSet = list[i] + if daemonSet.Namespace != pod.Namespace { + continue + } + selector, err = metav1.LabelSelectorAsSelector(daemonSet.Spec.Selector) + if err != nil { + // this should not happen if the DaemonSet passed validation + return nil, err + } + + // If a daemonSet with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + daemonSets = append(daemonSets, daemonSet) + } + + if len(daemonSets) == 0 { + return nil, fmt.Errorf("could not find daemon set for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return daemonSets, nil +} diff --git a/pkg/client/listers/extensions/internalversion/daemonset_expansion_test.go b/pkg/client/listers/extensions/internalversion/daemonset_expansion_test.go new file mode 100644 index 00000000000..dabe19bef99 --- /dev/null +++ b/pkg/client/listers/extensions/internalversion/daemonset_expansion_test.go @@ -0,0 +1,152 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/client/cache" +) + +func TestDaemonSetLister(t *testing.T) { + store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) + lister := NewDaemonSetLister(store) + testCases := []struct { + inDSs []*extensions.DaemonSet + list func() ([]*extensions.DaemonSet, error) + outDaemonSetNames sets.String + expectErr bool + }{ + // Basic listing + { + inDSs: []*extensions.DaemonSet{ + {ObjectMeta: metav1.ObjectMeta{Name: "basic"}}, + }, + list: func() ([]*extensions.DaemonSet, error) { + return lister.List(labels.Everything()) + }, + outDaemonSetNames: sets.NewString("basic"), + }, + // Listing multiple daemon sets + { + inDSs: []*extensions.DaemonSet{ + {ObjectMeta: metav1.ObjectMeta{Name: "basic"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "complex"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "complex2"}}, + }, + list: func() ([]*extensions.DaemonSet, error) { + return lister.List(labels.Everything()) + }, + outDaemonSetNames: sets.NewString("basic", "complex", "complex2"), + }, + // No pod labels + { + inDSs: []*extensions.DaemonSet{ + { + ObjectMeta: metav1.ObjectMeta{Name: "basic", Namespace: "ns"}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "baz"}}, + }, + }, + }, + list: func() ([]*extensions.DaemonSet, error) { + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "pod1", Namespace: "ns"}, + } + return lister.GetPodDaemonSets(pod) + }, + outDaemonSetNames: sets.NewString(), + expectErr: true, + }, + // No DS selectors + { + inDSs: []*extensions.DaemonSet{ + { + ObjectMeta: metav1.ObjectMeta{Name: "basic", Namespace: "ns"}, + }, + }, + list: func() ([]*extensions.DaemonSet, error) { + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "ns", + Labels: map[string]string{"foo": "bar"}, + }, + } + return lister.GetPodDaemonSets(pod) + }, + outDaemonSetNames: sets.NewString(), + expectErr: true, + }, + // Matching labels to selectors and namespace + { + inDSs: []*extensions.DaemonSet{ + { + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "ns"}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + }, + list: func() ([]*extensions.DaemonSet, error) { + pod := &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Labels: map[string]string{"foo": "bar"}, + Namespace: "ns", + }, + } + return lister.GetPodDaemonSets(pod) + }, + outDaemonSetNames: sets.NewString("bar"), + }, + } + for _, c := range testCases { + for _, r := range c.inDSs { + store.Add(r) + } + + daemonSets, err := c.list() + if err != nil && c.expectErr { + continue + } else if c.expectErr { + t.Error("Expected error, got none") + continue + } else if err != nil { + t.Errorf("Unexpected error %#v", err) + continue + } + daemonSetNames := make([]string, len(daemonSets)) + for ix := range daemonSets { + daemonSetNames[ix] = daemonSets[ix].Name + } + if !c.outDaemonSetNames.HasAll(daemonSetNames...) || len(daemonSetNames) != len(c.outDaemonSetNames) { + t.Errorf("Unexpected got controllers %+v expected %+v", daemonSetNames, c.outDaemonSetNames) + } + } +} diff --git a/pkg/client/listers/extensions/internalversion/deployment_expansion.go b/pkg/client/listers/extensions/internalversion/deployment_expansion.go new file mode 100644 index 00000000000..c42010fd1e2 --- /dev/null +++ b/pkg/client/listers/extensions/internalversion/deployment_expansion.go @@ -0,0 +1,67 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +// DeploymentListerExpansion allows custom methods to be added to +// DeploymentLister. +type DeploymentListerExpansion interface { + GetDeploymentsForReplicaSet(rs *extensions.ReplicaSet) ([]*extensions.Deployment, error) +} + +// DeploymentNamespaceListerExpansion allows custom methods to be added to +// DeploymentNamespaeLister. +type DeploymentNamespaceListerExpansion interface{} + +// GetDeploymentsForReplicaSet returns a list of deployments managing a replica set. Returns an error only if no matching deployments are found. +func (s *deploymentLister) GetDeploymentsForReplicaSet(rs *extensions.ReplicaSet) ([]*extensions.Deployment, error) { + if len(rs.Labels) == 0 { + return nil, fmt.Errorf("no deployments found for ReplicaSet %v because it has no labels", rs.Name) + } + + // TODO: MODIFY THIS METHOD so that it checks for the podTemplateSpecHash label + dList, err := s.Deployments(rs.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var deployments []*extensions.Deployment + for _, d := range dList { + selector, err := metav1.LabelSelectorAsSelector(d.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid label selector: %v", err) + } + // If a deployment with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(rs.Labels)) { + continue + } + deployments = append(deployments, d) + } + + if len(deployments) == 0 { + return nil, fmt.Errorf("could not find deployments set for ReplicaSet %s in namespace %s with labels: %v", rs.Name, rs.Namespace, rs.Labels) + } + + return deployments, nil +} diff --git a/pkg/client/listers/extensions/internalversion/expansion_generated.go b/pkg/client/listers/extensions/internalversion/expansion_generated.go index 47ce7a765cf..69feaca0ef9 100644 --- a/pkg/client/listers/extensions/internalversion/expansion_generated.go +++ b/pkg/client/listers/extensions/internalversion/expansion_generated.go @@ -18,22 +18,6 @@ limitations under the License. package internalversion -// DaemonSetListerExpansion allows custom methods to be added to -// DaemonSetLister. -type DaemonSetListerExpansion interface{} - -// DaemonSetNamespaceListerExpansion allows custom methods to be added to -// DaemonSetNamespaeLister. -type DaemonSetNamespaceListerExpansion interface{} - -// DeploymentListerExpansion allows custom methods to be added to -// DeploymentLister. -type DeploymentListerExpansion interface{} - -// DeploymentNamespaceListerExpansion allows custom methods to be added to -// DeploymentNamespaeLister. -type DeploymentNamespaceListerExpansion interface{} - // IngressListerExpansion allows custom methods to be added to // IngressLister. type IngressListerExpansion interface{} @@ -54,14 +38,6 @@ type NetworkPolicyNamespaceListerExpansion interface{} // PodSecurityPolicyLister. type PodSecurityPolicyListerExpansion interface{} -// ReplicaSetListerExpansion allows custom methods to be added to -// ReplicaSetLister. -type ReplicaSetListerExpansion interface{} - -// ReplicaSetNamespaceListerExpansion allows custom methods to be added to -// ReplicaSetNamespaeLister. -type ReplicaSetNamespaceListerExpansion interface{} - // ScaleListerExpansion allows custom methods to be added to // ScaleLister. type ScaleListerExpansion interface{} diff --git a/pkg/client/listers/extensions/internalversion/replicaset_expansion.go b/pkg/client/listers/extensions/internalversion/replicaset_expansion.go new file mode 100644 index 00000000000..d2ab13ec7f7 --- /dev/null +++ b/pkg/client/listers/extensions/internalversion/replicaset_expansion.go @@ -0,0 +1,71 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +// ReplicaSetListerExpansion allows custom methods to be added to +// ReplicaSetLister. +type ReplicaSetListerExpansion interface { + GetPodReplicaSets(pod *api.Pod) ([]*extensions.ReplicaSet, error) +} + +// ReplicaSetNamespaceListerExpansion allows custom methods to be added to +// ReplicaSetNamespaeLister. +type ReplicaSetNamespaceListerExpansion interface{} + +// GetPodReplicaSets returns a list of ReplicaSets managing a pod. Returns an error only if no matching ReplicaSets are found. +func (s *replicaSetLister) GetPodReplicaSets(pod *api.Pod) ([]*extensions.ReplicaSet, error) { + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no ReplicaSets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.ReplicaSets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var rss []*extensions.ReplicaSet + for _, rs := range list { + if rs.Namespace != pod.Namespace { + continue + } + selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid selector: %v", err) + } + + // If a ReplicaSet with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + rss = append(rss, rs) + } + + if len(rss) == 0 { + return nil, fmt.Errorf("could not find ReplicaSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return rss, nil +} diff --git a/pkg/client/listers/extensions/v1beta1/BUILD b/pkg/client/listers/extensions/v1beta1/BUILD index 30efb7b6861..7cb5734e526 100644 --- a/pkg/client/listers/extensions/v1beta1/BUILD +++ b/pkg/client/listers/extensions/v1beta1/BUILD @@ -5,22 +5,27 @@ licenses(["notice"]) load( "@io_bazel_rules_go//go:def.bzl", "go_library", + "go_test", ) go_library( name = "go_default_library", srcs = [ "daemonset.go", + "daemonset_expansion.go", "deployment.go", + "deployment_expansion.go", "expansion_generated.go", "ingress.go", "podsecuritypolicy.go", "replicaset.go", + "replicaset_expansion.go", "scale.go", "thirdpartyresource.go", ], tags = ["automanaged"], deps = [ + "//pkg/api/v1:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions/v1beta1:go_default_library", "//pkg/client/cache:go_default_library", @@ -42,3 +47,18 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["daemonset_expansion_test.go"], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//pkg/api/v1:go_default_library", + "//pkg/apis/extensions/v1beta1:go_default_library", + "//pkg/client/cache:go_default_library", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", + "//vendor:k8s.io/apimachinery/pkg/labels", + "//vendor:k8s.io/apimachinery/pkg/util/sets", + ], +) diff --git a/pkg/client/listers/extensions/v1beta1/daemonset_expansion.go b/pkg/client/listers/extensions/v1beta1/daemonset_expansion.go new file mode 100644 index 00000000000..d3497414e99 --- /dev/null +++ b/pkg/client/listers/extensions/v1beta1/daemonset_expansion.go @@ -0,0 +1,77 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" +) + +// DaemonSetListerExpansion allows custom methods to be added to +// DaemonSetLister. +type DaemonSetListerExpansion interface { + GetPodDaemonSets(pod *v1.Pod) ([]*v1beta1.DaemonSet, error) +} + +// DaemonSetNamespaceListerExpansion allows custom methods to be added to +// DaemonSetNamespaeLister. +type DaemonSetNamespaceListerExpansion interface{} + +// GetPodDaemonSets returns a list of daemon sets managing a pod. +// Returns an error if and only if no matching daemon sets are found. +func (s *daemonSetLister) GetPodDaemonSets(pod *v1.Pod) ([]*v1beta1.DaemonSet, error) { + var selector labels.Selector + var daemonSet *v1beta1.DaemonSet + + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no daemon sets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.DaemonSets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var daemonSets []*v1beta1.DaemonSet + for i := range list { + daemonSet = list[i] + if daemonSet.Namespace != pod.Namespace { + continue + } + selector, err = metav1.LabelSelectorAsSelector(daemonSet.Spec.Selector) + if err != nil { + // this should not happen if the DaemonSet passed validation + return nil, err + } + + // If a daemonSet with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + daemonSets = append(daemonSets, daemonSet) + } + + if len(daemonSets) == 0 { + return nil, fmt.Errorf("could not find daemon set for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return daemonSets, nil +} diff --git a/pkg/client/listers/extensions/v1beta1/daemonset_expansion_test.go b/pkg/client/listers/extensions/v1beta1/daemonset_expansion_test.go new file mode 100644 index 00000000000..c9c5f9ba6d8 --- /dev/null +++ b/pkg/client/listers/extensions/v1beta1/daemonset_expansion_test.go @@ -0,0 +1,152 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/kubernetes/pkg/api/v1" + extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" + "k8s.io/kubernetes/pkg/client/cache" +) + +func TestDaemonSetLister(t *testing.T) { + store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) + lister := NewDaemonSetLister(store) + testCases := []struct { + inDSs []*extensions.DaemonSet + list func() ([]*extensions.DaemonSet, error) + outDaemonSetNames sets.String + expectErr bool + }{ + // Basic listing + { + inDSs: []*extensions.DaemonSet{ + {ObjectMeta: metav1.ObjectMeta{Name: "basic"}}, + }, + list: func() ([]*extensions.DaemonSet, error) { + return lister.List(labels.Everything()) + }, + outDaemonSetNames: sets.NewString("basic"), + }, + // Listing multiple daemon sets + { + inDSs: []*extensions.DaemonSet{ + {ObjectMeta: metav1.ObjectMeta{Name: "basic"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "complex"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "complex2"}}, + }, + list: func() ([]*extensions.DaemonSet, error) { + return lister.List(labels.Everything()) + }, + outDaemonSetNames: sets.NewString("basic", "complex", "complex2"), + }, + // No pod labels + { + inDSs: []*extensions.DaemonSet{ + { + ObjectMeta: metav1.ObjectMeta{Name: "basic", Namespace: "ns"}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "baz"}}, + }, + }, + }, + list: func() ([]*extensions.DaemonSet, error) { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "pod1", Namespace: "ns"}, + } + return lister.GetPodDaemonSets(pod) + }, + outDaemonSetNames: sets.NewString(), + expectErr: true, + }, + // No DS selectors + { + inDSs: []*extensions.DaemonSet{ + { + ObjectMeta: metav1.ObjectMeta{Name: "basic", Namespace: "ns"}, + }, + }, + list: func() ([]*extensions.DaemonSet, error) { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "ns", + Labels: map[string]string{"foo": "bar"}, + }, + } + return lister.GetPodDaemonSets(pod) + }, + outDaemonSetNames: sets.NewString(), + expectErr: true, + }, + // Matching labels to selectors and namespace + { + inDSs: []*extensions.DaemonSet{ + { + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "ns"}, + Spec: extensions.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + }, + }, + }, + list: func() ([]*extensions.DaemonSet, error) { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Labels: map[string]string{"foo": "bar"}, + Namespace: "ns", + }, + } + return lister.GetPodDaemonSets(pod) + }, + outDaemonSetNames: sets.NewString("bar"), + }, + } + for _, c := range testCases { + for _, r := range c.inDSs { + store.Add(r) + } + + daemonSets, err := c.list() + if err != nil && c.expectErr { + continue + } else if c.expectErr { + t.Error("Expected error, got none") + continue + } else if err != nil { + t.Errorf("Unexpected error %#v", err) + continue + } + daemonSetNames := make([]string, len(daemonSets)) + for ix := range daemonSets { + daemonSetNames[ix] = daemonSets[ix].Name + } + if !c.outDaemonSetNames.HasAll(daemonSetNames...) || len(daemonSetNames) != len(c.outDaemonSetNames) { + t.Errorf("Unexpected got controllers %+v expected %+v", daemonSetNames, c.outDaemonSetNames) + } + } +} diff --git a/pkg/client/listers/extensions/v1beta1/deployment_expansion.go b/pkg/client/listers/extensions/v1beta1/deployment_expansion.go new file mode 100644 index 00000000000..e08799ebacc --- /dev/null +++ b/pkg/client/listers/extensions/v1beta1/deployment_expansion.go @@ -0,0 +1,67 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" +) + +// DeploymentListerExpansion allows custom methods to be added to +// DeploymentLister. +type DeploymentListerExpansion interface { + GetDeploymentsForReplicaSet(rs *extensions.ReplicaSet) ([]*extensions.Deployment, error) +} + +// DeploymentNamespaceListerExpansion allows custom methods to be added to +// DeploymentNamespaeLister. +type DeploymentNamespaceListerExpansion interface{} + +// GetDeploymentsForReplicaSet returns a list of deployments managing a replica set. Returns an error only if no matching deployments are found. +func (s *deploymentLister) GetDeploymentsForReplicaSet(rs *extensions.ReplicaSet) ([]*extensions.Deployment, error) { + if len(rs.Labels) == 0 { + return nil, fmt.Errorf("no deployments found for ReplicaSet %v because it has no labels", rs.Name) + } + + // TODO: MODIFY THIS METHOD so that it checks for the podTemplateSpecHash label + dList, err := s.Deployments(rs.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var deployments []*extensions.Deployment + for _, d := range dList { + selector, err := metav1.LabelSelectorAsSelector(d.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid label selector: %v", err) + } + // If a deployment with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(rs.Labels)) { + continue + } + deployments = append(deployments, d) + } + + if len(deployments) == 0 { + return nil, fmt.Errorf("could not find deployments set for ReplicaSet %s in namespace %s with labels: %v", rs.Name, rs.Namespace, rs.Labels) + } + + return deployments, nil +} diff --git a/pkg/client/listers/extensions/v1beta1/expansion_generated.go b/pkg/client/listers/extensions/v1beta1/expansion_generated.go index d98306b7750..12682e4c73b 100644 --- a/pkg/client/listers/extensions/v1beta1/expansion_generated.go +++ b/pkg/client/listers/extensions/v1beta1/expansion_generated.go @@ -18,22 +18,6 @@ limitations under the License. package v1beta1 -// DaemonSetListerExpansion allows custom methods to be added to -// DaemonSetLister. -type DaemonSetListerExpansion interface{} - -// DaemonSetNamespaceListerExpansion allows custom methods to be added to -// DaemonSetNamespaeLister. -type DaemonSetNamespaceListerExpansion interface{} - -// DeploymentListerExpansion allows custom methods to be added to -// DeploymentLister. -type DeploymentListerExpansion interface{} - -// DeploymentNamespaceListerExpansion allows custom methods to be added to -// DeploymentNamespaeLister. -type DeploymentNamespaceListerExpansion interface{} - // IngressListerExpansion allows custom methods to be added to // IngressLister. type IngressListerExpansion interface{} @@ -46,14 +30,6 @@ type IngressNamespaceListerExpansion interface{} // PodSecurityPolicyLister. type PodSecurityPolicyListerExpansion interface{} -// ReplicaSetListerExpansion allows custom methods to be added to -// ReplicaSetLister. -type ReplicaSetListerExpansion interface{} - -// ReplicaSetNamespaceListerExpansion allows custom methods to be added to -// ReplicaSetNamespaeLister. -type ReplicaSetNamespaceListerExpansion interface{} - // ScaleListerExpansion allows custom methods to be added to // ScaleLister. type ScaleListerExpansion interface{} diff --git a/pkg/client/listers/extensions/v1beta1/replicaset_expansion.go b/pkg/client/listers/extensions/v1beta1/replicaset_expansion.go new file mode 100644 index 00000000000..cfef9588406 --- /dev/null +++ b/pkg/client/listers/extensions/v1beta1/replicaset_expansion.go @@ -0,0 +1,71 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" + extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" +) + +// ReplicaSetListerExpansion allows custom methods to be added to +// ReplicaSetLister. +type ReplicaSetListerExpansion interface { + GetPodReplicaSets(pod *v1.Pod) ([]*extensions.ReplicaSet, error) +} + +// ReplicaSetNamespaceListerExpansion allows custom methods to be added to +// ReplicaSetNamespaeLister. +type ReplicaSetNamespaceListerExpansion interface{} + +// GetPodReplicaSets returns a list of ReplicaSets managing a pod. Returns an error only if no matching ReplicaSets are found. +func (s *replicaSetLister) GetPodReplicaSets(pod *v1.Pod) ([]*extensions.ReplicaSet, error) { + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no ReplicaSets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.ReplicaSets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var rss []*extensions.ReplicaSet + for _, rs := range list { + if rs.Namespace != pod.Namespace { + continue + } + selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid selector: %v", err) + } + + // If a ReplicaSet with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + rss = append(rss, rs) + } + + if len(rss) == 0 { + return nil, fmt.Errorf("could not find ReplicaSet for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return rss, nil +} diff --git a/pkg/client/listers/policy/internalversion/BUILD b/pkg/client/listers/policy/internalversion/BUILD index 13167d81b8b..5c73fe94032 100644 --- a/pkg/client/listers/policy/internalversion/BUILD +++ b/pkg/client/listers/policy/internalversion/BUILD @@ -13,12 +13,16 @@ go_library( "eviction.go", "expansion_generated.go", "poddisruptionbudget.go", + "poddisruptionbudget_expansion.go", ], tags = ["automanaged"], deps = [ + "//pkg/api:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/client/cache:go_default_library", + "//vendor:github.com/golang/glog", "//vendor:k8s.io/apimachinery/pkg/api/errors", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/labels", ], ) diff --git a/pkg/client/listers/policy/internalversion/expansion_generated.go b/pkg/client/listers/policy/internalversion/expansion_generated.go index 840b38e6d89..1a0389aca43 100644 --- a/pkg/client/listers/policy/internalversion/expansion_generated.go +++ b/pkg/client/listers/policy/internalversion/expansion_generated.go @@ -25,11 +25,3 @@ type EvictionListerExpansion interface{} // EvictionNamespaceListerExpansion allows custom methods to be added to // EvictionNamespaeLister. type EvictionNamespaceListerExpansion interface{} - -// PodDisruptionBudgetListerExpansion allows custom methods to be added to -// PodDisruptionBudgetLister. -type PodDisruptionBudgetListerExpansion interface{} - -// PodDisruptionBudgetNamespaceListerExpansion allows custom methods to be added to -// PodDisruptionBudgetNamespaeLister. -type PodDisruptionBudgetNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/policy/internalversion/poddisruptionbudget_expansion.go b/pkg/client/listers/policy/internalversion/poddisruptionbudget_expansion.go new file mode 100644 index 00000000000..a666e2b5f31 --- /dev/null +++ b/pkg/client/listers/policy/internalversion/poddisruptionbudget_expansion.go @@ -0,0 +1,74 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internalversion + +import ( + "fmt" + + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/policy" +) + +// PodDisruptionBudgetListerExpansion allows custom methods to be added to +// PodDisruptionBudgetLister. +type PodDisruptionBudgetListerExpansion interface { + GetPodPodDisruptionBudgets(pod *api.Pod) ([]*policy.PodDisruptionBudget, error) +} + +// PodDisruptionBudgetNamespaceListerExpansion allows custom methods to be added to +// PodDisruptionBudgetNamespaeLister. +type PodDisruptionBudgetNamespaceListerExpansion interface{} + +// GetPodPodDisruptionBudgets returns a list of PodDisruptionBudgets matching a pod. Returns an error only if no matching PodDisruptionBudgets are found. +func (s *podDisruptionBudgetLister) GetPodPodDisruptionBudgets(pod *api.Pod) ([]*policy.PodDisruptionBudget, error) { + var selector labels.Selector + + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no PodDisruptionBudgets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.PodDisruptionBudgets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var pdbList []*policy.PodDisruptionBudget + for i := range list { + pdb := list[i] + selector, err = metav1.LabelSelectorAsSelector(pdb.Spec.Selector) + if err != nil { + glog.Warningf("invalid selector: %v", err) + // TODO(mml): add an event to the PDB + continue + } + + // If a PDB with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + pdbList = append(pdbList, pdb) + } + + if len(pdbList) == 0 { + return nil, fmt.Errorf("could not find PodDisruptionBudget for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return pdbList, nil +} diff --git a/pkg/client/listers/policy/v1beta1/BUILD b/pkg/client/listers/policy/v1beta1/BUILD index b9423cb7cfe..d89e2e55159 100644 --- a/pkg/client/listers/policy/v1beta1/BUILD +++ b/pkg/client/listers/policy/v1beta1/BUILD @@ -13,13 +13,17 @@ go_library( "eviction.go", "expansion_generated.go", "poddisruptionbudget.go", + "poddisruptionbudget_expansion.go", ], tags = ["automanaged"], deps = [ + "//pkg/api/v1:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/apis/policy/v1beta1:go_default_library", "//pkg/client/cache:go_default_library", + "//vendor:github.com/golang/glog", "//vendor:k8s.io/apimachinery/pkg/api/errors", + "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/labels", ], ) diff --git a/pkg/client/listers/policy/v1beta1/expansion_generated.go b/pkg/client/listers/policy/v1beta1/expansion_generated.go index 7c4dc27a7bd..3deec5230ce 100644 --- a/pkg/client/listers/policy/v1beta1/expansion_generated.go +++ b/pkg/client/listers/policy/v1beta1/expansion_generated.go @@ -25,11 +25,3 @@ type EvictionListerExpansion interface{} // EvictionNamespaceListerExpansion allows custom methods to be added to // EvictionNamespaeLister. type EvictionNamespaceListerExpansion interface{} - -// PodDisruptionBudgetListerExpansion allows custom methods to be added to -// PodDisruptionBudgetLister. -type PodDisruptionBudgetListerExpansion interface{} - -// PodDisruptionBudgetNamespaceListerExpansion allows custom methods to be added to -// PodDisruptionBudgetNamespaeLister. -type PodDisruptionBudgetNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/policy/v1beta1/poddisruptionbudget_expansion.go b/pkg/client/listers/policy/v1beta1/poddisruptionbudget_expansion.go new file mode 100644 index 00000000000..ce2945808b2 --- /dev/null +++ b/pkg/client/listers/policy/v1beta1/poddisruptionbudget_expansion.go @@ -0,0 +1,74 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/kubernetes/pkg/api/v1" + policy "k8s.io/kubernetes/pkg/apis/policy/v1beta1" +) + +// PodDisruptionBudgetListerExpansion allows custom methods to be added to +// PodDisruptionBudgetLister. +type PodDisruptionBudgetListerExpansion interface { + GetPodPodDisruptionBudgets(pod *v1.Pod) ([]*policy.PodDisruptionBudget, error) +} + +// PodDisruptionBudgetNamespaceListerExpansion allows custom methods to be added to +// PodDisruptionBudgetNamespaeLister. +type PodDisruptionBudgetNamespaceListerExpansion interface{} + +// GetPodPodDisruptionBudgets returns a list of PodDisruptionBudgets matching a pod. Returns an error only if no matching PodDisruptionBudgets are found. +func (s *podDisruptionBudgetLister) GetPodPodDisruptionBudgets(pod *v1.Pod) ([]*policy.PodDisruptionBudget, error) { + var selector labels.Selector + + if len(pod.Labels) == 0 { + return nil, fmt.Errorf("no PodDisruptionBudgets found for pod %v because it has no labels", pod.Name) + } + + list, err := s.PodDisruptionBudgets(pod.Namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var pdbList []*policy.PodDisruptionBudget + for i := range list { + pdb := list[i] + selector, err = metav1.LabelSelectorAsSelector(pdb.Spec.Selector) + if err != nil { + glog.Warningf("invalid selector: %v", err) + // TODO(mml): add an event to the PDB + continue + } + + // If a PDB with a nil or empty selector creeps in, it should match nothing, not everything. + if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { + continue + } + pdbList = append(pdbList, pdb) + } + + if len(pdbList) == 0 { + return nil, fmt.Errorf("could not find PodDisruptionBudget for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels) + } + + return pdbList, nil +}