Beispiel #1
0
    def check_for_leftover_reference_keys(key, value):
        if key.startswith('|'):
            raise TemplateErrorException(
                "Unhandled reference key found: {0}".format(key))
        if key.startswith('@') and key.endswith('@'):
            raise TemplateErrorException(
                "Unhandled reference key found: {0}".format(key))

        return key, value
Beispiel #2
0
    def check_for_leftover_reference_values(value):
        if isinstance(value, list):
            for item in value:
                if item.startswith('|'):
                    raise TemplateErrorException(
                        "Unhandled reference value found: {0}".format(value))
        elif isinstance(value, string_types):
            if value.startswith('|'):
                raise TemplateErrorException(
                    "Unhandled reference value found: {0}".format(value))

        return value
 def _s3_get_file(url):
     s3 = S3()
     try:
         if url.lower().endswith(".json"):
             return json.loads(s3.get_contents_from_url(url))
         if url.lower().endswith(".yml") or url.lower().endswith(".yaml"):
             return yaml.load(s3.get_contents_from_url(url))
         raise TemplateErrorException(
             "{0} has an unknown file type. Please provide an url with [.json|.yml|.yaml] extension"
         )
     except Exception as e:
         raise TemplateErrorException(
             "Could not load file from {0}: {1}".format(url, e))
Beispiel #4
0
    def check_for_leftover_reference_values(value):
        pattern = re.compile("^\|[a-zA-Z]+\|[a-zA-Z]+")
        if isinstance(value, string_types) and pattern.search(value):
            raise TemplateErrorException(
                "Unhandled reference value found: {0}".format(value))

        return value
Beispiel #5
0
    def transform_include_key(cls, key, value):
        if not value:
            return key, value

        if isinstance(key, string_types):
            if key.lower().strip() == '|include|':
                if not isinstance(value, string_types):
                    raise TemplateErrorException(
                        "Value of '|include|' must be of type string")
                if not value.lower().startswith("s3://"):
                    raise TemplateErrorException(
                        "Value of '|include|' must start with s3://")

                return "Fn::Transform", {
                    "Name": "AWS::Include",
                    "Location": value
                }

        return key, value
Beispiel #6
0
 def get_cloudformation_template(cls, url, working_dir):
     """
     Load file content from url and return cfn-sphere CloudFormationTemplate
     :param url: str
     :param working_dir: str
     :return: CloudFormationTemplate
     """
     try:
         template_body_dict = cls.get_yaml_or_json_file(url, working_dir)
         return CloudFormationTemplate(body_dict=template_body_dict, name=os.path.basename(url))
     except Exception as e:
         raise TemplateErrorException("Could not load file from {0}: {1}".format(url, e))
Beispiel #7
0
    def _transform_dict(cls, dict_value, indentation_level=0, prefix=""):
        lines = []

        for key, value in sorted(dict_value.items()):
            # key indentation with two spaces
            if indentation_level > 0:
                indented_key = "  " * indentation_level + prefix + str(key)
            else:
                indented_key = prefix + str(key)

            if isinstance(key, string_types):
                # do not go any further and directly return cfn functions and their values
                if key.lower() == "ref" or key.lower().startswith("fn::"):
                    indented_hyphen = '  ' * indentation_level + prefix
                    # aws functions results will always be a string
                    result = {key: value}
                    line = cls.transform_kv_to_cfn_join(indented_hyphen,
                                                        result,
                                                        delimiter="")
                    lines.append(line)
                else:
                    # recursion for dict or list values
                    if isinstance(value, dict):
                        result = cls._transform_dict(value,
                                                     indentation_level + 1)
                        if isinstance(result, dict):
                            lines.append(
                                cls.transform_kv_to_cfn_join(
                                    indented_key, result))
                        elif isinstance(result, list):
                            lines.append(indented_key + ":")
                            lines.extend(result)
                        else:
                            raise TemplateErrorException(
                                "Failed to convert dict to list of lines")

                    elif isinstance(value, list):
                        lines.append(indented_key + ":")
                        lines.extend(
                            cls._transform_list(value, indentation_level + 1))
                    elif isinstance(value, int):
                        lines.append(indented_key + ": " + str(value))
                    elif isinstance(value, float):
                        lines.append(indented_key + ": " + str(value))
                    else:
                        lines.append(indented_key + ": '" + str(value) + "'")
            else:
                lines.append(cls.transform_kv_to_cfn_join(indented_key, value))

        return lines
Beispiel #8
0
    def transform_reference_string(value):
        if not value:
            return value

        if isinstance(value, string_types):
            if value.lower().startswith('|ref|'):
                referenced_value = value[5:]

                if not referenced_value:
                    raise TemplateErrorException(
                        "Reference must be like |ref|resource")

                return {'Ref': referenced_value}

        return value
Beispiel #9
0
    def transform_join_key(cls, key, value):
        if not value:
            return key, value

        if isinstance(key, string_types):
            if key.lower().startswith('|join|'):
                if not isinstance(value, list):
                    raise TemplateErrorException(
                        "Value of '|join|' must be of type list")

                join_string = key[6:]

                return 'Fn::Join', [join_string, value]

        return key, value
Beispiel #10
0
    def transform_yaml_user_data_key(cls, key, value):
        if not value:
            return key, value

        if isinstance(key, string_types):

            if str(key).lower() == '@yamluserdata@':

                if not isinstance(value, dict):
                    raise TemplateErrorException(
                        "Value of 'YamlUserData' must be of type dict")

                lines = cls.transform_dict_to_yaml_lines_list(value)

                return "UserData", {'Fn::Base64': {'Fn::Join': ['\n', lines]}}

        return key, value
Beispiel #11
0
    def transform_dict_to_yaml_lines_list(cls,
                                          userdata_dict,
                                          indentation_level=0):
        lines = []

        for key, value in userdata_dict.items():

            # key indentation with two spaces
            if indentation_level > 0:
                indented_key = '  ' * indentation_level + str(key)
            else:
                indented_key = key

            if isinstance(key, string_types):

                # do not go any further and directly return cfn functions and their values
                if key.lower() in ['ref', 'fn::getatt', 'fn::join']:
                    return {key: value}
                else:

                    # recursion for dict values
                    if isinstance(value, dict):
                        result = cls.transform_dict_to_yaml_lines_list(
                            value, indentation_level + 1)
                        if isinstance(result, dict):
                            lines.append(
                                cls.transform_kv_to_cfn_join(
                                    indented_key, result))
                        elif isinstance(result, list):
                            lines.append(indented_key + ':')
                            lines.extend(result)
                        else:
                            raise TemplateErrorException(
                                "Failed to convert dict to list of lines")
                    elif isinstance(value, list):
                        lines.extend([indented_key + ':'] +
                                     ['- {0}'.format(item) for item in value])

                    else:
                        lines.append(
                            cls.transform_kv_to_cfn_join(indented_key, value))
            else:
                lines.append(cls.transform_kv_to_cfn_join(indented_key, value))

        return lines
Beispiel #12
0
    def transform_taupage_user_data_key(cls, key, value):
        if not value:
            return key, value

        if isinstance(key, string_types):

            if str(key).lower() == '@taupageuserdata@':

                if not isinstance(value, dict):
                    raise TemplateErrorException(
                        "Value of 'TaupageUserData' must be of type dict")

                lines = ['#taupage-ami-config']
                lines.extend(cls.transform_dict_to_yaml_lines_list(value))

                return "UserData", {'Fn::Base64': {'Fn::Join': ['\n', lines]}}

        return key, value
Beispiel #13
0
    def transform_getattr_string(value):
        if not value:
            return value

        if isinstance(value, string_types):
            if value.lower().startswith('|getatt|'):
                elements = value.split('|', 3)

                if len(elements) != 4:
                    raise TemplateErrorException(
                        "Attribute reference must be like '|getatt|resource|attribute'"
                    )

                resource = elements[2]
                attribute = elements[3]

                return {'Fn::GetAtt': [resource, attribute]}

        return value
    def _fs_get_file(url, working_dir):
        """
        Load cfn template from filesystem

        :param url: str template path
        :return: dict repr of cfn template
        """
        if not os.path.isabs(url) and working_dir:
            url = os.path.join(working_dir, url)

        try:
            with open(url, 'r') as template_file:
                if url.lower().endswith(".json"):
                    return json.loads(template_file.read())
                if url.lower().endswith(".yml") or url.lower().endswith(
                        ".yaml"):
                    return yaml.load(template_file.read())
        except Exception as e:
            raise TemplateErrorException(
                "Could not load file from {0}: {1}".format(url, e))
Beispiel #15
0
    def check_for_leftover_reference_keys(cls, key, value):
        if cls.is_reference_key(key):
            raise TemplateErrorException(
                "Unhandled reference key found: {0}".format(key))

        return key, value