diff --git a/README.rst b/README.rst index 5b6d6e957..e93e07a92 100644 --- a/README.rst +++ b/README.rst @@ -255,6 +255,23 @@ Duplicating a single instance sample would look like this print(template.to_json()) +UserData +======== +You can pass in user data script to your launch config using ``from_file`` helper function under helpers/userdata.py file. +You can also use ``Ref`` method in the script file which will be translated into CloudFormation function. + +Example: + +.. code:: bash + + #!/bin/bash -ex + + /opt/aws/bin/cfn-init -v --stack "Ref('AWS::StackName')" \ + --resource LaunchConfig \ + --configsets ConfigCluster \ + --region Ref('AWS::Region') + + Community ========= diff --git a/tests/test_userdata.py b/tests/test_userdata.py index 7ce9c8402..23b4c61ca 100644 --- a/tests/test_userdata.py +++ b/tests/test_userdata.py @@ -56,6 +56,20 @@ def test_char_escaping(self): def test_nonexistant_file(self): self.assertRaises(IOError, self.create_result, 'nonexistant.sh') + def test_if_ref_is_replaced(self): + result = self.create_result('ref_func.sh') + + answer = self.create_answer([ + '/opt/aws/bin/cfn-init -v --stack "', + {'Ref': 'AWS::StackName'}, + '" \\\n', + ' --resource LaunchConfig \\\n', + ' --configsets ConfigCluster \\\n', + ' --region ', + {'Ref': 'AWS::Region'}, + '\n']) + self.assertEqual(result, answer) + if __name__ == '__main__': unittest.main() diff --git a/tests/userdata_test_scripts/ref_func.sh b/tests/userdata_test_scripts/ref_func.sh new file mode 100644 index 000000000..92f8ff644 --- /dev/null +++ b/tests/userdata_test_scripts/ref_func.sh @@ -0,0 +1,4 @@ +/opt/aws/bin/cfn-init -v --stack "Ref('AWS::StackName')" \ + --resource LaunchConfig \ + --configsets ConfigCluster \ + --region Ref('AWS::Region') diff --git a/troposphere/helpers/userdata.py b/troposphere/helpers/userdata.py index 5d25d1366..ab49a3e99 100644 --- a/troposphere/helpers/userdata.py +++ b/troposphere/helpers/userdata.py @@ -1,11 +1,14 @@ #!/usr/bin/python -from troposphere import Base64, Join +import re +from troposphere import Base64, Join, Ref -def from_file(filepath, delimiter='', blanklines=False): + +def from_file(filepath, delimiter='', blanklines=False, searchref=True): """ Imports userdata from a file. + Also supports passing Troposphere Ref function :type filepath: string :param filepath @@ -31,6 +34,22 @@ def from_file(filepath, delimiter='', blanklines=False): if blanklines and line.strip('\n\r ') == '': continue + if searchref: + pattern = r"""(?P.*) + Ref\(\'(?P[a-zA-Z0-9\:]+)\'\) + (?P.*[^\\*])""" + ref_pattern = re.compile(pattern, re.VERBOSE) + + ref_ex = ref_pattern.match(line) + + if ref_ex: + data.append(ref_ex.group('prefix')) + data.append(Ref(ref_ex.group('reference'))) + + if ref_ex.group('suffix'): + data.append(ref_ex.group('suffix')) + continue + data.append(line) except IOError: raise IOError('Error opening or reading file: {}'.format(filepath))