diff --git a/source/common/common/logger.h b/source/common/common/logger.h index 019a714ef2d83..0e5d454c3ca8c 100644 --- a/source/common/common/logger.h +++ b/source/common/common/logger.h @@ -20,8 +20,10 @@ namespace Envoy { namespace Logger { // clang-format off +// TODO: find out a way for extensions to register new logger IDs #define ALL_LOGGER_IDS(FUNCTION) \ FUNCTION(admin) \ + FUNCTION(aws) \ FUNCTION(assert) \ FUNCTION(backtrace) \ FUNCTION(client) \ diff --git a/source/extensions/filters/http/common/aws/BUILD b/source/extensions/filters/http/common/aws/BUILD index e21ff2645279a..0a0c543fb426c 100644 --- a/source/extensions/filters/http/common/aws/BUILD +++ b/source/extensions/filters/http/common/aws/BUILD @@ -49,3 +49,19 @@ envoy_cc_library( "//source/common/http:headers_lib", ], ) + +envoy_cc_library( + name = "region_provider_interface", + hdrs = ["region_provider.h"], + external_deps = ["abseil_optional"], +) + +envoy_cc_library( + name = "region_provider_impl_lib", + srcs = ["region_provider_impl.cc"], + hdrs = ["region_provider_impl.h"], + deps = [ + ":region_provider_interface", + "//source/common/common:logger_lib", + ], +) diff --git a/source/extensions/filters/http/common/aws/region_provider.h b/source/extensions/filters/http/common/aws/region_provider.h new file mode 100644 index 0000000000000..58e2ad64da74d --- /dev/null +++ b/source/extensions/filters/http/common/aws/region_provider.h @@ -0,0 +1,33 @@ +#pragma once + +#include "envoy/common/pure.h" + +#include "absl/types/optional.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace Common { +namespace Aws { + +/** + * Interface for classes capable of discovering the AWS region from the execution environment. + */ +class RegionProvider { +public: + virtual ~RegionProvider() = default; + + /** + * Discover and return the AWS region. + * @return AWS region, or nullopt if unable to discover the region. + */ + virtual absl::optional getRegion() PURE; +}; + +typedef std::shared_ptr RegionProviderSharedPtr; + +} // namespace Aws +} // namespace Common +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/common/aws/region_provider_impl.cc b/source/extensions/filters/http/common/aws/region_provider_impl.cc new file mode 100644 index 0000000000000..f535eaef3ec3c --- /dev/null +++ b/source/extensions/filters/http/common/aws/region_provider_impl.cc @@ -0,0 +1,30 @@ +#include "extensions/filters/http/common/aws/region_provider_impl.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace Common { +namespace Aws { + +static const char AWS_REGION[] = "AWS_REGION"; + +StaticRegionProvider::StaticRegionProvider(const std::string& region) : region_(region) {} + +absl::optional StaticRegionProvider::getRegion() { + return absl::optional(region_); +} + +absl::optional EnvironmentRegionProvider::getRegion() { + const auto region = std::getenv(AWS_REGION); + if (region == nullptr) { + return absl::nullopt; + } + ENVOY_LOG(debug, "Found environment region {}={}", AWS_REGION, region); + return absl::optional(region); +} + +} // namespace Aws +} // namespace Common +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/common/aws/region_provider_impl.h b/source/extensions/filters/http/common/aws/region_provider_impl.h new file mode 100644 index 0000000000000..114d1e294fb80 --- /dev/null +++ b/source/extensions/filters/http/common/aws/region_provider_impl.h @@ -0,0 +1,38 @@ +#pragma once + +#include "common/common/logger.h" + +#include "extensions/filters/http/common/aws/region_provider.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace Common { +namespace Aws { + +/** + * Retrieve AWS region name from the environment + */ +class EnvironmentRegionProvider : public RegionProvider, public Logger::Loggable { +public: + absl::optional getRegion() override; +}; + +/** + * Return statically configured AWS region name + */ +class StaticRegionProvider : public RegionProvider { +public: + StaticRegionProvider(const std::string& region); + + absl::optional getRegion() override; + +private: + const std::string region_; +}; + +} // namespace Aws +} // namespace Common +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/http/common/aws/BUILD b/test/extensions/filters/http/common/aws/BUILD index 1c5c0541e4ebf..67bc0a150c6e5 100644 --- a/test/extensions/filters/http/common/aws/BUILD +++ b/test/extensions/filters/http/common/aws/BUILD @@ -40,3 +40,12 @@ envoy_cc_test( "//test/test_common:utility_lib", ], ) + +envoy_cc_test( + name = "region_provider_impl_test", + srcs = ["region_provider_impl_test.cc"], + deps = [ + "//source/extensions/filters/http/common/aws:region_provider_impl_lib", + "//test/test_common:environment_lib", + ], +) diff --git a/test/extensions/filters/http/common/aws/region_provider_impl_test.cc b/test/extensions/filters/http/common/aws/region_provider_impl_test.cc new file mode 100644 index 0000000000000..42ce4d907bef7 --- /dev/null +++ b/test/extensions/filters/http/common/aws/region_provider_impl_test.cc @@ -0,0 +1,42 @@ +#include "extensions/filters/http/common/aws/region_provider_impl.h" + +#include "test/test_common/environment.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace Common { +namespace Aws { + +class EnvironmentRegionProviderTest : public testing::Test { +public: + virtual ~EnvironmentRegionProviderTest() { TestEnvironment::unsetEnvVar("AWS_REGION"); } + + EnvironmentRegionProvider provider_; +}; + +class StaticRegionProviderTest : public testing::Test { +public: + StaticRegionProviderTest() : provider_("test-region") {} + + StaticRegionProvider provider_; +}; + +TEST_F(EnvironmentRegionProviderTest, SomeRegion) { + TestEnvironment::setEnvVar("AWS_REGION", "test-region", 1); + EXPECT_EQ("test-region", provider_.getRegion().value()); +} + +TEST_F(EnvironmentRegionProviderTest, NoRegion) { EXPECT_FALSE(provider_.getRegion().has_value()); } + +TEST_F(StaticRegionProviderTest, SomeRegion) { + EXPECT_EQ("test-region", provider_.getRegion().value()); +} + +} // namespace Aws +} // namespace Common +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/test_common/environment.cc b/test/test_common/environment.cc index da848c98eb2bb..ea6c11d6f0eaa 100644 --- a/test/test_common/environment.cc +++ b/test/test_common/environment.cc @@ -315,7 +315,7 @@ void TestEnvironment::setEnvVar(const std::string& name, const std::string& valu if (!overwrite) { size_t requiredSize; const int rc = ::getenv_s(&requiredSize, nullptr, 0, name.c_str()); - ASSERT_EQ(rc, 0); + ASSERT_EQ(0, rc); if (requiredSize != 0) { return; } @@ -324,7 +324,17 @@ void TestEnvironment::setEnvVar(const std::string& name, const std::string& valu ASSERT_EQ(0, rc); #else const int rc = ::setenv(name.c_str(), value.c_str(), overwrite); - ASSERT_EQ(rc, 0); + ASSERT_EQ(0, rc); +#endif +} + +void TestEnvironment::unsetEnvVar(const std::string& name) { +#ifdef WIN32 + const int rc = ::_putenv_s(name.c_str(), ""); + ASSERT_EQ(0, rc); +#else + const int rc = ::unsetenv(name.c_str()); + ASSERT_EQ(0, rc); #endif } diff --git a/test/test_common/environment.h b/test/test_common/environment.h index 43fae4c923bba..45c188fb87a26 100644 --- a/test/test_common/environment.h +++ b/test/test_common/environment.h @@ -203,6 +203,11 @@ class TestEnvironment { * Set environment variable. Same args as setenv(2). */ static void setEnvVar(const std::string& name, const std::string& value, int overwrite); + + /** + * Removes environment variable. Same args as unsetenv(3). + */ + static void unsetEnvVar(const std::string& name); }; } // namespace Envoy