Skip to content

Commit

Permalink
Add custome resource to add vpc to hosted zone.
Browse files Browse the repository at this point in the history
This is required for now because of a CDK bug:
aws/aws-cdk#20496

The PR for the above bug is:
aws/aws-cdk#20530

Fix use of existing hosted zone.
  • Loading branch information
cartalla committed Jun 22, 2022
1 parent 28fa8cc commit 6fb3f00
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 39 deletions.
60 changes: 37 additions & 23 deletions source/cdk/cdk_slurm_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,9 @@ def check_config(self):
logger.warning(f"ErrorSnsTopicArn not set. Provide error-sns-topic-arn on the command line or ErrorSnsTopicArn in the config file to get error notifications.")
self.config['ErrorSnsTopicArn'] = ''

if 'Domain' not in self.config and 'HostedZoneId' not in self.config:
if 'Domain' not in self.config:
self.config['Domain'] = f"{self.stack_name}.local"
if 'Domain' in self.config and 'HostedZoneId' in self.config:
logger.error(f"Cannot specify both Domain({self.config['Domain']}) and HostedZoneId{self.config['HostedZoneId']}")
sys.exist(1)
logger.info(f"Domain defaulted to {self.config['Domain']}")

if 'ClusterName' not in self.config['slurm']:
self.config['slurm']['ClusterName'] = self.stack_name
Expand Down Expand Up @@ -492,25 +490,30 @@ def create_vpc(self):
logger.info(f"Subnet set to {self.config['SubnetId']}")
logger.info(f"availability zone: {self.subnet.availability_zone}")

remote_vpcs = {}
for region_dict in self.config['slurm']['InstanceConfig']['Regions']:
if region_dict['Region'] == self.config['Region']:
continue
remote_vpcs[region_dict['Region']] = ec2.Vpc.from_lookup(
self, f"Vpc{region_dict['Region']}",
region = region_dict['Region'],
vpc_id = region_dict['VpcId'])

# Can't create query logging for private hosted zone.
if 'HostedZoneId' in self.config:
self.hosted_zone = route53.HostedZone.from_hosted_zone_id(self, "PrivateDns", hosted_zone_id=self.config['HostedZoneId'])
self.config['Domain'] = self.hosted_zone.zone_name
self.hosted_zone = route53.HostedZone.from_hosted_zone_attributes(
self, "PrivateDns",
hosted_zone_id = self.config['HostedZoneId'],
zone_name = self.config['Domain']
)
else:
self.hosted_zone = route53.HostedZone(self, "PrivateDns",
vpcs = [self.vpc],
zone_name = self.config['Domain']
)
remote_vpcs = {}
for region_dict in self.config['slurm']['InstanceConfig']['Regions']:
if region_dict['Region'] == self.config['Region']:
continue
remote_vpcs[region_dict['Region']] = ec2.Vpc.from_lookup(
self, f"Vpc{region_dict['Region']}",
region = region_dict['Region'],
vpc_id = region_dict['VpcId'])
# BUG: CDK isn't creating the correct region for the vpcs even though cdk_context.json has it right.
#self.hosted_zone.add_vpc(remote_vpcs[region_dict['Region']])
# BUG: CDK isn't creating the correct region for the vpcs even though cdk_context.json has it right.
# for remote_region, remote_vpc in remote_vpcs.items():
# self.hosted_zone.add_vpc(remote_vpc)

def create_lambdas(self):
dnsLookupLambdaAsset = s3_assets.Asset(self, "DnsLookupLambdaAsset", path="resources/lambdas/DnsLookup")
Expand Down Expand Up @@ -558,19 +561,30 @@ def create_lambdas(self):
)
)

createRoute53ZoneLambdaAsset = s3_assets.Asset(self, "CreateRoute53ZoneLambdaAsset", path="resources/lambdas/CreateRoute53Zone")
self.create_route53_zone_lambda = aws_lambda.Function(
self, "CreateRoute53ZoneLambda",
function_name=f"{self.stack_name}-CreateRoute53Zone",
description="Create Route53 zone in other region",
routeRoute53ZoneAddVpcLambdaAsset = s3_assets.Asset(self, "Route53HostedZoneAddVpcLambdaAsset", path="resources/lambdas/Route53HostedZoneAddVpc")
self.route53_hosted_zone_add_vpc_lambda = aws_lambda.Function(
self, "Route53HostedZoneAddVpcLambda",
function_name=f"{self.stack_name}-Route53HostedZoneAddVpc",
description="Associated VPC with Route53 hosted zone",
memory_size=128,
runtime=aws_lambda.Runtime.PYTHON_3_7,
timeout=Duration.minutes(3),
log_retention=logs.RetentionDays.INFINITE,
handler="CreateRoute53Zone.lambda_handler",
code=aws_lambda.Code.from_bucket(createRoute53ZoneLambdaAsset.bucket, createRoute53ZoneLambdaAsset.s3_object_key)
handler="Route53HostedZoneAddVpc.lambda_handler",
code=aws_lambda.Code.from_bucket(routeRoute53ZoneAddVpcLambdaAsset.bucket, routeRoute53ZoneAddVpcLambdaAsset.s3_object_key)
)

self.route53_hosted_zone_add_vpc_lambda.add_to_role_policy(
statement=iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
"route53:AssociateVpcWithHostedZone",
"route53:DissociateVpcFromHostedZone",
],
resources=['*']
)
)

getOntapSvmDNSNameLambdaAsset = s3_assets.Asset(self, "GetOntapSvmDNSNameLambdaAsset", path="resources/lambdas/GetOntapSvmDNSName")
self.get_ontap_svm_dnsname_lambda = aws_lambda.Function(
self, "GetOntapSvmDNSNameLambda",
Expand Down
7 changes: 3 additions & 4 deletions source/cdk/config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,14 @@
# Domain:
# Domain name for the Route 53 private hosted zone that will be used
# by the slurm cluster for DNS.
# Alternately, provide HostedZoneId of an existing Route53 hosted zone to use and
# the zone name of the HostedZoneId.
# By default will be {StackName}.local
# Alternately, provide HostedZoneId of an existing Route53 hosted zone to use.
# Cannot specify both Domain and HostedZoneId.
Optional('Domain'): str,
#
# HostedZoneId:
# ID of an existing hosted zone that will be used by the slurm cluster for DNS.
# Alternately, provide Domain name to use for a new Route53 hosted zone to use.
# Cannot specify both Domain and HostedZoneId.
# You must provide the Domain name of the HostedZone if it is different than the default.
Optional('HostedZoneId'): str,
Optional('TimeZone', default='US/Central'): str,
'slurm': {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@
'''
Create/delete route53 zone in another region.
'''
import cfnresponse

import boto3
import cfnresponse
import logging

logging.getLogger().setLevel(logging.INFO)

def lambda_handler(event, context):
try:
logging.info(f"event:\n{json.dumps(event, indent=4)}")
properties = event['ResourceProperties']
required_properties = ['Region', 'VpcId', 'Domain']
required_properties = ['HostedZoneId', 'VpcId', 'VpcRegion']
error_message = ""
for property in required_properties:
try:
Expand All @@ -38,19 +40,36 @@ def lambda_handler(event, context):
if error_message:
raise KeyError(error_message)

route53_client = boto3.client('route53', region_name=properties['Region'])
hosted_zone_id = route53_client.create_hosted_zone(
Name = properties['Domain'],
VPC = {
'VPCRegion': properties['Region'],
'VPCId': properties['VpcId'],
},
HostedZoneConfig = {'PrivateZone': True}
)['HostedZone']['Id']
requestType = event['RequestType']

route53_client = boto3.client('route53')

if requestType in ['Update', 'Delete']:
try:
route53_client.disassociate_vpc_from_hosted_zone(
HostedZoneId = properties['HostedZoneId'],
VPC = {
'VPCRegion': properties['VpcRegion'],
'VPCId': properties['VpcId'],
},
HostedZoneConfig = {'PrivateZone': True}
)
except:
pass

if requestType in ['Create', 'Update']:
route53_client.associate_vpc_with_hosted_zone(
HostedZoneId = properties['HostedZoneId'],
VPC = {
'VPCRegion': properties['VpcRegion'],
'VPCId': properties['VpcId'],
},
HostedZoneConfig = {'PrivateZone': True}
)

except Exception as e:
logging.exception(str(e))
cfnresponse.send(event, context, cfnresponse.FAILED, {'error': str(e)}, str(e))
raise

cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, "{} {}.{} {}".format(properties['Type'], properties['Hostname'], properties['Domain'], properties['Value']))
cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, "")

0 comments on commit 6fb3f00

Please sign in to comment.