Skip to content
This repository was archived by the owner on Aug 19, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 103 additions & 175 deletions src/configuration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,105 +35,111 @@
namespace google {

namespace {

constexpr const char kConfigFileFlag[] = "config-file";

constexpr const char kDefaultProjectId[] = "";
constexpr const char kDefaultCredentialsFile[] = "";
constexpr const int kMetadataApiDefaultNumThreads = 3;
constexpr const int kMetadataApiDefaultPort = 8000;
constexpr const char kMetadataApiDefaultBindAddress[] = "0.0.0.0";
constexpr const char kMetadataApiDefaultResourceTypeSeparator[] = ".";
constexpr const int kMetadataReporterDefaultIntervalSeconds = 60;
constexpr const int kMetadataReporterDefaultPurgeDeleted = false;
constexpr const char kMetadataReporterDefaultUserAgent[] =
"metadata-agent/" STRINGIFY(AGENT_VERSION);
constexpr const char kMetadataIngestionDefaultEndpointFormat[] =
"https://stackdriver.googleapis.com/v1beta2/projects/{{project_id}}"
"/resourceMetadata:batchUpdate";
constexpr const int kMetadataIngestionDefaultRequestSizeLimitBytes =
8*1024*1024;
constexpr const int kMetadataIngestionDefaultRequestSizeLimitCount = 1000;
constexpr const char kMetadataIngestionDefaultRawContentVersion[] = "0.1";
constexpr const int kInstanceUpdaterDefaultIntervalSeconds = 60*60;
constexpr const char kDefaultInstanceResourceType[] =
""; // A blank value means "unspecified; detect via environment".
constexpr const int kDockerUpdaterDefaultIntervalSeconds = 0;
constexpr const char kDockerDefaultEndpointHost[] =
"unix://%2Fvar%2Frun%2Fdocker.sock/";
constexpr const char kDockerDefaultApiVersion[] = "1.23";
constexpr const char kDockerDefaultContainerFilter[] = "limit=30";
constexpr const int kKubernetesUpdaterDefaultIntervalSeconds = 0;
constexpr const int kKubernetesUpdaterDefaultWatchConnectionRetries = 15;
constexpr const char kKubernetesDefaultEndpointHost[] =
"https://kubernetes.default.svc";
constexpr const char kKubernetesDefaultPodLabelSelector[] = "";
constexpr const char kKubernetesDefaultClusterName[] = "";
constexpr const char kKubernetesDefaultClusterLocation[] = "";
constexpr const char kKubernetesDefaultNodeName[] = "";
constexpr const bool kKubernetesDefaultUseWatch = false;
constexpr const bool kKubernetesDefaultClusterLevelMetadata = false;
constexpr const bool kKubernetesDefaultServiceMetadata = true;
constexpr const char kDefaultInstanceId[] = "";
constexpr const char kDefaultInstanceZone[] = "";
constexpr const char kDefaultHealthCheckFile[] =
"/var/run/metadata-agent/health/unhealthy";
constexpr const int kDefaultHealthCheckMaxDataAgeSeconds = 5*60;
class Option {
public:
virtual void Set(const YAML::Node& value) = 0;
};

template<class T, class D>
class OptionDef : public Option {
public:
OptionDef(T& var, const D& default_) : var_(var) {
var = default_;
}
void Set(const YAML::Node& value) { var_ = value.as<T>(var_); }
private:
T& var_;
};

template<class T, class D>
Option* option(T& var, const D& default_) {
return new OptionDef<T, D>(var, default_);
}

}

class Configuration::OptionMap
: public std::map<std::string, std::unique_ptr<Option>> {
public:
OptionMap(std::vector<std::pair<const char*, Option*>>&& v) {
for (const auto& p : v) {
emplace(p.first, std::unique_ptr<Option>(p.second));
}
}
};

Configuration::Configuration()
: project_id_(kDefaultProjectId),
credentials_file_(kDefaultCredentialsFile),
verbose_logging_(false),
metadata_api_num_threads_(kMetadataApiDefaultNumThreads),
metadata_api_port_(kMetadataApiDefaultPort),
metadata_api_bind_address_(kMetadataApiDefaultBindAddress),
metadata_api_resource_type_separator_(
kMetadataApiDefaultResourceTypeSeparator),
metadata_reporter_interval_seconds_(
kMetadataReporterDefaultIntervalSeconds),
metadata_reporter_purge_deleted_(
kMetadataReporterDefaultPurgeDeleted),
metadata_reporter_user_agent_(
kMetadataReporterDefaultUserAgent),
metadata_ingestion_endpoint_format_(
kMetadataIngestionDefaultEndpointFormat),
metadata_ingestion_request_size_limit_bytes_(
kMetadataIngestionDefaultRequestSizeLimitBytes),
metadata_ingestion_request_size_limit_count_(
kMetadataIngestionDefaultRequestSizeLimitCount),
metadata_ingestion_raw_content_version_(
kMetadataIngestionDefaultRawContentVersion),
instance_updater_interval_seconds_(
kInstanceUpdaterDefaultIntervalSeconds),
instance_resource_type_(kDefaultInstanceResourceType),
docker_updater_interval_seconds_(kDockerUpdaterDefaultIntervalSeconds),
docker_endpoint_host_(kDockerDefaultEndpointHost),
docker_api_version_(kDockerDefaultApiVersion),
docker_container_filter_(kDockerDefaultContainerFilter),
kubernetes_updater_interval_seconds_(
kKubernetesUpdaterDefaultIntervalSeconds),
kubernetes_updater_watch_connection_retries_(
kKubernetesUpdaterDefaultWatchConnectionRetries),
kubernetes_endpoint_host_(kKubernetesDefaultEndpointHost),
kubernetes_pod_label_selector_(kKubernetesDefaultPodLabelSelector),
kubernetes_cluster_name_(kKubernetesDefaultClusterName),
kubernetes_cluster_location_(kKubernetesDefaultClusterLocation),
kubernetes_node_name_(kKubernetesDefaultNodeName),
kubernetes_use_watch_(kKubernetesDefaultUseWatch),
kubernetes_cluster_level_metadata_(
kKubernetesDefaultClusterLevelMetadata),
kubernetes_service_metadata_(kKubernetesDefaultServiceMetadata),
instance_id_(kDefaultInstanceId),
instance_zone_(kDefaultInstanceZone),
health_check_file_(kDefaultHealthCheckFile),
health_check_max_data_age_seconds_(
kDefaultHealthCheckMaxDataAgeSeconds) {}
: verbose_logging_(false),
options_(new OptionMap({
{"ProjectId", option(project_id_, "")},
{"CredentialsFile", option(credentials_file_, "")},
{"MetadataApiNumThreads", option(metadata_api_num_threads_, 3)},
{"MetadataApiPort", option(metadata_api_port_, 8000)},
{"MetadataApiBindAddress",
option(metadata_api_bind_address_, "0.0.0.0")},
{"MetadataApiResourceTypeSeparator",
option(metadata_api_resource_type_separator_, ".")},
{"MetadataReporterIntervalSeconds",
option(metadata_reporter_interval_seconds_, 60)},
{"MetadataReporterPurgeDeleted",
option(metadata_reporter_purge_deleted_, false)},
{"MetadataReporterUserAgent",
option(metadata_reporter_user_agent_,
"metadata-agent/" STRINGIFY(AGENT_VERSION))},
{"MetadataIngestionEndpointFormat",
option(metadata_ingestion_endpoint_format_,
"https://stackdriver.googleapis.com/v1beta2/projects/"
"{{project_id}}/resourceMetadata:batchUpdate")},
{"MetadataIngestionRequestSizeLimitBytes",
option(metadata_ingestion_request_size_limit_bytes_, 8*1024*1024)},
{"MetadataIngestionRequestSizeLimitCount",
option(metadata_ingestion_request_size_limit_count_, 1000)},
{"MetadataIngestionRawContentVersion",
option(metadata_ingestion_raw_content_version_, "0.1")},
{"InstanceUpdaterIntervalSeconds",
option(instance_updater_interval_seconds_, 60*60)},
// A blank value means "unspecified; detect via environment".
{"InstanceResourceType", option(instance_resource_type_, "")},
{"DockerUpdaterIntervalSeconds",
option(docker_updater_interval_seconds_, 0)},
{"DockerEndpointHost",
option(docker_endpoint_host_, "unix://%2Fvar%2Frun%2Fdocker.sock/")},
{"DockerApiVersion", option(docker_api_version_, "1.23")},
{"DockerContainerFilter", option(docker_container_filter_, "limit=30")},
{"KubernetesUpdaterIntervalSeconds",
option(kubernetes_updater_interval_seconds_, 0)},
{"KubernetesUpdaterWatchConnectionRetries",
option(kubernetes_updater_watch_connection_retries_, 15)},
{"KubernetesEndpointHost",
option(kubernetes_endpoint_host_, "https://kubernetes.default.svc")},
{"KubernetesPodLabelSelector",
option(kubernetes_pod_label_selector_, "")},
{"KubernetesClusterName", option(kubernetes_cluster_name_, "")},
{"KubernetesClusterLocation", option(kubernetes_cluster_location_, "")},
{"KubernetesNodeName", option(kubernetes_node_name_, "")},
{"KubernetesUseWatch", option(kubernetes_use_watch_, false)},
{"KubernetesClusterLevelMetadata",
option(kubernetes_cluster_level_metadata_, false)},
{"KubernetesServiceMetadata",
option(kubernetes_service_metadata_, true)},
{"InstanceId", option(instance_id_, "")},
{"InstanceZone", option(instance_zone_, "")},
{"HealthCheckFile",
option(health_check_file_,
"/var/run/metadata-agent/health/unhealthy")},
{"HealthCheckMaxDataAgeSeconds",
option(health_check_max_data_age_seconds_, 5*60)},
})) {}

Configuration::Configuration(std::istream& input) : Configuration() {
ParseConfiguration(input);
}

Configuration::~Configuration() = default;

int Configuration::ParseArguments(int ac, char** av) {
std::string config_file;
boost::program_options::options_description flags_desc;
Expand Down Expand Up @@ -219,93 +225,15 @@ void Configuration::ParseConfigFile(const std::string& filename) {
void Configuration::ParseConfiguration(std::istream& input) {
YAML::Node config = YAML::Load(input);
std::lock_guard<std::mutex> lock(mutex_);
project_id_ =
config["ProjectId"].as<std::string>(project_id_);
credentials_file_ =
config["CredentialsFile"].as<std::string>(credentials_file_);
metadata_api_num_threads_ =
config["MetadataApiNumThreads"].as<int>(metadata_api_num_threads_);
metadata_api_port_ =
config["MetadataApiPort"].as<int>(metadata_api_port_);
metadata_api_bind_address_ =
config["MetadataApiBindAddress"].as<std::string>(
metadata_api_bind_address_);
metadata_api_resource_type_separator_ =
config["MetadataApiResourceTypeSeparator"].as<std::string>(
metadata_api_resource_type_separator_);
metadata_reporter_interval_seconds_ =
config["MetadataReporterIntervalSeconds"].as<int>(
metadata_reporter_interval_seconds_);
metadata_reporter_purge_deleted_ =
config["MetadataReporterPurgeDeleted"].as<bool>(
metadata_reporter_purge_deleted_);
metadata_reporter_user_agent_ =
config["MetadataReporterUserAgent"].as<std::string>(
metadata_reporter_user_agent_);
metadata_ingestion_endpoint_format_ =
config["MetadataIngestionEndpointFormat"].as<std::string>(
metadata_ingestion_endpoint_format_);
metadata_ingestion_request_size_limit_bytes_ =
config["MetadataIngestionRequestSizeLimitBytes"].as<int>(
metadata_ingestion_request_size_limit_bytes_);
metadata_ingestion_request_size_limit_count_ =
config["MetadataIngestionRequestSizeLimitCount"].as<int>(
metadata_ingestion_request_size_limit_count_);
metadata_ingestion_raw_content_version_ =
config["MetadataIngestionRawContentVersion"].as<std::string>(
metadata_ingestion_raw_content_version_);
instance_updater_interval_seconds_ =
config["InstanceUpdaterIntervalSeconds"].as<int>(
instance_updater_interval_seconds_);
instance_resource_type_ =
config["InstanceResourceType"].as<std::string>(instance_resource_type_);
docker_updater_interval_seconds_ =
config["DockerUpdaterIntervalSeconds"].as<int>(
docker_updater_interval_seconds_);
docker_endpoint_host_ =
config["DockerEndpointHost"].as<std::string>(docker_endpoint_host_);
docker_api_version_ =
config["DockerApiVersion"].as<std::string>(docker_api_version_);
docker_container_filter_ =
config["DockerContainerFilter"].as<std::string>(
docker_container_filter_);
kubernetes_updater_interval_seconds_ =
config["KubernetesUpdaterIntervalSeconds"].as<int>(
kubernetes_updater_interval_seconds_);
kubernetes_updater_watch_connection_retries_ =
config["KubernetesUpdaterWatchConnectionRetries"].as<int>(
kubernetes_updater_watch_connection_retries_);
kubernetes_endpoint_host_ =
config["KubernetesEndpointHost"].as<std::string>(
kubernetes_endpoint_host_);
kubernetes_pod_label_selector_ =
config["KubernetesPodLabelSelector"].as<std::string>(
kubernetes_pod_label_selector_);
kubernetes_cluster_name_ =
config["KubernetesClusterName"].as<std::string>(
kubernetes_cluster_name_);
kubernetes_cluster_location_ =
config["KubernetesClusterLocation"].as<std::string>(
kubernetes_cluster_location_);
kubernetes_node_name_ =
config["KubernetesNodeName"].as<std::string>(kubernetes_node_name_);
kubernetes_use_watch_ =
config["KubernetesUseWatch"].as<bool>(kubernetes_use_watch_);
kubernetes_cluster_level_metadata_ =
config["KubernetesClusterLevelMetadata"].as<bool>(
kubernetes_cluster_level_metadata_);
kubernetes_service_metadata_ =
config["KubernetesServiceMetadata"].as<bool>(
kubernetes_service_metadata_);
instance_id_ =
config["InstanceId"].as<std::string>(instance_id_);
instance_zone_ =
config["InstanceZone"].as<std::string>(instance_zone_);
health_check_file_ =
config["HealthCheckFile"].as<std::string>(health_check_file_);
health_check_max_data_age_seconds_ =
config["HealthCheckMaxDataAgeSeconds"].as<int>(
health_check_max_data_age_seconds_);
for (const auto& kv : config) {
const std::string key = kv.first.as<std::string>();
auto option_it = options_->find(key);
if (option_it != options_->end()) {
option_it->second->Set(kv.second);
} else {
std::cerr << "Invalid option " << key << std::endl;
}
}
}

} // google
Expand Down
16 changes: 11 additions & 5 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#ifndef AGENT_CONFIG_H_
#define AGENT_CONFIG_H_

#include <memory>
#include <mutex>
#include <string>

Expand All @@ -29,8 +30,13 @@ class Configuration {
Configuration(std::istream& input);
// Used to accept inline construction of streams.
Configuration(std::istream&& input) : Configuration(input) {}
~Configuration();

// Shared configuration.
bool VerboseLogging() const {
std::lock_guard<std::mutex> lock(mutex_);
return verbose_logging_;
}
const std::string& ProjectId() const {
std::lock_guard<std::mutex> lock(mutex_);
return project_id_;
Expand All @@ -39,10 +45,6 @@ class Configuration {
std::lock_guard<std::mutex> lock(mutex_);
return credentials_file_;
}
bool VerboseLogging() const {
std::lock_guard<std::mutex> lock(mutex_);
return verbose_logging_;
}
// Metadata API server configuration options.
int MetadataApiNumThreads() const {
std::lock_guard<std::mutex> lock(mutex_);
Expand Down Expand Up @@ -179,6 +181,8 @@ class Configuration {
friend class ConfigurationArgumentParserTest;
friend int ::main(int, char**); // Calls ParseArguments.

class OptionMap; // Internal helper class.

void ParseConfigFile(const std::string& filename);
void ParseConfiguration(std::istream& input);
// Parse the command line.
Expand All @@ -189,9 +193,9 @@ class Configuration {
int ParseArguments(int ac, char** av);

mutable std::mutex mutex_;
bool verbose_logging_;
std::string project_id_;
std::string credentials_file_;
bool verbose_logging_;
int metadata_api_num_threads_;
int metadata_api_port_;
std::string metadata_api_bind_address_;
Expand Down Expand Up @@ -223,6 +227,8 @@ class Configuration {
std::string instance_zone_;
std::string health_check_file_;
int health_check_max_data_age_seconds_;

std::unique_ptr<const OptionMap> options_;
};

}
Expand Down