def main()

in _compile_cloudformation_template.py [0:0]


def main():
    in_dir, out_dir, static_asset_s3_prefix = sys.argv[1:4]
    static_asset_s3_prefix = static_asset_s3_prefix.strip('/')

    # Unfortunately we've had to split our template into multiple configs with the API config at the top so that
    # we could get past the 50kb limit of CloudFormation
    with TemplateCompiler(
            in_dir, out_dir,
            'cognito.yml', 'lambda.yml', 'api_gateway.yml', 'api_gateway_lambda_roles.yml') as configs:
        cognito_config, lambda_config, api_config, api_lambda_roles_config = configs
        paths = {}
        for func in base.route.registry.values():
            lambda_name = snake_case_to_capitalized_words(func.__name__) + 'Lambda'
            # Strip the parameter and return documentation out of the Lambda description as this confuses Lambda
            lambda_description = ''
            if func.__doc__:
                for line in func.__doc__.splitlines():
                    line = line.strip()
                    if (':param' or ':return') in line:
                        break
                    if line:
                        lambda_description += f'{line} '
            # Generate Lambda Resources
            lambda_config['Resources'][lambda_name] = {
                'Type': 'AWS::Lambda::Function',
                'Properties': {
                    'Code': './build',
                    'Description': lambda_description,
                    'Environment': {
                        'Variables': {
                            'APP_CLIENT_ID': Ref('CognitoUserPoolClient'),
                            'USER_POOL_ID': Ref('CognitoUserPool'),
                            'PARTICIPANT_TABLE': Ref('participantDynamoDBTable'),
                            'WHEEL_TABLE': Ref('wheelDynamoDBTable'),
                        }
                    },
                    'Handler': f"{func.__module__}.{func.__name__}",
                    'MemorySize': 128,
                    'Role': GetAtt('AWSOpsWheelLambdaRole.Arn'),
                    'Runtime': 'python3.9',
                    'Timeout': 3
                }
            }

            path = f'/api/{func.route.path.lstrip("/")}'
            paths.setdefault(path, {})
            for method in func.route.methods:
                paths[path][method.lower()] = make_api_path_config(lambda_name, func.route.path)
                stripped_path = path.lstrip('/')
                api_lambda_roles_config['Resources'][f"{lambda_name}GatewayPermissions{method}"] = {
                    'Type': 'AWS::Lambda::Permission',
                    'Properties': {
                        'Action': 'lambda:invokeFunction',
                        'FunctionName': Ref(lambda_name),
                        'Principal': 'apigateway.amazonaws.com',
                        'SourceArn': {'Fn::Join': ['', [
                            'arn:aws:execute-api:',
                            Ref('AWS::Region'),
                            ':',
                            Ref('AWS::AccountId'),
                            ':',
                            Ref("AWSOpsWheelAPI"),
                            f"/*/{method.upper()}/{stripped_path}",
                        ]]},
                    }
                }

        paths['/favicon.ico'] = {'get': {
            'produces': [ 'image/x-icon' ],
            'responses': {
                '200': {
                    'description': '200 response',
                    'schema': {
                        '$ref': '#/definitions/Empty'
                    },
                    'headers': {
                        'Content-Length': {
                            'type': 'string'
                        },
                        'Content-Type': {
                            'type': 'string'
                        }
                    }
                }
            },
            'x-amazon-apigateway-integration': {
              'responses': {
                'default': {
                  'statusCode': '200',
                  'responseParameters': {
                    'method.response.header.Content-Type': 'integration.response.header.Content-Type',
                    'method.response.header.Content-Length': 'integration.response.header.Content-Length'
                  },
                  'contentHandling': 'CONVERT_TO_BINARY'
                }
              },
              'uri': f'{static_asset_s3_prefix}/favicon.ico',
              'passthroughBehavior': 'when_no_match',
              'httpMethod': 'GET',
              'contentHandling': 'CONVERT_TO_BINARY',
              'type': 'http'
            }
        }}

        paths['/static/{proxy+}'] = {'x-amazon-apigateway-any-method': {
            'parameters': [{'in': 'path', 'name': 'proxy', 'required': True, 'type': 'string'}],
            'produces': ['application/json'],
            'responses': {},
            'x-amazon-apigateway-integration': {
                'cacheKeyParameters': ['method.request.path.proxy'],
                'cacheNamespace': 'static_assets',
                'httpMethod': 'ANY',
                'passthroughBehavior': 'when_no_match',
                'requestParameters': {'integration.request.path.proxy': 'method.request.path.proxy'},
                'responses': {'default': {'statusCode': '200'}},
                'type': 'http_proxy',
                'uri': f'{static_asset_s3_prefix}/{{proxy}}',
                'contentHandling': 'CONVERT_TO_BINARY'}
        }}

        paths['/'] = {'x-amazon-apigateway-any-method': {
            'parameters': [],
            'produces': ['application/json'],
            'responses': {},
            'x-amazon-apigateway-integration': {
                'httpMethod': 'ANY',
                'passthroughBehavior': 'when_no_match',
                'requestParameters': {},
                'responses': {'default': {'statusCode': '200'}},
                'type': 'http_proxy',
                'uri': f'{static_asset_s3_prefix}/index.production.html'}
        }}

        paths['/{proxy+}'] = {'x-amazon-apigateway-any-method': {
            'parameters': [{'in': 'path', 'name': 'proxy', 'required': False, 'type': 'string'}],
            'produces': ['application/json'],
            'responses': {},
            'x-amazon-apigateway-integration': {
                'cacheKeyParameters': ['method.request.path.proxy'],
                'cacheNamespace': 'static_assets',
                'httpMethod': 'ANY',
                'passthroughBehavior': 'when_no_match',
                'requestParameters': {'integration.request.path.proxy': 'method.request.path.proxy'},
                'responses': {'default': {'statusCode': '200'}},
                'type': 'http_proxy',
                'uri': f'{static_asset_s3_prefix}/index.production.html'}
        }}

        api_config['Resources']['AWSOpsWheelAPI']['Properties']['Body'] = {
            'schemes': ['https'],
            'swagger': '2.0',
            'info': {'title': 'AWSOpsWheel', 'version': '0.1'},
            'definitions': {
                'Empty': {'title': 'Empty Schema', 'type': 'object'}
            },
            'x-amazon-apigateway-binary-media-types': ['audio/mpeg', 'audio/*', 'image/x-icon', 'application/font*', 'font/*'],
            'basePath': '/',
            'paths': paths,
            'securityDefinitions': {
                'apiUsers': {
                    'type': 'apiKey',
                    'name': 'Authorization',
                    'in': 'header',
                    'x-amazon-apigateway-authtype': 'cognito_user_pools',
                    'x-amazon-apigateway-authorizer': {
                        'type': 'COGNITO_USER_POOLS',
                        'providerARNs': [Ref('CognitoUserPoolArn')]
                    }
                }
            }
        }