donkeyx
donkeyx

Reputation: 616

AWS:elastic_ip Assign a name to an elastic ip using cloudformation

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

Answers (2)

Udara Jayawardana
Udara Jayawardana

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

ab77
ab77

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

Related Questions