diff --git a/userspace/libsinsp/chisel.h b/userspace/libsinsp/chisel.h index 2581826d6d..8b38ff96eb 100644 --- a/userspace/libsinsp/chisel.h +++ b/userspace/libsinsp/chisel.h @@ -150,7 +150,7 @@ class SINSP_PUBLIC sinsp_chisel uint64_t m_lua_last_interval_sample_time; uint64_t m_lua_last_interval_ts; vector m_allocated_fltchecks; - char m_lua_fld_storage[1024]; + char m_lua_fld_storage[16384]; chiselinfo* m_lua_cinfo; string m_new_chisel_to_exec; int m_udp_socket; diff --git a/userspace/libsinsp/chisel_api.cpp b/userspace/libsinsp/chisel_api.cpp index e8b9e24a00..902454222f 100644 --- a/userspace/libsinsp/chisel_api.cpp +++ b/userspace/libsinsp/chisel_api.cpp @@ -114,7 +114,7 @@ uint32_t lua_cbacks::rawval_to_lua_stack(lua_State *ls, uint8_t* rawval, const f case PT_BYTEBUF: if(rawval[len] == 0) { - lua_pushstring(ls, (char*)rawval); + lua_pushlstring(ls, (char*)rawval, len); return 1; } else @@ -128,7 +128,7 @@ uint32_t lua_cbacks::rawval_to_lua_stack(lua_State *ls, uint8_t* rawval, const f memcpy(ch->m_lua_fld_storage, rawval, max_len); ch->m_lua_fld_storage[max_len] = 0; - lua_pushstring(ls, (char*)ch->m_lua_fld_storage); + lua_pushlstring(ls, (char*)ch->m_lua_fld_storage, max_len); return 1; } case PT_SOCKADDR: diff --git a/userspace/libsinsp/filterchecks.cpp b/userspace/libsinsp/filterchecks.cpp index a81cdce5c8..fe9fa79f6e 100644 --- a/userspace/libsinsp/filterchecks.cpp +++ b/userspace/libsinsp/filterchecks.cpp @@ -6317,6 +6317,10 @@ const filtercheck_field_info sinsp_filter_check_k8s_fields[] = {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.rs.id", "Kubernetes replica set id."}, {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.rs.label", "Kubernetes replica set label. E.g. 'k8s.rs.label.foo'."}, {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.rs.labels", "Kubernetes replica set comma-separated key/value labels. E.g. 'foo1:bar1,foo2:bar2'."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.deployment.name", "Kubernetes deployment name."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.deployment.id", "Kubernetes deployment id."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.deployment.label", "Kubernetes deployment label. E.g. 'k8s.rs.label.foo'."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "k8s.deployment.labels", "Kubernetes deployment comma-separated key/value labels. E.g. 'foo1:bar1,foo2:bar2'."}, }; sinsp_filter_check_k8s::sinsp_filter_check_k8s() @@ -6376,6 +6380,14 @@ int32_t sinsp_filter_check_k8s::parse_field_name(const char* str, bool alloc_sta return extract_arg("k8s.ns.label", val); } + else if(string(val, 0, sizeof("k8s.deployment.label") - 1) == "k8s.deployment.label" && + string(val, 0, sizeof("k8s.deployment.labels") - 1) != "k8s.deployment.labels") + { + m_field_id = TYPE_K8S_DEPLOYMENT_LABEL; + m_field = &m_info.m_fields[m_field_id]; + + return extract_arg("k8s.deployment.label", val); + } else { return sinsp_filter_check::parse_field_name(str, alloc_state); @@ -6480,6 +6492,20 @@ vector sinsp_filter_check_k8s::find_svc_by_pod(const k8s_p return services; } +const k8s_deployment_t* sinsp_filter_check_k8s::find_deployment_by_pod(const k8s_pod_t* pod) +{ + const k8s_state_t& k8s_state = m_inspector->m_k8s_client->get_state(); + + const k8s_state_t::pod_deployment_map& pod_deployments = k8s_state.get_pod_deployment_map(); + k8s_state_t::pod_deployment_map::const_iterator it = pod_deployments.find(pod->get_uid()); + if(it != pod_deployments.end()) + { + return it->second; + } + + return NULL; +} + void sinsp_filter_check_k8s::concatenate_labels(const k8s_pair_list& labels, string* s) { for(const k8s_pair_t& label_pair : labels) @@ -6779,6 +6805,52 @@ uint8_t* sinsp_filter_check_k8s::extract(sinsp_evt *evt, OUT uint32_t* len, bool } break; } + case TYPE_K8S_DEPLOYMENT_NAME: + { + const k8s_deployment_t* deployment = find_deployment_by_pod(pod); + if(deployment != NULL) + { + m_tstr = deployment->get_name(); + *len = m_tstr.size(); + return (uint8_t*) m_tstr.c_str(); + } + break; + } + case TYPE_K8S_DEPLOYMENT_ID: + { + const k8s_deployment_t* deployment = find_deployment_by_pod(pod); + if(deployment != NULL) + { + m_tstr = deployment->get_uid(); + *len = m_tstr.size(); + return (uint8_t*) m_tstr.c_str(); + } + break; + } + case TYPE_K8S_DEPLOYMENT_LABEL: + { + const k8s_deployment_t* deployment = find_deployment_by_pod(pod); + if(deployment != NULL) + { + if(find_label(deployment->get_labels(), m_argname, &m_tstr)) + { + *len = m_tstr.size(); + return (uint8_t*) m_tstr.c_str(); + } + } + break; + } + case TYPE_K8S_DEPLOYMENT_LABELS: + { + const k8s_deployment_t* deployment = find_deployment_by_pod(pod); + if(deployment != NULL) + { + concatenate_labels(deployment->get_labels(), &m_tstr); + *len = m_tstr.size(); + return (uint8_t*) m_tstr.c_str(); + } + break; + } default: ASSERT(false); return NULL; diff --git a/userspace/libsinsp/filterchecks.h b/userspace/libsinsp/filterchecks.h index 6265f39a49..d90133e19c 100644 --- a/userspace/libsinsp/filterchecks.h +++ b/userspace/libsinsp/filterchecks.h @@ -868,6 +868,10 @@ class sinsp_filter_check_k8s : public sinsp_filter_check TYPE_K8S_RS_ID, TYPE_K8S_RS_LABEL, TYPE_K8S_RS_LABELS, + TYPE_K8S_DEPLOYMENT_NAME, + TYPE_K8S_DEPLOYMENT_ID, + TYPE_K8S_DEPLOYMENT_LABEL, + TYPE_K8S_DEPLOYMENT_LABELS, }; sinsp_filter_check_k8s(); @@ -882,6 +886,7 @@ class sinsp_filter_check_k8s : public sinsp_filter_check const k8s_rc_t* find_rc_by_pod(const k8s_pod_t* pod); const k8s_rs_t* find_rs_by_pod(const k8s_pod_t* pod); vector find_svc_by_pod(const k8s_pod_t* pod); + const k8s_deployment_t* find_deployment_by_pod(const k8s_pod_t* pod); void concatenate_labels(const k8s_pair_list& labels, string* s); bool find_label(const k8s_pair_list& labels, const string& key, string* value); diff --git a/userspace/libsinsp/k8s.cpp b/userspace/libsinsp/k8s.cpp index 75018d014b..c649fcc0fe 100644 --- a/userspace/libsinsp/k8s.cpp +++ b/userspace/libsinsp/k8s.cpp @@ -96,7 +96,7 @@ void k8s::check_components() { if(m_net->has_handler(*it)) { - k8s_net::handler_ptr_t handler = m_net->get_handler(*it); + k8s_net::handler_ptr_t handler = k8s_net::get_handler(m_net->handlers(), *it); if(handler) { k8s_handler::api_error_ptr handler_error = handler->error(); @@ -229,7 +229,7 @@ void k8s::simulate_watch_event(const std::string& json, int version) { if(m_handler_map.find(component_type) == m_handler_map.end()) { - m_handler_map[component_type] = k8s_net::get_handler(m_state, component_type, false); + m_handler_map[component_type] = k8s_net::make_handler(m_state, component_type, false); } if(m_handler_map[component_type]) { diff --git a/userspace/libsinsp/k8s_api_handler.cpp b/userspace/libsinsp/k8s_api_handler.cpp index 4acaa80ac0..206d66cdc5 100644 --- a/userspace/libsinsp/k8s_api_handler.cpp +++ b/userspace/libsinsp/k8s_api_handler.cpp @@ -17,8 +17,8 @@ k8s_api_handler::k8s_api_handler(collector_ptr_t collector, ssl_ptr_t ssl, bt_ptr_t bt): k8s_handler("k8s_api_handler", false, url, path, - filter, ".", collector, http_version, - 1000L, ssl, bt, nullptr, false) + filter, ".", std::make_shared(), + collector, http_version, 1000L, ssl, bt, nullptr, false) { } diff --git a/userspace/libsinsp/k8s_component.cpp b/userspace/libsinsp/k8s_component.cpp index 67b084eb83..3b618b9dc7 100644 --- a/userspace/libsinsp/k8s_component.cpp +++ b/userspace/libsinsp/k8s_component.cpp @@ -639,6 +639,19 @@ k8s_deployment_t::k8s_deployment_t(const std::string& name, const std::string& u { } +std::vector k8s_deployment_t::get_selected_pods(const std::vector& pods) const +{ + std::vector pod_vec; + for(const auto& pod : pods) + { + if(selectors_in_labels(pod.get_labels()) && get_namespace() == pod.get_namespace()) + { + pod_vec.push_back(&pod); + } + } + return pod_vec; +} + // // event // diff --git a/userspace/libsinsp/k8s_component.h b/userspace/libsinsp/k8s_component.h index fa0c3b0064..64c387a546 100644 --- a/userspace/libsinsp/k8s_component.h +++ b/userspace/libsinsp/k8s_component.h @@ -493,6 +493,8 @@ class k8s_deployment_t : public k8s_component void set_replicas(const Json::Value& item); void set_replicas(int desired, int current); + std::vector get_selected_pods(const std::vector& pods) const; + private: k8s_replicas_t m_replicas; }; diff --git a/userspace/libsinsp/k8s_daemonset_handler.cpp b/userspace/libsinsp/k8s_daemonset_handler.cpp index ea20942d38..a233eba8a5 100644 --- a/userspace/libsinsp/k8s_daemonset_handler.cpp +++ b/userspace/libsinsp/k8s_daemonset_handler.cpp @@ -52,6 +52,7 @@ std::string k8s_daemonset_handler::STATE_FILTER = "}"; k8s_daemonset_handler::k8s_daemonset_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -60,7 +61,7 @@ k8s_daemonset_handler::k8s_daemonset_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_daemonset_handler", true, url, "/apis/extensions/v1beta1/daemonsets", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_daemonset_handler.h b/userspace/libsinsp/k8s_daemonset_handler.h index 954b6f6d06..9dc2383e72 100644 --- a/userspace/libsinsp/k8s_daemonset_handler.h +++ b/userspace/libsinsp/k8s_daemonset_handler.h @@ -15,6 +15,7 @@ class k8s_daemonset_handler : public k8s_handler { public: k8s_daemonset_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_deployment_handler.cpp b/userspace/libsinsp/k8s_deployment_handler.cpp index 309d91685c..f534a131ae 100644 --- a/userspace/libsinsp/k8s_deployment_handler.cpp +++ b/userspace/libsinsp/k8s_deployment_handler.cpp @@ -52,6 +52,7 @@ std::string k8s_deployment_handler::STATE_FILTER = "}"; k8s_deployment_handler::k8s_deployment_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -60,7 +61,7 @@ k8s_deployment_handler::k8s_deployment_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_deployment_handler", true, url, "/apis/extensions/v1beta1/deployments", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_deployment_handler.h b/userspace/libsinsp/k8s_deployment_handler.h index aa8194156a..f6bd625d4f 100644 --- a/userspace/libsinsp/k8s_deployment_handler.h +++ b/userspace/libsinsp/k8s_deployment_handler.h @@ -15,6 +15,7 @@ class k8s_deployment_handler : public k8s_handler { public: k8s_deployment_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_event_handler.cpp b/userspace/libsinsp/k8s_event_handler.cpp index 5834a6d5ae..866c335bcd 100644 --- a/userspace/libsinsp/k8s_event_handler.cpp +++ b/userspace/libsinsp/k8s_event_handler.cpp @@ -52,6 +52,7 @@ std::string k8s_event_handler::STATE_FILTER = "}"; k8s_event_handler::k8s_event_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -61,7 +62,7 @@ k8s_event_handler::k8s_event_handler(k8s_state_t& state, filter_ptr_t event_filter): k8s_handler("k8s_event_handler", true, url, "/api/v1/events", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect), m_event_filter(event_filter) { diff --git a/userspace/libsinsp/k8s_event_handler.h b/userspace/libsinsp/k8s_event_handler.h index 4e12e9bffe..09d08bc84c 100644 --- a/userspace/libsinsp/k8s_event_handler.h +++ b/userspace/libsinsp/k8s_event_handler.h @@ -17,6 +17,7 @@ class k8s_event_handler : public k8s_handler typedef user_event_filter_t::ptr_t filter_ptr_t; k8s_event_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_handler.cpp b/userspace/libsinsp/k8s_handler.cpp index 516a8337e9..e1df5614ea 100644 --- a/userspace/libsinsp/k8s_handler.cpp +++ b/userspace/libsinsp/k8s_handler.cpp @@ -32,6 +32,7 @@ k8s_handler::k8s_handler(const std::string& id, const std::string& path, const std::string& state_filter, const std::string& event_filter, + ptr_t dependency_handler, collector_ptr_t collector, const std::string& http_version, int timeout_ms, @@ -53,7 +54,8 @@ k8s_handler::k8s_handler(const std::string& id, m_bt(bt), m_watch(watch), m_connect(connect), - m_is_captured(is_captured) + m_is_captured(is_captured), + m_dependency_handler(dependency_handler) { g_logger.log("Creating K8s " + name() + " (" + m_id + ") " "handler object for [" + uri(m_url).to_string(false) + m_path + ']', @@ -78,6 +80,7 @@ void k8s_handler::make_http() m_http->add_json_filter(m_filter); m_http->add_json_filter(ERROR_FILTER); m_req_sent = false; + m_resp_recvd = false; connect(); } } @@ -181,32 +184,35 @@ void k8s_handler::check_collector_status() void k8s_handler::process_events() { - for(auto evt : m_events) + if(m_dependency_handler->is_state_built()) { - if(evt && !evt->isNull()) + for(auto evt : m_events) { - g_logger.log("k8s_handler (" + m_id + ") data:\n" + json_as_string(*evt), - sinsp_logger::SEV_TRACE); - if(m_is_captured) + if(evt && !evt->isNull()) { - m_state->enqueue_capture_event(*evt); + g_logger.log("k8s_handler (" + m_id + ") data:\n" + json_as_string(*evt), + sinsp_logger::SEV_TRACE); + if(m_is_captured) + { + m_state->enqueue_capture_event(*evt); + } + handle_json(std::move(*evt)); + if(!m_state_built) { m_state_built = true; } + } + else + { + g_logger.log("k8s_handler (" + m_id + ") error (" + uri(m_url).to_string(false) + ") " + + (!evt ? "data is null." : (evt->isNull() ? "JSON is null." : "Unknown")), + sinsp_logger::SEV_ERROR); } - handle_json(std::move(*evt)); - if(!m_state_built) { m_state_built = true; } - } - else - { - g_logger.log("k8s_handler (" + m_id + ") error (" + uri(m_url).to_string(false) + ") " + - (!evt ? "data is null." : (evt->isNull() ? "JSON is null." : "Unknown")), - sinsp_logger::SEV_ERROR); } + m_events.clear(); } - m_events.clear(); } void k8s_handler::check_state() { - if(m_collector && m_state_built && m_watch && !m_watching) + if(m_collector && m_resp_recvd && m_watch && !m_watching) { // done with initial state handling, switch to events m_collector->remove(m_http); @@ -509,6 +515,7 @@ void k8s_handler::set_event_json(json_ptr_t json, const std::string&) if(json) { m_events.emplace_back(json); + if(!m_resp_recvd) { m_resp_recvd = true; } g_logger.log("k8s_handler added event, (" + m_id + ") has " + std::to_string(m_events.size()) + " events from " + uri(m_url).to_string(false), sinsp_logger::SEV_TRACE); } diff --git a/userspace/libsinsp/k8s_handler.h b/userspace/libsinsp/k8s_handler.h index 4fd01613d7..0662bf1e9c 100644 --- a/userspace/libsinsp/k8s_handler.h +++ b/userspace/libsinsp/k8s_handler.h @@ -37,6 +37,7 @@ class k8s_handler const std::string& path, const std::string& state_filter, const std::string& event_filter, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, const std::string& http_version = "1.0", int timeout_ms = default_timeout_ms, @@ -96,6 +97,7 @@ class k8s_handler void log_not_found(const msg_data& data) const; k8s_state_t* m_state = nullptr; + bool m_state_built = false; static std::string ERROR_FILTER; @@ -133,7 +135,7 @@ class k8s_handler ssl_ptr_t m_ssl; bt_ptr_t m_bt; bool m_req_sent = false; - bool m_state_built = false; + bool m_resp_recvd = false; // some handlers only fetch state and die by design (eg. api or extensions handlers // have no need to continuously watch for updates) @@ -162,6 +164,10 @@ class k8s_handler // // global capture flag is checked in the k8s state call bool m_is_captured = false; + + // k8s_handler on which this handler depends; the dependency handler must not be null and + // it must have its state fully built before this handler can begin building its own state + ptr_t m_dependency_handler; }; inline k8s_handler::handler_ptr_t k8s_handler::handler() @@ -212,3 +218,25 @@ inline k8s_handler::api_error_ptr k8s_handler::error() const { return m_error; } + +// This dummy class serves only as a dependency stand-in for nodes, +// which have no dependencies but the logic requires a pointer to +// handler to determine whether dependency is ready; to avoid +// special casing nodes handler all over the place, we have this dummy +// liar which is always returning true for its state being built +class k8s_dummy_handler : public k8s_handler +{ +public: + k8s_dummy_handler(): k8s_handler("k8s_dummy_handler", false, "", "", + "", "", nullptr, nullptr, "", 0, + nullptr, nullptr, nullptr, false, false) + { + m_state_built = true; + } + +private: + virtual bool handle_component(const Json::Value& json, const msg_data* data = 0) + { + return false; + }; +}; diff --git a/userspace/libsinsp/k8s_namespace_handler.cpp b/userspace/libsinsp/k8s_namespace_handler.cpp index 69e0e6b7fb..b31868f85c 100644 --- a/userspace/libsinsp/k8s_namespace_handler.cpp +++ b/userspace/libsinsp/k8s_namespace_handler.cpp @@ -43,6 +43,7 @@ std::string k8s_namespace_handler::STATE_FILTER = "}"; k8s_namespace_handler::k8s_namespace_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -51,7 +52,7 @@ k8s_namespace_handler::k8s_namespace_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_namespace_handler", true, url, "/api/v1/namespaces", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_namespace_handler.h b/userspace/libsinsp/k8s_namespace_handler.h index 48559ca78e..ace19559e1 100644 --- a/userspace/libsinsp/k8s_namespace_handler.h +++ b/userspace/libsinsp/k8s_namespace_handler.h @@ -14,6 +14,7 @@ class k8s_namespace_handler : public k8s_handler { public: k8s_namespace_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_net.cpp b/userspace/libsinsp/k8s_net.cpp index 6baa6146e1..c3418b4239 100644 --- a/userspace/libsinsp/k8s_net.cpp +++ b/userspace/libsinsp/k8s_net.cpp @@ -99,63 +99,47 @@ void k8s_net::stop_watching() } } -bool k8s_net::has_dependency(const k8s_component::type_map::value_type& component) +k8s_net::handler_ptr_t k8s_net::get_dependency_handler(const handler_map_t& handlers, const k8s_component::type& component) { - switch(component.first) + switch(component) { case k8s_component::K8S_NODES: - return true; + return std::make_shared(); case k8s_component::K8S_NAMESPACES: - { - auto it = m_handlers.find(k8s_component::K8S_NODES); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_NODES); case k8s_component::K8S_PODS: - { - auto it = m_handlers.find(k8s_component::K8S_NAMESPACES); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_NAMESPACES); case k8s_component::K8S_REPLICATIONCONTROLLERS: - { - auto it = m_handlers.find(k8s_component::K8S_PODS); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_PODS); case k8s_component::K8S_SERVICES: - { - auto it = m_handlers.find(k8s_component::K8S_REPLICATIONCONTROLLERS); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_REPLICATIONCONTROLLERS); case k8s_component::K8S_REPLICASETS: - { - auto it = m_handlers.find(k8s_component::K8S_SERVICES); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_SERVICES); case k8s_component::K8S_DAEMONSETS: - { - auto it = m_handlers.find(k8s_component::K8S_REPLICASETS); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_REPLICASETS); case k8s_component::K8S_DEPLOYMENTS: - { - auto it = m_handlers.find(k8s_component::K8S_DAEMONSETS); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_DAEMONSETS); case k8s_component::K8S_EVENTS: - { - auto it = m_handlers.find(k8s_component::K8S_SERVICES); - return it!= m_handlers.end() && it->second && it->second->is_state_built(); - } + return get_handler(handlers, k8s_component::K8S_SERVICES); case k8s_component::K8S_COMPONENT_COUNT: - default: - throw sinsp_exception("k8s_net::add_handler: invalid type: " + - component.second + " (" + - std::to_string(component.first) + ')'); + default: break; } - return false; + throw sinsp_exception(std::string("Invalid K8s component type:") + std::to_string(component)); } -k8s_net::handler_ptr_t k8s_net::get_handler(k8s_state_t& state, const k8s_component::type component, bool connect, - collector_ptr_t collector, const std::string& urlstr, +k8s_net::handler_ptr_t k8s_net::get_dependency_handler(const handler_map_t& handlers, const k8s_component::type_map::value_type& component) +{ + return get_dependency_handler(handlers, component.first); +} + +bool k8s_net::has_dependency(const k8s_component::type_map::value_type& component) +{ + auto it = get_dependency_handler(m_handlers, component); + return (it && it->is_state_built()); +} + +k8s_net::handler_ptr_t k8s_net::make_handler(k8s_state_t& state, const k8s_component::type component, bool connect, + handler_ptr_t dep, collector_ptr_t collector, const std::string& urlstr, ssl_ptr_t ssl, bt_ptr_t bt, filter_ptr_t event_filter) { std::ostringstream os; @@ -170,23 +154,23 @@ k8s_net::handler_ptr_t k8s_net::get_handler(k8s_state_t& state, const k8s_compon switch(component) { case k8s_component::K8S_NODES: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_NAMESPACES: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_PODS: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_REPLICATIONCONTROLLERS: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_REPLICASETS: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_SERVICES: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_DAEMONSETS: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_DEPLOYMENTS: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect); case k8s_component::K8S_EVENTS: - return std::make_shared(state, collector, os.str(), "1.0", ssl, bt, connect, event_filter); + return std::make_shared(state, dep, collector, os.str(), "1.0", ssl, bt, connect, event_filter); case k8s_component::K8S_COMPONENT_COUNT: default: return nullptr; @@ -199,47 +183,37 @@ void k8s_net::add_handler(const k8s_component::type_map::value_type& component) { if(!has_handler(component)) { - // connections are asynchronous, so we make sure here that all components - // on which this component depends are connected and initially populated - if(has_dependency(component)) + handler_ptr_t handler = + make_handler(m_state, component.first, true, get_dependency_handler(m_handlers, component), m_collector, m_uri.to_string(), m_ssl, m_bt, m_event_filter); + if(handler) { - handler_ptr_t handler = - get_handler(m_state, component.first, true, m_collector, m_uri.to_string(), m_ssl, m_bt, m_event_filter); - if(handler) + if(!m_machine_id.empty()) { - if(!m_machine_id.empty()) - { - handler->set_machine_id(m_machine_id); - } - else if(handler->name() == "events") - { - g_logger.log("K8s machine ID (MAC) is empty - scope will not be available for " + handler->name(), - sinsp_logger::SEV_WARNING); - } - m_handlers[component.first] = handler; + handler->set_machine_id(m_machine_id); } - else + else if(handler->name() == "events") { - std::ostringstream os; - os << "K8s: invalid component type encountered while creating handler: " << - component.second << " (" << - std::to_string(component.first) << ')'; - if(k8s_component::is_critical(component)) - { - throw sinsp_exception(os.str()); - } - else - { - g_logger.log(os.str(), sinsp_logger::SEV_ERROR); - } + g_logger.log("K8s machine ID (MAC) is empty - scope will not be available for " + handler->name(), + sinsp_logger::SEV_WARNING); } - g_logger.log("K8s: created " + k8s_component::get_name(component) + " handler.", sinsp_logger::SEV_INFO); + m_handlers[component.first] = handler; } else { - g_logger.log("K8s: component " + k8s_component::get_name(component) + " does not have dependencies populated yet.", - sinsp_logger::SEV_DEBUG); + std::ostringstream os; + os << "K8s: invalid component type encountered while creating handler: " << + component.second << " (" << + std::to_string(component.first) << ')'; + if(k8s_component::is_critical(component)) + { + throw sinsp_exception(os.str()); + } + else + { + g_logger.log(os.str(), sinsp_logger::SEV_ERROR); + } } + g_logger.log("K8s: created " + k8s_component::get_name(component) + " handler.", sinsp_logger::SEV_INFO); } else { diff --git a/userspace/libsinsp/k8s_net.h b/userspace/libsinsp/k8s_net.h index 0894514817..ab81d48a64 100644 --- a/userspace/libsinsp/k8s_net.h +++ b/userspace/libsinsp/k8s_net.h @@ -37,24 +37,16 @@ class k8s_net ~k8s_net(); - static handler_ptr_t get_handler(k8s_state_t& state, const k8s_component::type component, bool connect = true, + static handler_ptr_t make_handler(k8s_state_t& state, const k8s_component::type component, bool connect = true, + handler_ptr_t dep = std::make_shared(), collector_ptr_t collector = nullptr, const std::string& urlstr = "", ssl_ptr_t ssl = nullptr, bt_ptr_t bt = nullptr, filter_ptr_t event_filter = nullptr); void add_handler(const k8s_component::type_map::value_type& component); bool has_handler(const k8s_component::type_map::value_type& component); - handler_ptr_t get_handler(const k8s_component::type_map::value_type& component); bool has_dependency(const k8s_component::type_map::value_type& component); - bool is_state_built(const k8s_component::type_map::value_type& component) - { - const auto& it = m_handlers.find(component.first); - if(it != m_handlers.end()) - { - return it->second && it->second->is_state_built(); - } - return false; - } + bool is_state_built(const k8s_component::type_map::value_type& component); void watch(); void stop_watching(); @@ -63,14 +55,20 @@ class k8s_net void set_machine_id(const std::string& machine_id); const std::string& get_machine_id() const; + typedef k8s_handler::handler_t handler_t; + typedef std::map handler_map_t; + + const handler_map_t& handlers() const; + static handler_ptr_t get_handler(const handler_map_t& handlers, k8s_component::type component); + static handler_ptr_t get_handler(const handler_map_t& handlers, const k8s_component::type_map::value_type& component); + static handler_ptr_t get_dependency_handler(const handler_map_t& handlers, const k8s_component::type_map::value_type& component); + static handler_ptr_t get_dependency_handler(const handler_map_t& handlers, const k8s_component::type& component); + private: void init(); bool is_secure(); void cleanup(); - typedef k8s_handler::handler_t handler_t; - typedef std::map handler_map_t; - k8s& m_k8s; k8s_state_t& m_state; collector_ptr_t m_collector; @@ -101,16 +99,37 @@ inline bool k8s_net::has_handler(const k8s_component::type_map::value_type& comp return (it != m_handlers.end()) && it->second; } -inline k8s_net::handler_ptr_t k8s_net::get_handler(const k8s_component::type_map::value_type& component) +inline k8s_net::handler_ptr_t k8s_net::get_handler(const handler_map_t& handlers, k8s_component::type component) { - auto it = m_handlers.find(component.first); - if(it != m_handlers.end()) + auto it = handlers.find(component); + if(it != handlers.end()) { return it->second; } return nullptr; } +inline k8s_net::handler_ptr_t k8s_net::get_handler(const handler_map_t& handlers, const k8s_component::type_map::value_type& component) +{ + return get_handler(handlers, component.first); + /*auto it = handlers.find(component.first); + if(it != handlers.end()) + { + return it->second; + } + return nullptr;*/ +} + +inline bool k8s_net::is_state_built(const k8s_component::type_map::value_type& component) +{ + const auto& it = m_handlers.find(component.first); + if(it != m_handlers.end()) + { + return it->second && it->second->is_state_built(); + } + return false; +} + inline void k8s_net::set_machine_id(const std::string& machine_id) { m_machine_id = machine_id; @@ -121,4 +140,9 @@ inline const std::string& k8s_net::get_machine_id() const return m_machine_id; } +inline const k8s_net::handler_map_t& k8s_net::handlers() const +{ + return m_handlers; +} + #endif // HAS_CAPTURE diff --git a/userspace/libsinsp/k8s_node_handler.cpp b/userspace/libsinsp/k8s_node_handler.cpp index d557d49d2d..0b0eb1f943 100644 --- a/userspace/libsinsp/k8s_node_handler.cpp +++ b/userspace/libsinsp/k8s_node_handler.cpp @@ -46,6 +46,7 @@ std::string k8s_node_handler::STATE_FILTER = "}"; k8s_node_handler::k8s_node_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -54,7 +55,7 @@ k8s_node_handler::k8s_node_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_node_handler", true, url, "/api/v1/nodes", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_node_handler.h b/userspace/libsinsp/k8s_node_handler.h index a8d1d69f73..0de3ab8d0f 100644 --- a/userspace/libsinsp/k8s_node_handler.h +++ b/userspace/libsinsp/k8s_node_handler.h @@ -15,6 +15,7 @@ class k8s_node_handler : public k8s_handler { public: k8s_node_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_pod_handler.cpp b/userspace/libsinsp/k8s_pod_handler.cpp index 267a93f975..b5d9de195a 100644 --- a/userspace/libsinsp/k8s_pod_handler.cpp +++ b/userspace/libsinsp/k8s_pod_handler.cpp @@ -58,6 +58,7 @@ std::string k8s_pod_handler::STATE_FILTER = "}"; k8s_pod_handler::k8s_pod_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -66,7 +67,7 @@ k8s_pod_handler::k8s_pod_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_pod_handler", true, url, "/api/v1/pods?fieldSelector=status.phase%3DRunning", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_pod_handler.h b/userspace/libsinsp/k8s_pod_handler.h index c33a006ed4..2cb8554903 100644 --- a/userspace/libsinsp/k8s_pod_handler.h +++ b/userspace/libsinsp/k8s_pod_handler.h @@ -15,6 +15,7 @@ class k8s_pod_handler : public k8s_handler { public: k8s_pod_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_replicaset_handler.cpp b/userspace/libsinsp/k8s_replicaset_handler.cpp index 680c15fea6..cc04fef474 100644 --- a/userspace/libsinsp/k8s_replicaset_handler.cpp +++ b/userspace/libsinsp/k8s_replicaset_handler.cpp @@ -52,6 +52,7 @@ std::string k8s_replicaset_handler::STATE_FILTER = "}"; k8s_replicaset_handler::k8s_replicaset_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -60,7 +61,7 @@ k8s_replicaset_handler::k8s_replicaset_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_replicaset_handler", true, url, "/apis/extensions/v1beta1/replicasets", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_replicaset_handler.h b/userspace/libsinsp/k8s_replicaset_handler.h index ee75c403c2..dc9f03363f 100644 --- a/userspace/libsinsp/k8s_replicaset_handler.h +++ b/userspace/libsinsp/k8s_replicaset_handler.h @@ -15,6 +15,7 @@ class k8s_replicaset_handler : public k8s_handler { public: k8s_replicaset_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_replicationcontroller_handler.cpp b/userspace/libsinsp/k8s_replicationcontroller_handler.cpp index 32bbe1563c..28d3182fa0 100644 --- a/userspace/libsinsp/k8s_replicationcontroller_handler.cpp +++ b/userspace/libsinsp/k8s_replicationcontroller_handler.cpp @@ -52,6 +52,7 @@ std::string k8s_replicationcontroller_handler::STATE_FILTER = "}"; k8s_replicationcontroller_handler::k8s_replicationcontroller_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -60,7 +61,7 @@ k8s_replicationcontroller_handler::k8s_replicationcontroller_handler(k8s_state_t bool connect): k8s_handler("k8s_replicationcontroller_handler", true, url, "/api/v1/replicationcontrollers", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_replicationcontroller_handler.h b/userspace/libsinsp/k8s_replicationcontroller_handler.h index d62ba42a2b..c2828a54b3 100644 --- a/userspace/libsinsp/k8s_replicationcontroller_handler.h +++ b/userspace/libsinsp/k8s_replicationcontroller_handler.h @@ -15,6 +15,7 @@ class k8s_replicationcontroller_handler : public k8s_handler { public: k8s_replicationcontroller_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_service_handler.cpp b/userspace/libsinsp/k8s_service_handler.cpp index 9a1d6460c7..edc541a215 100644 --- a/userspace/libsinsp/k8s_service_handler.cpp +++ b/userspace/libsinsp/k8s_service_handler.cpp @@ -52,6 +52,7 @@ std::string k8s_service_handler::STATE_FILTER = "}"; k8s_service_handler::k8s_service_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector, std::string url, const std::string& http_version, @@ -60,7 +61,7 @@ k8s_service_handler::k8s_service_handler(k8s_state_t& state, bool connect): k8s_handler("k8s_service_handler", true, url, "/api/v1/services", - STATE_FILTER, EVENT_FILTER, collector, + STATE_FILTER, EVENT_FILTER, dependency_handler, collector, http_version, 1000L, ssl, bt, &state, true, connect) { } diff --git a/userspace/libsinsp/k8s_service_handler.h b/userspace/libsinsp/k8s_service_handler.h index acf49f904e..91b4e27028 100644 --- a/userspace/libsinsp/k8s_service_handler.h +++ b/userspace/libsinsp/k8s_service_handler.h @@ -15,6 +15,7 @@ class k8s_service_handler : public k8s_handler { public: k8s_service_handler(k8s_state_t& state, + ptr_t dependency_handler, collector_ptr_t collector = nullptr, std::string url = "", const std::string& http_version = "1.0", diff --git a/userspace/libsinsp/k8s_state.cpp b/userspace/libsinsp/k8s_state.cpp index ed9c84794b..694c9c9c72 100644 --- a/userspace/libsinsp/k8s_state.cpp +++ b/userspace/libsinsp/k8s_state.cpp @@ -441,27 +441,26 @@ void k8s_state_t::update_cache(const k8s_component::type_map::key_type& componen case k8s_component::K8S_DEPLOYMENTS: { - // TODO - /*const k8s_services& services = get_services(); + const k8s_deployments& deployments = get_deployments(); const k8s_pods& pods = get_pods(); - k8s_state_t::pod_service_map& pod_svc_map = get_pod_service_map(); - pod_svc_map.clear(); - for(const auto& service : services) + k8s_state_t::pod_deployment_map& pod_deployment_map = get_pod_deployment_map(); + pod_deployment_map.clear(); + for(const auto& deployment : deployments) { - std::vector pod_subset = service.get_selected_pods(pods); + std::vector pod_subset = deployment.get_selected_pods(pods); for(auto& pod : pod_subset) { const std::string& pod_uid = pod->get_uid(); - if(!is_component_cached(pod_svc_map, pod_uid, &service)) + if(!is_component_cached(pod_deployment_map, pod_uid, &deployment)) { - cache_component(pod_svc_map, pod_uid, &service); + cache_component(pod_deployment_map, pod_uid, &deployment); } else { - g_logger.log("Attempt to cache already cached SERVICE: " + pod_uid, sinsp_logger::SEV_ERROR); + g_logger.log("Attempt to cache already cached Deployment: " + pod_uid, sinsp_logger::SEV_ERROR); } } - }*/ + } } break; diff --git a/userspace/libsinsp/k8s_state.h b/userspace/libsinsp/k8s_state.h index 2d69580d2b..656b77308c 100644 --- a/userspace/libsinsp/k8s_state.h +++ b/userspace/libsinsp/k8s_state.h @@ -26,6 +26,7 @@ class k8s_state_t typedef std::unordered_multimap pod_service_map; typedef std::unordered_map pod_rc_map; typedef std::unordered_map pod_rs_map; + typedef std::unordered_multimap pod_deployment_map; static const int CAPTURE_VERSION_NONE = -1; static const int CAPTURE_VERSION_1 = 1; @@ -247,6 +248,7 @@ class k8s_state_t const pod_service_map& get_pod_service_map() const { return m_pod_services; } const pod_rc_map& get_pod_rc_map() const { return m_pod_rcs; } const pod_rs_map& get_pod_rs_map() const { return m_pod_rss; } + const pod_deployment_map& get_pod_deployment_map() const { return m_pod_deployments; } #ifdef HAS_CAPTURE void set_capture_version(int version); @@ -320,6 +322,7 @@ class k8s_state_t pod_service_map& get_pod_service_map() { return m_pod_services; } pod_rc_map& get_pod_rc_map() { return m_pod_rcs; } pod_rs_map& get_pod_rs_map() { return m_pod_rss; } + pod_deployment_map& get_pod_deployment_map() { return m_pod_deployments; } static const std::string m_docker_prefix; // "docker://" static const std::string m_rkt_prefix; // "rkt://" @@ -329,6 +332,7 @@ class k8s_state_t pod_service_map m_pod_services; pod_rc_map m_pod_rcs; pod_rs_map m_pod_rss; + pod_deployment_map m_pod_deployments; #ifdef HAS_CAPTURE event_list_t m_capture_events; #endif // HAS_CAPTURE diff --git a/userspace/libsinsp/socket_handler.h b/userspace/libsinsp/socket_handler.h index 9baa0acd30..a022226554 100644 --- a/userspace/libsinsp/socket_handler.h +++ b/userspace/libsinsp/socket_handler.h @@ -514,6 +514,9 @@ class socket_data_handler return nullptr; } + // connection is non-blocking and a socket + // should not be polled until it is connected + // this flag indicates readiness to be polled bool is_enabled() const { return m_enabled; diff --git a/userspace/sysdig.project b/userspace/sysdig.project index 39d240d85c..b877356cf9 100644 --- a/userspace/sysdig.project +++ b/userspace/sysdig.project @@ -190,8 +190,13 @@ - - + + + + + + +