diff --git a/src/kubernetes.cc b/src/kubernetes.cc index ad2293b3..93a7f9b5 100644 --- a/src/kubernetes.cc +++ b/src/kubernetes.cc @@ -154,7 +154,8 @@ json::value KubernetesReader::ComputePodAssociations(const json::Object* pod) const std::string namespace_name = metadata->Get("namespace"); const std::string pod_id = metadata->Get("uid"); - const json::value top_level = FindTopLevelOwner(namespace_name, pod->Clone()); + const json::value top_level = FindTopLevelController( + namespace_name, pod->Clone()); const json::Object* top_level_controller = top_level->As(); const json::Object* top_level_metadata = top_level_controller->Get("metadata"); @@ -1033,7 +1034,7 @@ json::value KubernetesReader::GetOwner( return owner->Clone(); } -json::value KubernetesReader::FindTopLevelOwner( +json::value KubernetesReader::FindTopLevelController( const std::string& ns, json::value object) const throw(QueryException, json::Exception) { const json::Object* obj = object->As(); @@ -1042,27 +1043,42 @@ json::value KubernetesReader::FindTopLevelOwner( #endif const json::Object* metadata = obj->Get("metadata"); #ifdef VERBOSE - LOG(DEBUG) << "FindTopLevelOwner: metadata is " << *metadata; + LOG(DEBUG) << "FindTopLevelController: metadata is " << *metadata; #endif if (!metadata->Has("ownerReferences")) { #ifdef VERBOSE - LOG(DEBUG) << "FindTopLevelOwner: no owner references in " << *metadata; + LOG(DEBUG) << "FindTopLevelController: no owner references in " + << *metadata; #endif return object; } const json::Array* refs = metadata->Get("ownerReferences"); #ifdef VERBOSE - LOG(DEBUG) << "FindTopLevelOwner: refs is " << *refs; + LOG(DEBUG) << "FindTopLevelController: refs is " << *refs; #endif - if (refs->size() > 1) { - LOG(WARNING) << "Found multiple owner references for " << *obj - << " picking the first one arbitrarily."; + + // Kubernetes objects are supposed to have at most one controller: + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#objectmeta-v1-meta. + const json::Object* controller_ref = nullptr; + for (const json::value& ref : *refs) { + const json::Object* ref_obj = ref->As(); + if (ref_obj->Has("controller") && + ref_obj->Get("controller")) { + controller_ref = ref_obj; + break; + } + } + if (!controller_ref) { +#ifdef VERBOSE + LOG(DEBUG) << "FindTopLevelController: no controller references in " + << *refs; +#endif + return object; } - const json::value& ref = (*refs)[0]; #ifdef VERBOSE - LOG(DEBUG) << "FindTopLevelOwner: ref is " << *ref; + LOG(DEBUG) << "FindTopLevelController: controller_ref is " << *controller_ref; #endif - return FindTopLevelOwner(ns, GetOwner(ns, ref->As())); + return FindTopLevelController(ns, GetOwner(ns, controller_ref)); } bool KubernetesReader::ValidateConfiguration() const { diff --git a/src/kubernetes.h b/src/kubernetes.h index d8b5414a..6e3b7b0f 100644 --- a/src/kubernetes.h +++ b/src/kubernetes.h @@ -136,10 +136,9 @@ class KubernetesReader { json::value GetOwner(const std::string& ns, const json::Object* owner_ref) const throw(QueryException, json::Exception); - // For a given object, returns the top-level owner object. - // When there are multiple owner references, follows the first one. - json::value FindTopLevelOwner(const std::string& ns, json::value object) const - throw(QueryException, json::Exception); + // For a given object, returns the top-level controller object. + json::value FindTopLevelController(const std::string& ns, json::value object) + const throw(QueryException, json::Exception); // Cached data. mutable std::recursive_mutex mutex_;