Skip to content

Commit

Permalink
Add an introspection endpoint for container metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
Molter73 committed Apr 1, 2024
1 parent d7fb9bc commit af350d6
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 0 deletions.
3 changes: 3 additions & 0 deletions collector/lib/CollectorConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ BoolEnvVar enable_runtime_filters("ROX_COLLECTOR_RUNTIME_FILTERS_ENABLED", false
BoolEnvVar use_docker_ce("ROX_COLLECTOR_CE_USE_DOCKER", false);
BoolEnvVar use_podman_ce("ROX_COLLECTOR_CE_USE_PODMAN", false);

BoolEnvVar enable_introspection("ROX_COLLECTOR_INTROSPECTION_ENABLE", false);

} // namespace

constexpr bool CollectorConfig::kTurnOffScrape;
Expand Down Expand Up @@ -79,6 +81,7 @@ void CollectorConfig::InitCollectorConfig(CollectorArgs* args) {
enable_runtime_filters_ = enable_runtime_filters.value();
use_docker_ce_ = use_docker_ce.value();
use_podman_ce_ = use_podman_ce.value();
enable_introspection_ = enable_introspection.value();

for (const auto& syscall : kSyscalls) {
syscalls_.push_back(syscall);
Expand Down
2 changes: 2 additions & 0 deletions collector/lib/CollectorConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class CollectorConfig {
bool EnableRuntimeFilters() const { return enable_runtime_filters_; }
bool UseDockerCe() const { return use_docker_ce_; }
bool UsePodmanCe() const { return use_podman_ce_; }
bool IsIntrospectionEnabled() const { return enable_introspection_; }
const std::vector<double>& GetConnectionStatsQuantiles() const { return connection_stats_quantiles_; }
double GetConnectionStatsError() const { return connection_stats_error_; }
unsigned int GetConnectionStatsWindow() const { return connection_stats_window_; }
Expand Down Expand Up @@ -113,6 +114,7 @@ class CollectorConfig {
bool enable_runtime_filters_;
bool use_docker_ce_;
bool use_podman_ce_;
bool enable_introspection_;
std::vector<double> connection_stats_quantiles_;
double connection_stats_error_;
unsigned int connection_stats_window_;
Expand Down
9 changes: 9 additions & 0 deletions collector/lib/CollectorService.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "CollectorService.h"

#include "ContainerInfoInspector.h"

extern "C" {
#include <signal.h>
}
Expand Down Expand Up @@ -58,6 +60,8 @@ void CollectorService::RunForever() {

std::unique_ptr<NetworkStatusNotifier> net_status_notifier;

std::unique_ptr<ContainerInfoInspector> container_info_inspector;

CLOG(INFO) << "Network scrape interval set to " << config_.ScrapeInterval() << " seconds";

if (config_.grpc_channel) {
Expand Down Expand Up @@ -99,6 +103,11 @@ void CollectorService::RunForever() {
CLOG(FATAL) << "Unable to start collector stats exporter";
}

if (config_.IsIntrospectionEnabled()) {
container_info_inspector = std::make_unique<ContainerInfoInspector>(system_inspector_.GetContainerMetadataInspector());
server.addHandler(container_info_inspector->kBaseRoute, container_info_inspector.get());
}

system_inspector_.Init(config_, conn_tracker);
system_inspector_.Start();

Expand Down
34 changes: 34 additions & 0 deletions collector/lib/ContainerInfoInspector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "ContainerInfoInspector.h"

#include <civetweb.h>
#include <string>
#include <string_view>

namespace collector {
const char* const ContainerInfoInspector::kBaseRoute = "/state/containers/";

bool ContainerInfoInspector::handleGet(CivetServer* server, struct mg_connection* conn) {
const mg_request_info* req_info = mg_get_request_info(conn);
if (req_info == nullptr) {
return ServerError(conn, "unable to read request");
}

std::string_view url = req_info->local_uri;
std::string container_id(url.substr(url.rfind('/') + 1));

if (container_id.length() != 12) {
return ClientError(conn, "invalid container ID");
}

Json::Value root;

root["container_id"] = container_id;
root["namespace"] = std::string(container_metadata_inspector_->GetNamespace(container_id));

mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nConnection: close\r\n\r\n");
mg_printf(conn, "%s\r\n", writer_.write(root).c_str());

return true;
}

} // namespace collector
34 changes: 34 additions & 0 deletions collector/lib/ContainerInfoInspector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef _CONTAINER_INFO_INSPECTOR_
#define _CONTAINER_INFO_INSPECTOR_

#include <CivetServer.h>
#include <civetweb.h>
#include <memory>
#include <string>
#include <unordered_map>

#include "ContainerMetadata.h"
#include "IntrospectionEndpoint.h"
#include "json/writer.h"

namespace collector {

using QueryParams = std::unordered_map<std::string, std::string>;

class ContainerInfoInspector : public IntrospectionEndpoint {
public:
static const char* const kBaseRoute;

ContainerInfoInspector(const std::shared_ptr<ContainerMetadata>& cmi) : container_metadata_inspector_(cmi) {}

// implementation of CivetHandler
bool handleGet(CivetServer* server, struct mg_connection* conn) override;

private:
std::shared_ptr<ContainerMetadata> container_metadata_inspector_;
Json::FastWriter writer_;
};

} // namespace collector

#endif //_CONTAINER_INFO_INSPECTOR_
33 changes: 33 additions & 0 deletions collector/lib/IntrospectionEndpoint.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "IntrospectionEndpoint.h"

#include <sstream>

namespace collector {

QueryParams IntrospectionEndpoint::ParseParameters(const char* queryString) {
QueryParams params;

if (queryString == nullptr) {
return params;
}

std::stringstream query_stringstream(queryString);
while (query_stringstream.good()) {
std::string statement;

std::getline(query_stringstream, statement, '&');

size_t equal = statement.find('=');

if (equal != std::string::npos) {
params[statement.substr(0, equal)] = statement.substr(equal + 1);
}
}
return params;
}

std::optional<std::string> IntrospectionEndpoint::GetParameter(const QueryParams& params, const std::string& paramName) {
return params.count(paramName) != 0 ? std::make_optional(params.at(paramName)) : std::nullopt;
}

} // namespace collector
27 changes: 27 additions & 0 deletions collector/lib/IntrospectionEndpoint.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef _INTROSPECTION_ENDPOINT_
#define _INTROSPECTION_ENDPOINT_

#include <CivetServer.h>
#include <optional>
#include <unordered_map>

namespace collector {

using QueryParams = std::unordered_map<std::string, std::string>;

class IntrospectionEndpoint : public CivetHandler {
protected:
static QueryParams ParseParameters(const char* queryString);
static std::optional<std::string> GetParameter(const QueryParams& params, const std::string& paramName);

static bool ServerError(struct mg_connection* conn, const char* err) {
return mg_send_http_error(conn, 500, err) >= 0;
}
static bool ClientError(struct mg_connection* conn, const char* err) {
return mg_send_http_error(conn, 400, err) >= 0;
}
};

} // namespace collector

#endif // _INTROSPECTION_ENDPOINT_
3 changes: 3 additions & 0 deletions collector/lib/system-inspector/Service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "CollectorException.h"
#include "CollectorStats.h"
#include "ContainerEngine.h"
#include "ContainerMetadata.h"
#include "EventNames.h"
#include "HostInfo.h"
#include "KernelDriver.h"
Expand Down Expand Up @@ -89,6 +90,8 @@ bool Service::InitKernel(const CollectorConfig& config, const DriverCandidate& c
inspector_->get_parser()->set_track_connection_status(true);
}

container_metadata_inspector_.reset(new ContainerMetadata(inspector_.get()));

if (config.EnableRuntimeFilters()) {
uint64_t mask = 1 << CT_CRI |
1 << CT_CRIO |
Expand Down
4 changes: 4 additions & 0 deletions collector/lib/system-inspector/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "libsinsp/sinsp.h"

#include "ContainerMetadata.h"
#include "Control.h"
#include "DriverCandidates.h"
#include "SignalHandler.h"
Expand Down Expand Up @@ -44,6 +45,8 @@ class Service : public SystemInspector {

void GetProcessInformation(uint64_t pid, ProcessInfoCallbackRef callback);

std::shared_ptr<ContainerMetadata> GetContainerMetadataInspector() { return container_metadata_inspector_; };

private:
FRIEND_TEST(SystemInspectorServiceTest, FilterEvent);

Expand All @@ -69,6 +72,7 @@ class Service : public SystemInspector {

mutable std::mutex libsinsp_mutex_;
std::unique_ptr<sinsp> inspector_;
std::shared_ptr<ContainerMetadata> container_metadata_inspector_;
std::unique_ptr<sinsp_evt_formatter> default_formatter_;
std::unique_ptr<ISignalServiceClient> signal_client_;
std::vector<SignalHandlerEntry> signal_handlers_;
Expand Down

0 comments on commit af350d6

Please sign in to comment.