def __init__(self, scope: core.Construct, construct_id: str, queue_context: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) q = dict(self.node.try_get_context(queue_context)) queue_dlq = _sqs.Queue(self, q["queue_dlq_name"], queue_name=q["queue_dlq_name"]) queue = _sqs.Queue( self, q["queue_name"], queue_name=q["queue_name"], dead_letter_queue=_sqs.DeadLetterQueue( max_receive_count=q["queue_dlq_max_receive_count"], queue=queue_dlq), encryption=_sqs.QueueEncryption.KMS_MANAGED, visibility_timeout=Duration.seconds(30), delivery_delay=Duration.seconds(15), retention_period=Duration.hours(14), ) self.queue = queue self.queue_dlq = queue_dlq # Outputs core.CfnOutput(self, "QueueUrl", value=queue.queue_url)
def __create_cloud_front_cache_policy(self) -> aws_cloudfront.CachePolicy: return aws_cloudfront.CachePolicy( self, 'CloudFrontCachePolicy', comment= 'The CloudFront cache policy used by the DefaultCacheBehavior', default_ttl=Duration.seconds(1), max_ttl=Duration.seconds(1), min_ttl=Duration.seconds(1))
def _get_health_check(self): return HealthCheck( healthy_http_codes="200", healthy_threshold_count=5, interval=Duration.seconds(30), path="/healthz", timeout=Duration.seconds(5), unhealthy_threshold_count=2, )
def get_alb_config(self, protocol: ElbProtocol = ElbProtocol.HTTP, port: int = None) -> ElbHealthCheck: """Get the health check configuration for the ALB Target Group. Parameters: port: Use a different port for the health check. By default ALB uses the traffic port protocol: Specify the protocol to use for the health check. By default, this is non-SSL HTTP. """ # An ALB load balancer uses it's health check to determine which tasks # in the ECS service should receive traffic. Additionally, it will # notify the ECS system to stop any tasks that it determines are # unhealthy. The ALB health check configuration is mostly # independent of the ECS health check configuration. # # The same health check configuration is used to determine when a # newly started task is ready to receive traffic, and also to # determine if an ongoing task has become broken. # # There is a problem with the whole-system configuration, in that # if the ALB stops a newly started task that it thinks is unhealthy, # then ECS doesn't realise that the service is unhealthy, and the # deployment will incorrectly succeed. # # The solution is to tweak the health check configurations so that # the ECS health check quickly detects and stops an unhealthy task # (either at startup or ongoing), and the ALB health check never # stops a task at startup. # # Therefore we create an ALB health check configuration that is quite # slow. This means that some genuine problems don't get automatically # resolved in a timely manner, but TBH the nature of this category of # problem (external to the container itself) is unusual. if self.timeout >= self.check_interval_alb: raise ValueError( "Healthcheck timeout is longer than the ALB repeat interval") if (self.min_time_to_unhealthy_alb + 30) < self.max_time_to_unhealthy_ecs: raise ValueError( "Healthcheck timing means that the ALB might stop an unhealthy " "ECS task before ECS does, which is undesirable.") return ElbHealthCheck( # Unhealthy ECS tasks always get stopped and never get to recover, # therefore there is no point setting this. # healthy_threshold_count=5, interval=Duration.seconds(self.check_interval_alb), path=self.endpoint_path, port=port, protocol=protocol, timeout=Duration.seconds(self.timeout), unhealthy_threshold_count=self.num_checks_alb, )
def create_cloudfront_distribution(self): return Distribution(self, "image-resize-distribution", default_behavior=BehaviorOptions( origin=S3Origin(bucket=self.image_bucket), cache_policy=CachePolicy( self, "image-resize-cache-policy", default_ttl=Duration.seconds(0), min_ttl=Duration.seconds(0), max_ttl=Duration.days(365))), default_root_object="index.html")
def __init__( self, scope: Construct, id: str, cluster: _Cluster, shared_airflow_env: dict, vpc: _Vpc, **kwargs, ) -> None: super().__init__(scope, id, **kwargs) task_definition = FargateTaskDefinition( self, "task-def", cpu=512, memory_limit_mib=1024 ) container = task_definition.add_container( "container", image=ContainerImage.from_registry("apache/airflow:1.10.12-python3.8"), command=["webserver"], logging=LogDriver.aws_logs(stream_prefix="webserver"), environment=shared_airflow_env, ) port_mapping = PortMapping(container_port=8080, host_port=8080) container.add_port_mappings(port_mapping) service = FargateService( self, "service", cluster=cluster, task_definition=task_definition, ) lb = ApplicationLoadBalancer(self, "lb", vpc=vpc, internet_facing=True) listener = lb.add_listener("public_listener", port=80, open=True) health_check = HealthCheck( interval=Duration.seconds(60), path="/health", timeout=Duration.seconds(5), ) listener.add_targets( "webserver", port=8080, targets=[service], health_check=health_check, ) CfnOutput(self, "LoadBalancerDNS", value=lb.load_balancer_dns_name)
def __init__( self, scope: Construct, construct_id: str, *, deploy_env: str, users_role: aws_iam.Role, package_name: str, botocore_lambda_layer: aws_lambda_python.PythonLayerVersion, ): super().__init__(scope, construct_id) self.lambda_function = aws_lambda.Function( self, f"{deploy_env}-{construct_id}-function", function_name=f"{deploy_env}-{construct_id}", handler=f"backend.{package_name}.entrypoint.lambda_handler", runtime=PYTHON_RUNTIME, timeout=Duration.seconds(60), code=bundled_code(package_name), layers=[botocore_lambda_layer], # type: ignore[list-item] ) self.lambda_function.add_environment("DEPLOY_ENV", deploy_env) self.lambda_function.grant_invoke(users_role) # type: ignore[arg-type]
def __init__(self, scope: Construct, construct_id: str, env: Environment) -> None: super().__init__(scope, construct_id, env=env) smol_table = SmolTable(self, "SmolTable", table_name=TABLE_NAME) smol_vpc = Vpc.from_lookup(self, "CoreVPC", vpc_name=VPC_NAME) smol_subnets = SubnetSelection( one_per_az=True, subnet_type=SubnetType.PRIVATE, ) smol_lambda = Function( self, "SmolAPI", code=Code.from_asset_image(directory=abspath("./")), environment={ "CAPTCHA_KEY": environ["CAPTCHA_KEY"], "SAFE_BROWSING_KEY": environ["SAFE_BROWSING_KEY"], }, function_name=FUNCTION_NAME, handler=Handler.FROM_IMAGE, log_retention=RetentionDays.ONE_WEEK, memory_size=MEMORY_ALLOCATION, reserved_concurrent_executions=RESERVED_CONCURRENCY, runtime=Runtime.FROM_IMAGE, timeout=Duration.seconds(TIMEOUT_SEC), tracing=Tracing.ACTIVE, vpc=smol_vpc, vpc_subnets=smol_subnets, ) smol_table.table.grant(smol_lambda, "dynamodb:DescribeTable") smol_table.table.grant(smol_lambda, "dynamodb:GetItem") smol_table.table.grant(smol_lambda, "dynamodb:PutItem") SmolTarget(self, "SmolTarget", smol_lambda, API_HOST)
def get_ecs_service_properties(self) -> dict: """Get health-check-related properties for an ECS Service.""" # This is the period of time that an unhealthy state is not acted # on - an unhealthy task won't be stopped inside this period. # Note that failed health check requests are still counted as # contributing to an unhealthy state. # # Also note that the same value is used by both ECS container # health checks and ALB health checks - see # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service_definition_parameters.html # This means that if ALB determines that the task is unhealthy # before this time finished, then ALB will stop the task instead # of ECS and our deployment model will break. # # Therefore we hard-code it to something small, in order to ensure # it has no impact. grace_period = 10 if self.min_time_to_unhealthy_alb < grace_period: raise ValueError( "The ECS grace period is too long, which means that ALB might " "mark a container as unhealthy at the same time as ECS.") return dict( health_check_grace_period=Duration.seconds(grace_period), # The default healthy percentages are reasonable. # # It's also possible that they are ignored for Fargate deployments - see # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service_definition_parameters.html # # Therefore we don't set these. # min_healthy_percent=50, # max_healthy_percent=200, )
async def create_canary_function(self, id: str) -> Function: function = None with open('canary/canary.py', 'r') as code: canary_code = code.read() function = Function( self, '{}CanaryFunction'.format(id), timeout=Duration.seconds(3), code=InlineCode(canary_code), handler='index.handler', tracing=Tracing.ACTIVE, initial_policy=[MINIMAL_FUNCTION_POLICY_STATEMENT], runtime=Runtime( name='python3.7', supports_inline_code=True, ) ) Rule(self, '{}CanaryRule'.format(id), enabled=True, schedule=Schedule.cron(), targets=[LambdaFunction(handler=function)]) return function
async def create_site_function(self, id: str, domain: str, cdn_name: str) -> Function: env = { 'PROD': 'True', 'SITE_DOMAIN': domain, 'APP_VERSION': '0.02', 'STATIC_DOMAIN': cdn_name, 'PROD': 'True' } site_code_asset = Asset( self, '{}FunctionAsset'.format(id), path='site_function') site_code = S3Code( bucket=site_code_asset.bucket, key=site_code_asset.s3_object_key) return Function( self, '{}Function'.format(id), timeout=Duration.seconds(3), code=site_code, handler='site_function.handler', environment=env, tracing=Tracing.ACTIVE, initial_policy=[DDB_FUNCTION_POLICY_STATEMENT], runtime=Runtime( name='python3.7', supports_inline_code=True, ) )
def __init__(self, scope: cdk.Construct, construct_id: str, lambda_context: str, **kwargs) -> None: super().__init__(scope, construct_id) fn = dict(self.node.try_get_context(lambda_context)) lambda_fn = Function( self, fn["fn_name"], function_name=fn["fn_name"], runtime=Runtime.PYTHON_3_8, handler=fn["fn_handler"], code=Code.from_asset(fn["fn_path"]), tracing=Tracing.ACTIVE, current_version_options={ "removal_policy": cdk.RemovalPolicy.RETAIN }, retry_attempts=fn["fn_retry_attempts"], timeout=Duration.seconds(fn["fn_timeout"]), reserved_concurrent_executions=fn["fn_reserved_concurrency"]) lambda_fn_alias = lambda_fn.current_version.add_alias(fn["fn_alias"]) # # Outputs cdk.CfnOutput(self, fn["fn_name"] + 'Arn', value=lambda_fn.function_arn) self._function = lambda_fn self._function_alias = lambda_fn_alias
def create_lambda(self, envs: EnvSettings): is_app_only = self.node.try_get_context("is_app_only") if is_app_only == "true": code = Code.from_asset( path="../backend/functions/image_resize/.serverless/main.zip") else: code = Code.from_cfn_parameters() function = Function( self, "image-resize-lambda", function_name=f"{envs.project_name}-image-resize", code=code, handler="index.handler", runtime=Runtime.NODEJS_12_X, memory_size=512, timeout=Duration.seconds(30), tracing=Tracing.ACTIVE, ) api_gateway = LambdaRestApi( self, "ImageResizeLambdaApi", rest_api_name=f"{envs.project_name}-image-resize", handler=function) return function, code, api_gateway
def _create_token_validation_lambda(self) -> aws_lambda.Function: return lambda_python.PythonFunction( scope=self, id="token_validation_lambda", function_name=f"orbit-{self.context.name}-token-validation", entry=_lambda_path("token_validation"), index="index.py", handler="handler", runtime=aws_lambda.Runtime.PYTHON_3_8, timeout=Duration.seconds(5), environment={ "COGNITO_USER_POOL_ID": self.user_pool.user_pool_id, "REGION": self.context.region, "COGNITO_USER_POOL_CLIENT_ID": self.user_pool_client.user_pool_client_id, }, initial_policy=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ "ec2:Describe*", "logs:Create*", "logs:PutLogEvents", "logs:Describe*" ], resources=["*"], ) ], )
def _create_eks_service_lambda(self) -> aws_lambda.Function: return lambda_python.PythonFunction( scope=self, id="eks_service_lambda", function_name=f"orbit-{self.context.name}-eks-service-handler", entry=_lambda_path("eks_service_handler"), index="index.py", handler="handler", runtime=aws_lambda.Runtime.PYTHON_3_8, timeout=Duration.seconds(5), environment={ "REGION": self.context.region, }, initial_policy=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["eks:List*", "eks:Describe*"], resources=[ f"arn:aws:eks:{self.context.region}:{self.context.account_id}:cluster/orbit-*", f"arn:aws:eks:{self.context.region}:{self.context.account_id}:nodegroup/orbit-*/*/*", ], ) ], )
def _create_queues(self): post_anime_dl = Queue(self, "post_anime_dl") self.post_anime_queue = Queue( self, "anime", dead_letter_queue=DeadLetterQueue(max_receive_count=5, queue=post_anime_dl), receive_message_wait_time=Duration.seconds(20) )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here queue = sqs.Queue( self, "MyFirstQueue", visibility_timeout=Duration.seconds(300), )
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # ECR Repository ecr_repo = ecr.Repository( self, "EcrRepository", repository_name="intro_lambda_container" ) # Lambda Functions lam.Function( self, "LambdaFunctionPythonBaseImage", function_name="intro-lambda-container-python-base-image", code=lam.Code.from_ecr_image( repository=ecr_repo, tag="python-base-image" ), handler=lam.Handler.FROM_IMAGE, runtime=lam.Runtime.FROM_IMAGE, timeout=Duration.seconds(60) ) lam.Function( self, "LambdaFunctionPythonCustomImage", function_name="intro-lambda-container-python-custom-image", code=lam.Code.from_ecr_image( repository=ecr_repo, tag="python-custom-image" ), handler=lam.Handler.FROM_IMAGE, runtime=lam.Runtime.FROM_IMAGE, timeout=Duration.seconds(60) ) lam.Function( self, "LambdaFunctionRustCustomImage", function_name="intro-lambda-container-rust-custom-image", code=lam.Code.from_ecr_image( repository=ecr_repo, tag="rust-custom-image" ), handler=lam.Handler.FROM_IMAGE, runtime=lam.Runtime.FROM_IMAGE, timeout=Duration.seconds(60) )
def _create_lambdas(self): clean_pycache() for root, dirs, files in os.walk(LAMBDAS_DIR): for f in files: if f != "__init__.py": continue parent_folder = os.path.basename(os.path.dirname(root)) lambda_folder = os.path.basename(root) name = f"{parent_folder}-{lambda_folder}" lambda_config = self.lambdas_config[name] layers = [] for layer_name in lambda_config["layers"]: layers.append(self.layers[layer_name]) lambda_role = Role( self, f"{name}_role", assumed_by=ServicePrincipal(service="lambda.amazonaws.com") ) for policy in lambda_config["policies"]: lambda_role.add_to_policy(policy) lambda_role.add_managed_policy( ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole")) lambda_args = { "code": Code.from_asset(root), "handler": "__init__.handle", "runtime": Runtime.PYTHON_3_8, "layers": layers, "function_name": name, "environment": lambda_config["variables"], "role": lambda_role, "timeout": Duration.seconds(lambda_config["timeout"]), "memory_size": lambda_config["memory"], } if "concurrent_executions" in lambda_config: lambda_args["reserved_concurrent_executions"] = lambda_config["concurrent_executions"] self.lambdas[name] = Function(self, name, **lambda_args) self.lambdas["sqs_handlers-post_anime"].add_event_source(SqsEventSource(self.post_anime_queue)) Rule( self, "titles_updater", schedule=Schedule.cron(hour="2", minute="10"), targets=[LambdaFunction(self.lambdas["crons-titles_updater"])] ) Rule( self, "episodes_updater", schedule=Schedule.cron(hour="4", minute="10"), targets=[LambdaFunction(self.lambdas["crons-episodes_updater"])] )
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) table_name = "posts2" function_name = "cl2" email = "*****@*****.**" table = Table( self, "cl_posts", table_name=table_name, partition_key=Attribute(name="url", type=AttributeType.STRING), time_to_live_attribute="ttl", ) function = PythonFunction( self, "cl_function", function_name=function_name, entry="src", index="app.py", runtime=Runtime.PYTHON_3_8, environment={ "cl_email": email, "cl_table_name": table_name }, timeout=Duration.seconds(300), initial_policy=[ PolicyStatement( actions=["ses:SendEmail", "ses:VerifyEmailIdentity"], resources=[ f"arn:aws:ses:{self.region}:{self.account}:identity/{email}" ], ), PolicyStatement( actions=[ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem" ], resources=[table.table_arn], ), ], ) with open("events/event.json") as f: event = json.load(f) Rule( self, "cl_schedule", schedule=Schedule.expression("cron(0 19 * * ? *)"), targets=[ LambdaFunction(function, event=RuleTargetInput.from_object(event)) ], )
def _create_job_processing_queue(self, project_name: str, lambda_size: int): return Queue( self, f"DataProcessingQueue-{lambda_size}", queue_name=f"{project_name}-data-processing-{lambda_size}", visibility_timeout=Duration.seconds(300), dead_letter_queue=DeadLetterQueue( queue=self.dead_letter_queue, max_receive_count=self.job_processing_max_retries), )
def get_ecs_config(self, command: str = None) -> EcsHealthCheck: """Get the health check configuration for the ECS container definition for a webserver container. Parameters: command: By default we configure the ECS health check to do a HTTP GET on the health check endpoint. This parameter specifies an alternate command. """ # ECS will replace any task that is part of a service, and # is deemed to be unhealthy (because any essential container in that # task is unhealthy). Therefore we need at least 1 container-level # healthcheck in the task definition. # If you don't specify a health check in the container definition in # the task definition, then ECS won't know about it (even if it is # baked into the image after being specified in the Dockerfile). # Therefore we always define a health check in the container definition # # See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_healthcheck if self.timeout >= self.check_interval_ecs: raise ValueError( "Healthcheck timeout is longer than the ECS repeat interval") if not command: # Use `wget` rather than `curl`, since it is present in more # vanilla OS images (eg. Alpine) command = f'wget -T {self.timeout} -O - "http://localhost:{self.container_port}{self.endpoint_path}"' return EcsHealthCheck( command=[command + " || exit 1"], interval=Duration.seconds(self.check_interval_ecs), # Docker calls it "retries", but it's actually total number of # attempts, not first attempt + N retries. # See https://docs.docker.com/engine/reference/builder/#healthcheck retries=self.num_checks_ecs, start_period=Duration.seconds(self.max_container_startup), # Make the Docker service's timeout be longer than the `wget` # timeout, so that we get output from `wget` timeout=Duration.seconds(self.timeout + 1), )
def _create_lambdas(self): for root, dirs, files in os.walk(LAMBDAS_DIR): for f in files: if f != "__init__.py": continue parent_folder = os.path.basename(os.path.dirname(root)) lambda_folder = os.path.basename(root) name = f"{parent_folder}-{lambda_folder}" lambda_config = self.lambdas_config[name] layers = [] for layer_name in lambda_config["layers"]: layers.append(self.layers[layer_name]) lambda_role = Role(self, f"{name}_role", assumed_by=ServicePrincipal( service="lambda.amazonaws.com")) for policy in lambda_config["policies"]: lambda_role.add_to_policy(policy) lambda_role.add_managed_policy( ManagedPolicy.from_aws_managed_policy_name( "service-role/AWSLambdaBasicExecutionRole")) self.lambdas[name] = Function( self, name, code=Code.from_asset(root), handler="__init__.handle", runtime=Runtime.PYTHON_3_8, layers=layers, function_name=name, environment=lambda_config["variables"], role=lambda_role, timeout=Duration.seconds(lambda_config["timeout"]), memory_size=lambda_config["memory"], ) Rule(self, "update_eps", schedule=Schedule.cron(hour="2", minute="10"), targets=[LambdaFunction(self.lambdas["cron-update_eps"])])
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here lambda_fn = _lambda.Function( self, 'facadeHandler', runtime=_lambda.Runtime.PYTHON_3_8, timeout=Duration.seconds(30), code=_lambda.Code.asset('facade/lambdas/facadeapi'), handler='app.on_request') # The code that defines your stack goes here utils = CPUtils() facade_api = utils.create_api_gateway(self, "facade-api", "Facade", lambda_fn, enable_proxy=True)
def __init__(self, scope: core.Construct, construct_id: str, lambda_context: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) fn = dict(self.node.try_get_context(lambda_context)) # lambda dlq lambda_fn_dlq = _sqs.Queue(self, fn["fn_dlq_name"], queue_name=fn["fn_dlq_name"]) lambda_fn = Function( self, fn["fn_name"], function_name=fn["fn_name"], runtime=Runtime.PYTHON_3_8, handler=fn["fn_handler"], code=Code.from_asset(fn["fn_path"]), tracing=Tracing.ACTIVE, current_version_options={ "removal_policy": core.RemovalPolicy.RETAIN }, environment={ "ENVIRONMENT_VALUE": "DUMMY_VALUE", }, dead_letter_queue=lambda_fn_dlq, retry_attempts=fn["fn_retry_attempts"], timeout=Duration.seconds(fn["fn_timeout"]), reserved_concurrent_executions=fn["fn_reserved_concurrency"]) lambda_fn_alias = lambda_fn.current_version.add_alias(fn["fn_alias"]) lambda_fn_dlq.grant_send_messages(lambda_fn) # # Outputs core.CfnOutput(self, fn["fn_name"] + 'Arn', value=(lambda_fn.function_arn)) self._function = lambda_fn self._function_alias = lambda_fn_alias self._function_dlq = lambda_fn_dlq
def create_lambda(self, lambda_id: str, path_to_code: str, handler_name: str, description: Union[str, None] = None, environment: Union[Dict, None] = None, function_name: Union[str, None] = None, memory_size: Union[float, int, None] = None, timeout: Union[int] = None) -> None: _lambda.Function(scope=self, id=lambda_id, runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.Code.asset(path_to_code), handler=handler_name, description=description, environment=environment, function_name=function_name, memory_size=memory_size, timeout=Duration.seconds(timeout))
def _create_lambda_fn(self, envs: EnvSettings, memory_size: int, queue: Queue): is_app_only = self.node.try_get_context("is_app_only") if is_app_only == "true": code = Code.from_asset( path="../backend/functions/worker/.serverless/main.zip") else: code = Code.from_cfn_parameters() function = Function( self, f"data-processing-worker-{memory_size}", function_name=f"{envs.project_name}-data-processing-{memory_size}", code=code, runtime=Runtime.PYTHON_3_8, handler="handler.main", environment={ "AWS_STORAGE_BUCKET_NAME": self.app_bucket.bucket_name, "IMAGE_SCRAPING_FETCH_TIMEOUT": "15", "AWS_IMAGE_STORAGE_BUCKET_NAME": self.resize_lambda_image_bucket.bucket_name, "AWS_IMAGE_STATIC_URL": self.resize_lambda_image_bucket.bucket_website_url, "BACKEND_URL": self.backend_url, "LAMBDA_AUTH_TOKEN": self.lambda_auth_token.secret_value.to_string(), }, memory_size=memory_size, timeout=Duration.seconds(300), tracing=Tracing.ACTIVE, ) function.add_event_source(SqsEventSource(queue, batch_size=1)) self.app_bucket.grant_read_write(function.role) self.resize_lambda_image_bucket.grant_read_write(function.role) return function, code
def __create_cloud_front_www( self, origin_bucket_name: str, domain_name: str, alternative_domain_names: Optional[List[str]], ssl_certificate: aws_certificatemanager.Certificate, cache_policy: aws_cloudfront.CachePolicy, origin_access_identity: aws_cloudfront.OriginAccessIdentity, edge_lambda_viewer_request: aws_lambda.Version ) -> aws_cloudfront.Distribution: domain_names = alternative_domain_names if alternative_domain_names else [] domain_names.append(domain_name) domain_names = set(domain_names) return aws_cloudfront.Distribution( self, 'CloudFrontWWW', enabled=True, certificate=ssl_certificate, comment='CloudFront Distribution for your WWW static website', domain_names=list(domain_names), http_version=HttpVersion.HTTP2, price_class=PriceClass.PRICE_CLASS_100, default_behavior=BehaviorOptions( allowed_methods=AllowedMethods.ALLOW_GET_HEAD, cached_methods=CachedMethods.CACHE_GET_HEAD, cache_policy=cache_policy, viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS, origin=aws_cloudfront_origins.S3Origin( bucket=Bucket.from_bucket_name( self, "OriginProd", bucket_name=origin_bucket_name), origin_access_identity=origin_access_identity, origin_path='/src/prod'), edge_lambdas=[ EdgeLambda(event_type=LambdaEdgeEventType.VIEWER_REQUEST, include_body=False, function_version=edge_lambda_viewer_request) ]), error_responses=[ ErrorResponse(ttl=Duration.seconds(300), response_page_path='/404.html', http_status=403, response_http_status=404) ])
def __create_lambda_function( self, lambda_name: str, handler: str, role: iam.Role, environment: dict, description: str = '', timeout: Duration = Duration.seconds(_API_HANDLER_LAMBDA_TIMEOUT) ) -> Function: return _lambda.Function( self, lambda_name, runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset(self._LAMBDA_ASSET_DIR), handler=handler, role=role, retry_attempts=0, environment=environment, timeout=timeout, memory_size=self._API_HANDLER_LAMBDA_MEMORY_SIZE, description=description)
def __create_cloud_front_www_edit_path_for_origin_lambda( self, webflow_aws_setup_bucket: str, lambda_execution_role: aws_iam.Role) -> aws_lambda.Function: return aws_lambda.Function( self, 'CloudFrontEditPathForOrigin', description= 'Appends .html extension to universal paths, preserving files with other extensions (ex .css)', handler='index.handler', runtime=aws_lambda.Runtime.NODEJS_12_X, timeout=Duration.seconds(5), memory_size=128, role=lambda_execution_role, code=Code.bucket( bucket=Bucket.from_bucket_name( self, "SourceBucketWWWEditPathForOriginLambda", bucket_name=webflow_aws_setup_bucket), key= 'lambda_function/cloudfront_www_edit_path_for_origin/package.zip' ))