Skip to content
This repository was archived by the owner on Aug 19, 2019. It is now read-only.
Merged
5 changes: 5 additions & 0 deletions src/configuration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ MetadataAgentConfiguration::MetadataAgentConfiguration()
instance_zone_(kDefaultInstanceZone),
health_check_file_(kDefaultHealthCheckFile) {}

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

int MetadataAgentConfiguration::ParseArguments(int ac, char** av) {
std::string config_file;
boost::program_options::options_description flags_desc;
Expand Down
21 changes: 13 additions & 8 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@
#include <mutex>
#include <string>

int main(int, char**);

namespace google {

class MetadataAgentConfiguration {
public:
MetadataAgentConfiguration();
// Parse the command line.
// A zero return value means that parsing succeeded and the program should
// proceed. A positive return value means that parsing failed. A negative
// value means that parsing succeeded, but all of the arguments were handled
// within the function and the program should exit with a success exit code.
int ParseArguments(int ac, char** av);
MetadataAgentConfiguration(std::istream& input);
// Used to accept inline construction of streams.
MetadataAgentConfiguration(std::istream&& input)
: MetadataAgentConfiguration(input) {}

// Shared configuration.
const std::string& ProjectId() const {
Expand Down Expand Up @@ -157,11 +157,16 @@ class MetadataAgentConfiguration {
}

private:
friend class MetadataAgentConfigurationTest;
friend class HealthCheckerUnittest;
friend int ::main(int, char**); // Calls ParseArguments.

void ParseConfigFile(const std::string& filename);
void ParseConfiguration(std::istream& input);
// Parse the command line.
// A zero return value means that parsing succeeded and the program should
// proceed. A positive return value means that parsing failed. A negative
// value means that parsing succeeded, but all of the arguments were handled
// within the function and the program should exit with a success exit code.
int ParseArguments(int ac, char** av);

mutable std::mutex mutex_;
std::string project_id_;
Expand Down
103 changes: 46 additions & 57 deletions test/configuration_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,80 @@

namespace google {

class MetadataAgentConfigurationTest : public ::testing::Test {
protected:
void ParseConfiguration(const std::string& input) {
std::stringstream stream(input);
config.ParseConfiguration(stream);
}

void VerifyDefaultConfig() const {
EXPECT_EQ("", config.ProjectId());
EXPECT_EQ("", config.CredentialsFile());
EXPECT_EQ(3, config.MetadataApiNumThreads());
EXPECT_EQ(8000, config.MetadataApiPort());
EXPECT_EQ(".", config.MetadataApiResourceTypeSeparator());
EXPECT_EQ(60, config.MetadataReporterIntervalSeconds());
EXPECT_EQ(false, config.MetadataReporterPurgeDeleted());
EXPECT_THAT(config.MetadataReporterUserAgent(),
::testing::StartsWith("metadata-agent/"));
EXPECT_EQ("https://stackdriver.googleapis.com/"
"v1beta2/projects/{{project_id}}/resourceMetadata:batchUpdate",
config.MetadataIngestionEndpointFormat());
EXPECT_EQ(8*1024*1024, config.MetadataIngestionRequestSizeLimitBytes());
EXPECT_EQ("0.1", config.MetadataIngestionRawContentVersion());
EXPECT_EQ(60*60, config.InstanceUpdaterIntervalSeconds());
EXPECT_EQ("", config.InstanceResourceType());
EXPECT_EQ(60, config.DockerUpdaterIntervalSeconds());
EXPECT_EQ("unix://%2Fvar%2Frun%2Fdocker.sock/",
config.DockerEndpointHost());
EXPECT_EQ("1.23", config.DockerApiVersion());
EXPECT_EQ("limit=30", config.DockerContainerFilter());
EXPECT_EQ(0, config.KubernetesUpdaterIntervalSeconds());
EXPECT_EQ("https://kubernetes.default.svc",
config.KubernetesEndpointHost());
EXPECT_EQ("", config.KubernetesPodLabelSelector());
EXPECT_EQ("", config.KubernetesClusterName());
EXPECT_EQ("", config.KubernetesClusterLocation());
EXPECT_EQ("", config.KubernetesNodeName());
EXPECT_EQ(true, config.KubernetesUseWatch());
EXPECT_EQ("", config.InstanceId());
EXPECT_EQ("", config.InstanceZone());
EXPECT_EQ("/var/run/metadata-agent/health/unhealthy", config.HealthCheckFile());
}
void VerifyDefaultConfig(const MetadataAgentConfiguration& config) {
EXPECT_EQ("", config.ProjectId());
EXPECT_EQ("", config.CredentialsFile());
EXPECT_EQ(3, config.MetadataApiNumThreads());
EXPECT_EQ(8000, config.MetadataApiPort());
EXPECT_EQ(".", config.MetadataApiResourceTypeSeparator());
EXPECT_EQ(60, config.MetadataReporterIntervalSeconds());
EXPECT_EQ(false, config.MetadataReporterPurgeDeleted());
EXPECT_THAT(config.MetadataReporterUserAgent(),
::testing::StartsWith("metadata-agent/"));
EXPECT_EQ("https://stackdriver.googleapis.com/"
"v1beta2/projects/{{project_id}}/resourceMetadata:batchUpdate",
config.MetadataIngestionEndpointFormat());
EXPECT_EQ(8*1024*1024, config.MetadataIngestionRequestSizeLimitBytes());
EXPECT_EQ("0.1", config.MetadataIngestionRawContentVersion());
EXPECT_EQ(60*60, config.InstanceUpdaterIntervalSeconds());
EXPECT_EQ("", config.InstanceResourceType());
EXPECT_EQ(60, config.DockerUpdaterIntervalSeconds());
EXPECT_EQ("unix://%2Fvar%2Frun%2Fdocker.sock/", config.DockerEndpointHost());
EXPECT_EQ("1.23", config.DockerApiVersion());
EXPECT_EQ("limit=30", config.DockerContainerFilter());
EXPECT_EQ(0, config.KubernetesUpdaterIntervalSeconds());
EXPECT_EQ("https://kubernetes.default.svc", config.KubernetesEndpointHost());
EXPECT_EQ("", config.KubernetesPodLabelSelector());
EXPECT_EQ("", config.KubernetesClusterName());
EXPECT_EQ("", config.KubernetesClusterLocation());
EXPECT_EQ("", config.KubernetesNodeName());
EXPECT_EQ(true, config.KubernetesUseWatch());
EXPECT_EQ("", config.InstanceId());
EXPECT_EQ("", config.InstanceZone());
EXPECT_EQ("/var/run/metadata-agent/health/unhealthy", config.HealthCheckFile());
}

TEST(MetadataAgentConfigurationTest, NoConfig) {
MetadataAgentConfiguration config;
};

TEST_F(MetadataAgentConfigurationTest, NoConfig) {
VerifyDefaultConfig();
VerifyDefaultConfig(config);
}

TEST_F(MetadataAgentConfigurationTest, EmptyConfig) {
ParseConfiguration("");
VerifyDefaultConfig();
TEST(MetadataAgentConfigurationTest, EmptyConfig) {
MetadataAgentConfiguration config(std::istringstream(""));
VerifyDefaultConfig(config);
}

TEST_F(MetadataAgentConfigurationTest, PopulatedConfig) {
ParseConfiguration(
TEST(MetadataAgentConfigurationTest, PopulatedConfig) {
MetadataAgentConfiguration config(std::istringstream(
"ProjectId: TestProjectId\n"
"MetadataApiNumThreads: 13\n"
"MetadataReporterPurgeDeleted: true\n"
"MetadataReporterUserAgent: \"foobar/foobaz\"\n"
"HealthCheckFile: /a/b/c\n"
);
));
EXPECT_EQ("TestProjectId", config.ProjectId());
EXPECT_EQ(13, config.MetadataApiNumThreads());
EXPECT_EQ(true, config.MetadataReporterPurgeDeleted());
EXPECT_EQ("foobar/foobaz", config.MetadataReporterUserAgent());
EXPECT_EQ("/a/b/c", config.HealthCheckFile());
}

TEST_F(MetadataAgentConfigurationTest, CommentSkipped) {
ParseConfiguration(
TEST(MetadataAgentConfigurationTest, CommentSkipped) {
MetadataAgentConfiguration config(std::istringstream(
"ProjectId: TestProjectId\n"
"#MetadataApiNumThreads: 13\n"
"MetadataReporterPurgeDeleted: true\n"
);
));
EXPECT_EQ(3, config.MetadataApiNumThreads());
}

TEST_F(MetadataAgentConfigurationTest, BlankLine) {
ParseConfiguration(
TEST(MetadataAgentConfigurationTest, BlankLine) {
MetadataAgentConfiguration config(std::istringstream(
"ProjectId: TestProjectId\n"
"\n"
"\n"
"MetadataReporterPurgeDeleted: true\n"
);
));
EXPECT_EQ("TestProjectId", config.ProjectId());
EXPECT_EQ(true, config.MetadataReporterPurgeDeleted());
}
Expand Down
31 changes: 14 additions & 17 deletions test/health_checker_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,32 @@ class HealthCheckerUnittest : public ::testing::Test {
return health_checker.IsHealthy();
}

void SetIsolationPath(const std::string& isolation_path) {
isolation_path_ = isolation_path;
std::stringstream stream(
"HealthCheckFile: './" + isolation_path_ + "/unhealthy'");
config_.ParseConfiguration(stream);
}

std::string isolation_path_;
MetadataAgentConfiguration config_;
};

namespace {
std::istringstream IsolationPathConfig(const std::string& test_name) {
return std::istringstream("HealthCheckFile: './" + test_name + "/unhealthy'");
}
} // namespace

TEST_F(HealthCheckerUnittest, DefaultHealthy) {
SetIsolationPath(test_info_->name());
HealthChecker health_checker(config_);
MetadataAgentConfiguration config(IsolationPathConfig(test_info_->name()));
HealthChecker health_checker(config);
EXPECT_TRUE(IsHealthy(health_checker));
Cleanup(&health_checker);
}

TEST_F(HealthCheckerUnittest, SimpleFailure) {
SetIsolationPath(test_info_->name());
HealthChecker health_checker(config_);
MetadataAgentConfiguration config(IsolationPathConfig(test_info_->name()));
HealthChecker health_checker(config);
SetUnhealthy(&health_checker, "kubernetes_pod_thread");
EXPECT_FALSE(IsHealthy(health_checker));
Cleanup(&health_checker);
}

TEST_F(HealthCheckerUnittest, MultiFailure) {
SetIsolationPath(test_info_->name());
HealthChecker health_checker(config_);
MetadataAgentConfiguration config(IsolationPathConfig(test_info_->name()));
HealthChecker health_checker(config);
EXPECT_TRUE(IsHealthy(health_checker));
SetUnhealthy(&health_checker, "kubernetes_pod_thread");
EXPECT_FALSE(IsHealthy(health_checker));
Expand All @@ -60,8 +57,8 @@ TEST_F(HealthCheckerUnittest, MultiFailure) {
}

TEST_F(HealthCheckerUnittest, FailurePersists) {
SetIsolationPath(test_info_->name());
HealthChecker health_checker(config_);
MetadataAgentConfiguration config(IsolationPathConfig(test_info_->name()));
HealthChecker health_checker(config);
EXPECT_TRUE(IsHealthy(health_checker));
SetUnhealthy(&health_checker, "kubernetes_pod_thread");
EXPECT_FALSE(IsHealthy(health_checker));
Expand Down