1 Answer
- Newest
- Most votes
- Most comments
0
Custom Resource (or Macro) is the only way to go. Not only does AWS::EC2::Subnet
not support it as a return value as you mentioned, but you're also trying to reference an existing resource not created by your template.
Quick sample but do note - DescribeRouteTables
will only work if the subnet has been explicitly associated and not for a default route table. That will require extra coding/logic.
AWSTemplateFormatVersion: "2010-09-09"
Description: Subnet Custom Resource
Parameters:
TheSubnet:
Description: Subnet ID
Type: AWS::EC2::Subnet::Id
Default: subnet-32432943294
Resources:
CustomFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.lambda_handler
Timeout: 30
Role: !GetAtt 'CustomResourceRole.Arn'
Runtime: python3.7
Code:
ZipFile: |
import boto3
import json
import urllib
def sendResponse(event, context, responseData, responseStatus="FAILED"):
response_body = json.dumps({
"Status": responseStatus,
"Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
"PhysicalResourceId": context.log_stream_name,
"StackId": event["StackId"],
"RequestId": event["RequestId"],
"LogicalResourceId": event["LogicalResourceId"],
"Data":responseData
})
# Not using the old .put (deprecated)
enc_body = response_body.encode('utf-8')
opener = urllib.request.build_opener(urllib.request.HTTPHandler)
request = urllib.request.Request(event['ResponseURL'], data=enc_body)
request.add_header('Content-Type', '')
request.add_header('Content-Length', len(response_body))
request.get_method = lambda: 'PUT'
response = opener.open(request)
print("RESPONSE {}: {}".format(response.getcode(), response.msg))
def lambda_handler(event, context):
# Delete...
if event['RequestType'] == 'Delete':
sendResponse(event, context, {"Message": "DELETE"}, "SUCCESS")
return '{}'
try:
ec2 = boto3.client('ec2')
subnet = event["ResourceProperties"].get("SubnetId")
resp = ec2.describe_route_tables(
Filters=
[
{
'Name': 'association.subnet-id',
'Values': [subnet]
}
]
)
print(resp['RouteTables'][0])
sendResponse(event, context, resp['RouteTables'][0], "SUCCESS")
except:
print("ERROR")
sendResponse(event, context, {"Value": "ERROR"})
CustomResourceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Condition: {}
Path: /
Policies:
- PolicyName: QuerySubnet
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- Effect: Allow
Action:
- ec2:DescribeSubnets
- ec2:DescribeRouteTables
Resource: '*'
SubnetQuery:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt CustomFunction.Arn
SubnetId: !Ref TheSubnet
Outputs:
RouteTableId:
Description: Discovered Route Table ID
Value: !GetAtt SubnetQuery.RouteTableId
Relevant content
- asked 8 months ago
- asked 8 months ago
- asked 4 months ago
- Accepted Answerasked 7 months ago
- AWS OFFICIALUpdated a month ago
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated a year ago