Skip to content

Commit 309e18a

Browse files
Sergey RyabininSergeyRyabinin
authored andcommitted
Generate dualstack endpoints for EC2 service
1 parent 8465e8f commit 309e18a

File tree

4 files changed

+164
-14
lines changed

4 files changed

+164
-14
lines changed

aws-cpp-sdk-ec2-integration-tests/EC2TestsDualStack.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,8 @@ TEST_F(EC2DualStackTests, TestDualStackMocked)
4444

4545
Aws::Client::ClientConfiguration clientConfig;
4646
clientConfig.region = "us-east-1";
47-
// Although SDK does not properly compute dualstack endpoints, let's keep this flag for future's backward compatibility
4847
clientConfig.useDualStack = true;
49-
// TODO: remove next with proper endpoint generation support
50-
// Use dualstack endpoint posted by EC2
51-
clientConfig.endpointOverride = "api.ec2.us-east-1.aws";
48+
5249
Aws::Auth::AWSCredentials mockCreds("accessKey", "secretKey", "sessionToken");
5350
Aws::EC2::EC2Client ec2Client(mockCreds, clientConfig);
5451

@@ -73,11 +70,7 @@ TEST_F(EC2DualStackTests, TestDualStackEndpoint)
7370
{
7471
Aws::Client::ClientConfiguration clientConfig;
7572
clientConfig.region = "us-east-1";
76-
// Although SDK does not properly compute dualstack endpoints, let's keep this flag for future's backward compatibility
7773
clientConfig.useDualStack = true;
78-
// TODO: remove next with proper endpoint generation support
79-
// Use dualstack endpoint posted by EC2
80-
clientConfig.endpointOverride = "api.ec2.us-east-1.aws";
8174

8275
Aws::EC2::EC2Client ec2Client(clientConfig);
8376

aws-cpp-sdk-ec2/source/EC2Endpoint.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55

66
#include <aws/ec2/EC2Endpoint.h>
7+
#include <aws/core/Region.h>
8+
#include <aws/core/utils/logging/LogMacros.h>
9+
#include <aws/core/utils/memory/stl/AWSSet.h>
710
#include <aws/core/utils/memory/stl/AWSStringStream.h>
811
#include <aws/core/utils/HashingUtils.h>
912

@@ -21,6 +24,11 @@ namespace EC2Endpoint
2124
static const int US_ISO_EAST_1_HASH = Aws::Utils::HashingUtils::HashString("us-iso-east-1");
2225
static const int US_ISOB_EAST_1_HASH = Aws::Utils::HashingUtils::HashString("us-isob-east-1");
2326

27+
// https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Using_Endpoints.html#ipv6
28+
static const Aws::UnorderedSet<Aws::String> EC2_DUALSTACK_REGIONS {
29+
Aws::Region::US_EAST_1, Aws::Region::US_EAST_2, Aws::Region::US_WEST_2, Aws::Region::US_WEST_1,
30+
Aws::Region::AP_SOUTH_1, Aws::Region::SA_EAST_1};
31+
static const char* EC2_ENDPOINT_TAG = "EC2Endpoint";
2432

2533
Aws::String ForRegion(const Aws::String& regionName, bool useDualStack)
2634
{
@@ -29,14 +37,16 @@ namespace EC2Endpoint
2937
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
3038

3139
Aws::StringStream ss;
32-
ss << "ec2" << ".";
33-
3440
if(useDualStack)
3541
{
36-
ss << "dualstack.";
42+
if ((EC2_DUALSTACK_REGIONS.find(regionName)) == EC2_DUALSTACK_REGIONS.end())
43+
{
44+
AWS_LOGSTREAM_WARN(EC2_ENDPOINT_TAG,
45+
"EC2 service does not support dualstack endpoint in the region: " << regionName);
46+
}
47+
ss << "api.";
3748
}
38-
39-
ss << region;
49+
ss << "ec2." << region;
4050

4151
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
4252
{
@@ -52,7 +62,14 @@ namespace EC2Endpoint
5262
}
5363
else
5464
{
55-
ss << ".amazonaws.com";
65+
if(useDualStack)
66+
{
67+
ss << ".aws";
68+
}
69+
else
70+
{
71+
ss << ".amazonaws.com";
72+
}
5673
}
5774

5875
return ss.str();

code-generation/generator/src/main/java/com/amazonaws/util/awsclientgenerator/generators/cpp/ec2/Ec2CppClientGenerator.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.*;
1010
import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.Error;
1111
import com.amazonaws.util.awsclientgenerator.generators.cpp.QueryCppClientGenerator;
12+
import org.apache.velocity.Template;
13+
import org.apache.velocity.VelocityContext;
1214

15+
import java.nio.charset.StandardCharsets;
1316
import java.util.Collection;
1417
import java.util.LinkedList;
1518
import java.util.List;
@@ -742,4 +745,19 @@ public SdkFileEntry[] generateSourceFiles(ServiceModel serviceModel) throws Exce
742745
return super.generateSourceFiles(serviceModel);
743746
}
744747

748+
@Override
749+
protected SdkFileEntry generateRegionSourceFile(ServiceModel serviceModel) throws Exception {
750+
751+
// Customized template for EC2 endpoints
752+
// TODO: cleanup with a proper dualstack endpoints support
753+
Template template = velocityEngine.getTemplate(
754+
"/com/amazonaws/util/awsclientgenerator/velocity/cpp/ec2/EC2EndpointEnumSource.vm",
755+
StandardCharsets.UTF_8.name());
756+
757+
VelocityContext context = createContext(serviceModel);
758+
context.put("endpointMapping", computeEndpointMappingForService(serviceModel));
759+
760+
String fileName = String.format("source/%sEndpoint.cpp", serviceModel.getMetadata().getClassNamePrefix());
761+
return makeFile(template, context, fileName, true);
762+
}
745763
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#parse("com/amazonaws/util/awsclientgenerator/velocity/cfamily/Attribution.vm")
2+
3+
#set($metadata = $serviceModel.metadata)
4+
#set($rootNamespace = $serviceModel.namespace)
5+
#set($serviceNamespace = $metadata.namespace)
6+
#set($endpointPrefix = $metadata.endpointPrefix)
7+
\#include <aws/${metadata.projectName}/${metadata.classNamePrefix}Endpoint.h>
8+
\#include <aws/core/Region.h>
9+
\#include <aws/core/utils/logging/LogMacros.h>
10+
\#include <aws/core/utils/memory/stl/AWSSet.h>
11+
\#include <aws/core/utils/memory/stl/AWSStringStream.h>
12+
\#include <aws/core/utils/HashingUtils.h>
13+
14+
using namespace Aws;
15+
using namespace ${rootNamespace}::${serviceNamespace};
16+
17+
namespace ${rootNamespace}
18+
{
19+
namespace ${serviceNamespace}
20+
{
21+
namespace ${metadata.classNamePrefix}Endpoint
22+
{
23+
#if(!$metadata.globalEndpoint)
24+
static const int CN_NORTH_1_HASH = Aws::Utils::HashingUtils::HashString("cn-north-1");
25+
static const int CN_NORTHWEST_1_HASH = Aws::Utils::HashingUtils::HashString("cn-northwest-1");
26+
static const int US_ISO_EAST_1_HASH = Aws::Utils::HashingUtils::HashString("us-iso-east-1");
27+
static const int US_ISOB_EAST_1_HASH = Aws::Utils::HashingUtils::HashString("us-isob-east-1");
28+
#end
29+
30+
#foreach($regionEndpointPair in $endpointMapping.entrySet())
31+
#set($customizedRegion = $regionEndpointPair.key)
32+
#if ($metadata.globalEndpoint || !($customizedRegion.equals("cn-north-1") || $customizedRegion.equals("cn-northwest-1") || $customizedRegion.equals("us-iso-east-1") || $customizedRegion.equals("us-isob-east-1")))
33+
static const int ${regionEndpointPair.key.toUpperCase().replace("-", "_")}_HASH = Aws::Utils::HashingUtils::HashString("${regionEndpointPair.key}");
34+
#end
35+
#end
36+
// https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Using_Endpoints.html#ipv6
37+
static const Aws::UnorderedSet<Aws::String> ${serviceModel.serviceName.toUpperCase()}_DUALSTACK_REGIONS {
38+
Aws::Region::US_EAST_1, Aws::Region::US_EAST_2, Aws::Region::US_WEST_2, Aws::Region::US_WEST_1,
39+
Aws::Region::AP_SOUTH_1, Aws::Region::SA_EAST_1};
40+
static const char* ${serviceModel.serviceName.toUpperCase()}_ENDPOINT_TAG = "${serviceModel.serviceName.toUpperCase()}Endpoint";
41+
42+
Aws::String ForRegion(const Aws::String& regionName, bool useDualStack)
43+
{
44+
#if($metadata.globalEndpoint)
45+
#if($endpointMapping.isEmpty())
46+
AWS_UNREFERENCED_PARAM(regionName);
47+
AWS_UNREFERENCED_PARAM(useDualStack);
48+
return "${metadata.globalEndpoint}";
49+
#else
50+
auto hash = Aws::Utils::HashingUtils::HashString(regionName.c_str());
51+
52+
if(!useDualStack)
53+
{
54+
#foreach($regionEndpointPair in $endpointMapping.entrySet())
55+
if(hash == ${regionEndpointPair.key.toUpperCase().replace("-", "_")}_HASH)
56+
{
57+
return "${regionEndpointPair.value}";
58+
}
59+
#end
60+
}
61+
return "${metadata.globalEndpoint}";
62+
#end##end if endpoint mapping
63+
#else##no global endpoint means standard endpoints calculation except for special regions
64+
// Fallback to us-east-1 if global endpoint does not exists.
65+
Aws::String region = regionName == Aws::Region::AWS_GLOBAL ? Aws::Region::US_EAST_1 : regionName;
66+
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
67+
68+
#if(!$endpointMapping.isEmpty())
69+
if(!useDualStack)
70+
{
71+
#foreach($regionEndpointPair in $endpointMapping.entrySet())
72+
if(hash == ${regionEndpointPair.key.toUpperCase().replace("-", "_")}_HASH)
73+
{
74+
return "${regionEndpointPair.value}";
75+
}
76+
#end
77+
}
78+
#end
79+
Aws::StringStream ss;
80+
if(useDualStack)
81+
{
82+
if ((${serviceModel.serviceName.toUpperCase()}_DUALSTACK_REGIONS.find(regionName)) == ${serviceModel.serviceName.toUpperCase()}_DUALSTACK_REGIONS.end())
83+
{
84+
AWS_LOGSTREAM_WARN(${serviceModel.serviceName.toUpperCase()}_ENDPOINT_TAG,
85+
"${serviceModel.serviceName.toUpperCase()} service does not support dualstack endpoint in the region: " << regionName);
86+
}
87+
ss << "api.";
88+
}
89+
ss << "${endpointPrefix}." << region;
90+
91+
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
92+
{
93+
ss << ".amazonaws.com.cn";
94+
}
95+
else if (hash == US_ISO_EAST_1_HASH)
96+
{
97+
ss << ".c2s.ic.gov";
98+
}
99+
else if (hash == US_ISOB_EAST_1_HASH)
100+
{
101+
ss << ".sc2s.sgov.gov";
102+
}
103+
else
104+
{
105+
if(useDualStack)
106+
{
107+
ss << ".aws";
108+
}
109+
else
110+
{
111+
ss << ".amazonaws.com";
112+
}
113+
}
114+
115+
return ss.str();
116+
#end
117+
}
118+
119+
} // namespace ${metadata.classNamePrefix}Endpoint
120+
} // namespace ${serviceNamespace}
121+
} // namespace ${rootNamespace}
122+

0 commit comments

Comments
 (0)