diff --git a/src/kubernetes.cc b/src/kubernetes.cc index 6d902bd8..e5a42346 100644 --- a/src/kubernetes.cc +++ b/src/kubernetes.cc @@ -527,13 +527,42 @@ json::value KubernetesReader::GetOwner( const std::string api_version = owner_ref->Get("apiVersion"); const std::string kind = owner_ref->Get("kind"); const std::string name = owner_ref->Get("name"); - const auto path_component = KindPath(api_version, kind); + const std::string uid = owner_ref->Get("uid"); + + // Even though we query by name, we should look up the owner by uid, + // to handle the case when an object is deleted and re-constructed. + const std::string encoded_ref = boost::algorithm::join( + std::vector{api_version, kind, uid}, "/"); + + std::lock_guard lock(mutex_); + auto found = owners_.emplace(std::piecewise_construct, + std::forward_as_tuple(encoded_ref), + std::forward_as_tuple()); + json::value& owner = found.first->second; + if (found.second) { // Not found, inserted new. + const auto path_component = KindPath(api_version, kind); #ifdef VERBOSE - LOG(DEBUG) << "KindPath returned {" << path_component.first << ", " - << path_component.second << "}"; + LOG(DEBUG) << "KindPath returned {" << path_component.first << ", " + << path_component.second << "}"; #endif - return QueryMaster(path_component.first + "/namespaces/" + ns + "/" + - path_component.second + "/" + name); + owner = std::move( + QueryMaster(path_component.first + "/namespaces/" + ns + "/" + + path_component.second + "/" + name)); + // Sanity check: because we are looking up by name, the object we get + // back might have a different uid. + const json::Object* owner_obj = owner->As(); + const json::Object* metadata = owner_obj->Get("metadata"); + const std::string owner_uid = metadata->Get("uid"); + if (owner_uid != uid) { + LOG(WARNING) << "Owner " << kind << "'" << name << "' (id " << uid + << ") disappeared before we could query it. Found id " + << owner_uid << " instead."; + owner.reset(); + throw QueryException("Owner " + kind + " " + name + " (id " + uid + + ") disappeared"); + } + } + return owner->Clone(); } json::value KubernetesReader::FindTopLevelOwner( diff --git a/src/kubernetes.h b/src/kubernetes.h index d0f5d452..6f739e54 100644 --- a/src/kubernetes.h +++ b/src/kubernetes.h @@ -85,6 +85,8 @@ class KubernetesReader { // A memoized map from version to a map from kind to name. mutable std::map> version_to_kind_to_name_; + // A memoized map from an encoded owner reference to the owner object. + mutable std::map owners_; const MetadataAgentConfiguration& config_; Environment environment_;