Reputation: 616
I am trying to use cloudformation and assign a "name" to an elastic ip using the normal process i.e:
IPAddress:
Description: 'ip:${AWS::Region}:${AWS::StackName} - elastic up for something'
Type: 'AWS::EC2::EIP'
Properties:
Tags:
- Key: Name
Value: !Sub 'ec2:${AWS::Region}:${AWS::StackName}'
For some reason cloudformation throws an error: "tags not supported", so I guess I am asking, is there a way to set the "Name" of the elastic ip with cloud-formation?
Cheers
Upvotes: 6
Views: 3088
Reputation: 1148
Reason for your error is in CloudFormation, elastic IP resources "AWS::EC2::EIP" not supporting Tags for Properties.
For the second question, as far as I know, there's no way, at the moment to name an elastic IP from cloud formation.
Update (11/22/2019) Tags are now supported. Refer the Docs here.
Upvotes: 8
Reputation: 871
Don't hold your breath, here is a thread on AWS forums, started in 2012 on this subject.
Instead use CloudFormation Custom Resources to varnish over this and other CFN shortcomings.
Following is my implementation using Python and boto3.
Python source code for
tag-ec2-resource.py
import cfnresponse
import boto3
import os
def lambda_handler(event, context):
print(event, context)
ec2 = boto3.client('ec2', region_name=os.environ['AWS_REGION'])
ResourceId = event['ResourceProperties']['ResourceId']
TagKey = event['ResourceProperties']['TagKey']
TagValue = event['ResourceProperties']['TagValue']
responseData = {}
if event['RequestType'] == 'Delete':
try:
response = ec2.delete_tags(
Resources=[
ResourceId,
],
Tags=[
{
'Key': TagKey,
'Value': TagValue
}
]
)
print(response)
except Exception as e:
print(e)
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, physicalResourceId=ResourceId)
return
if event['RequestType'] == 'Update':
try:
OldResourceId = event['OldResourceProperties']['ResourceId']
OldTagKey = event['OldResourceProperties']['TagKey']
OldTagValue = event['OldResourceProperties']['TagValue']
response = ec2.delete_tags(
Resources=[
OldResourceId,
],
Tags=[
{
'Key': OldTagKey,
'Value': OldTagValue
}
]
)
print(response)
except Exception as e:
print(e)
try:
response = ec2.create_tags(
Resources=[
ResourceId,
],
Tags=[
{
'Key': TagKey,
'Value': TagValue
},
]
)
print(response)
except:
pass
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, physicalResourceId=ResourceId)
(you'll need to package cfn-response with this function)
define Lambda role
TagEC2ResourceLambdaRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- 'lambda.amazonaws.com'
Action:
- 'sts:AssumeRole'
Path: '/'
Policies:
- PolicyName: 'AmazonLambdaServicePolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
- 'ec2:Describe*'
- 'ec2:CreateTags'
- 'ec2:DeleteTags'
Resource: '*'
define Lambda function
TagEC2ResourceLambda:
Type: 'AWS::Lambda::Function'
Properties:
FunctionName: !Join [ '-', [ 'tag-ec2-resource', !Select [ 2, !Split [ '/', !Ref 'AWS::StackId' ]]]]
Handler: 'tag-ec2-resource.lambda_handler'
Code:
S3Bucket: !Ref 'S3Bucket'
S3Key: !Sub 'lambda-functions/tag-ec2-resource-${LambdaVersion}.zip'
Runtime: python2.7
Role: !Ref 'TagEC2ResourceLambdaRoleArn'
Description: 'Tag EC2 resource.'
Timeout: 30
Tags:
- Key: Name
Value: !Ref 'NameTag'
Lastly, tag EIP using custom resource in your template
MyEipTag:
Type: 'Custom::TagEC2Resource'
Properties:
ServiceToken: !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:tag-ec2-resource-${LambdaStackGuid}'
ResourceId: !GetAtt MyEiP.AllocationId
TagKey: 'Name'
TagValue: 'my-very-special-EIP'
Hope this helps.
Upvotes: 5