Skip to content

Instantly share code, notes, and snippets.

@tomislacker
Last active September 12, 2019 14:41
Show Gist options
  • Save tomislacker/a5e623e854108938edcdda4c29c4a13a to your computer and use it in GitHub Desktop.
Save tomislacker/a5e623e854108938edcdda4c29c4a13a to your computer and use it in GitHub Desktop.
CloudFormation - Search & Replace Custom Resource
---
AWSTemplateFormatVersion: 2010-09-09
Description: Testing something
Resources:
R1:
Type: Custom::StringReplacement
Properties:
ServiceToken: !ImportValue cfn-helpers:Replace
Find: '-test'
Replace: '-prod'
Subject: example-stack-name-test
R2:
Type: Custom::StringReplacement
Properties:
ServiceToken: !ImportValue cfn-helpers:Replace
Find: '-[^-]+$'
Limit: 1
Regex: True
Replace: '-prod'
Subject: example-stack-name-test
Outputs:
R1:
# Results in 'example-stack-name-prod'
Value: !GetAtt R1.Result
R2:
# Results in 'example-stack-name-prod'
Value: !GetAtt R2.Result
# vim: ft=yaml.cloudformation sw=2 ts=2
---
AWSTemplateFormatVersion: 2010-09-09
Description: |
Provides a Lambda-backed Custom Resource for doing string replacement.
Resource Parameters:
Find (required, string): String or regular expression to find
Insensitive (optional, boolean): Switch to indicate case sensitivity.
Defaults to False & requires Regex=True
Limit (optional, integer): Maximum number of matches to replace
Regex (optional, boolean): If the `Find` parameter is a regular
expression. Defaults to False
Replace (required, string): Replacement string
Subject (required, string): String to do replacement in
Return Parameters:
Result (string): Result of the string replacement
Resources:
ReplaceFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${ReplaceFunction}
RetentionInDays: 1
ReplaceFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal: {Service: lambda.amazonaws.com}
Action: sts:AssumeRole
Path: /cfn-custom-resources/
Policies:
- PolicyName: logs
PolicyDocument:
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*"
ReplaceFunction:
Type: AWS::Lambda::Function
Properties:
Description: Executes string replacement
Handler: index.lambda_handler
MemorySize: 128
Role: !GetAtt ReplaceFunctionRole.Arn
Runtime: python3.6
Timeout: 5
Code:
ZipFile: |
import cfnresponse
def lambda_handler(event, context):
# Define the signal & data that will be returned
return_status = cfnresponse.FAILED
return_data = {}
try:
# Fetch the invocation settings
props = event['ResourceProperties']
find = props['Find']
insensitive = props.get('Insensitive', '').lower() == 'true'
limit = int(props.get('Limit', 0))
regex = props.get('Regex', '').lower() == 'true'
replace = props['Replace']
subject = props['Subject']
# Sanity check
if insensitive and not regex:
raise NotImplementedError(
'Cannot do case-insensitive replacement without'
'setting Regex=True')
if regex:
# Regular expression replacement
import re
kwargs = {}
if limit:
kwargs.update({'count': limit})
if insensitive:
kwargs.update({'flags': re.I})
result = re.sub(find, replace, subject, **kwargs)
else:
# Simple string replacement
result = subject.replace(find, replace)
# Setup return data & signal
return_data.update({
'Result': result,
})
return_status = cfnresponse.SUCCESS
except Exception as e:
# Some error
import traceback
traceback.print_exc()
return_data.update({
'Exception': str(e),
})
# Send the CFN response
cfnresponse.send(
event,
context,
return_status,
return_data)
Outputs:
ReplaceFunctionArn:
Description: ARN of the replacement Lambda function
Value: !GetAtt ReplaceFunction.Arn
Export:
Name: cfn-helpers:Replace
# vim: ft=yaml.cloudformation sw=2 ts=2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment