def __init__(self, scope: Construct, id: str, envs: EnvSettings): super().__init__(scope, id) self.backend_repository = Repository( self, "BackendRepository", repository_name=self.get_backend_repository_name(envs), removal_policy=RemovalPolicy.DESTROY, ) self.nginx_repository = Repository( self, "NginxRepository", repository_name=self.get_nginx_repository_name(envs), removal_policy=RemovalPolicy.DESTROY, ) self.webapp_repository = Repository( self, "WebAppRepository", repository_name=self.get_webapp_repository_name(envs), removal_policy=RemovalPolicy.DESTROY, )
def create_backend_build_project(self, envs: EnvSettings, repo: Repository): project = PipelineProject( self, "BackendBuild", project_name=f"{envs.project_name}-build-backend", build_spec=self.backend_spec, environment=BuildEnvironment( environment_variables={ "REPOSITORY_URI": BuildEnvironmentVariable(value=repo.repository_uri), "PUSH_IMAGES": BuildEnvironmentVariable(value="1"), }, build_image=LinuxBuildImage.STANDARD_2_0, privileged=True, ), cache=Cache.local(LocalCacheMode.DOCKER_LAYER), ) repo.grant_pull_push(project) return project
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) stack_util = StackUtil() Repository(self, 'Repository', repository_name=stack_util.get_name('repo'), lifecycle_rules=[LifecycleRule( description='leave only one untagged', rule_priority=1, tag_status=TagStatus.UNTAGGED, max_image_count=1 )])
def retrieve_webapp_ecr_repository(self, envs: EnvSettings): return Repository.from_repository_name( self, "ECRWebAppRepository", BaseECR.get_webapp_repository_name(envs))
def retrieve_nginx_ecr_repository(self, envs: EnvSettings): return Repository.from_repository_name( self, "ECRNginxRepository", BaseECR.get_nginx_repository_name(envs))
def retrieve_backend_ecr_repository(self, envs: EnvSettings): return Repository.from_repository_name( self, "ECRBackendRepository", BaseECR.get_backend_repository_name(envs))
def __init__(self, scope: cdk.Construct, construct_id: str, ecr_repository: ecr.Repository, ecs_service: ecs.FargateService, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) backend_repository = codecommit.Repository( self, 'BackendRepository', repository_name='MythicalMysfits-BackendRepository' ) codebuild_project = codebuild.PipelineProject( self, 'BuildProject', project_name='MythicalMysfitsServiceCodeBuildProject', environment=codebuild.BuildEnvironment( build_image=codebuild.LinuxBuildImage.UBUNTU_14_04_PYTHON_3_5_2, compute_type=codebuild.ComputeType.SMALL, environment_variables={ 'AWS_ACCOUNT_ID': codebuild.BuildEnvironmentVariable( type=codebuild.BuildEnvironmentVariableType.PLAINTEXT, value=self.account), 'AWS_DEFAULT_REGION': codebuild.BuildEnvironmentVariable( type=codebuild.BuildEnvironmentVariableType.PLAINTEXT, value=self.region), }, privileged=True ) ) codebuild_policy_stm = _iam.PolicyStatement() codebuild_policy_stm.add_resources(backend_repository.repository_arn) codebuild_policy_stm.add_actions( "codecommit:ListBranches", "codecommit:ListRepositories", "codecommit:BatchGetRepositories", "codecommit:GitPull" ) codebuild_project.add_to_role_policy(codebuild_policy_stm) ecr_repository.grant_pull_push(codebuild_project.grant_principal) source_output = codepipeline.Artifact() source_action = actions.CodeCommitSourceAction( action_name='CodeCommit-Source', branch='main', trigger=actions.CodeCommitTrigger.EVENTS, repository=backend_repository, output=source_output ) build_output = codepipeline.Artifact() build_action = actions.CodeBuildAction( action_name='Build', input=source_output, outputs=[ build_output ], project=codebuild_project ) deploy_action = actions.EcsDeployAction( action_name='DeployAction', service=ecs_service, input=build_output ) pipeline = codepipeline.Pipeline( self, 'Pipeline', pipeline_name='MythicalMysfitsPipeline', ) pipeline.add_stage(stage_name='Source', actions=[source_action]) pipeline.add_stage(stage_name='Build', actions=[build_action]) # # the following pipeline.add_stage doesn't work # pipeline.add_stage(stage_name='Deploy', actions=[deploy_action]) cdk.CfnOutput(self, 'BackendRepositoryCloneUrlHttp', description='Backend Repository CloneUrl HTTP', value=backend_repository.repository_clone_url_http) cdk.CfnOutput(self, 'BackendRepositoryCloneUrlSsh', description='Backend Repository CloneUrl SSH', value=backend_repository.repository_clone_url_ssh)
def create_pipeline( scope: core.Construct, stack_name: str, ecr_repository: ecr.Repository, app_service: ecs.FargateService, config: StackConfig, worker_service: ecs.FargateService = None, ): project = codebuild.PipelineProject( scope, 'build', project_name=stack_name, description=f'Build project for {stack_name}. Managed by AWS CDK.', environment=codebuild.BuildEnvironment( privileged=True, build_image=codebuild.LinuxBuildImage.AMAZON_LINUX_2_2), environment_variables={ 'REPOSITORY_URI': codebuild.BuildEnvironmentVariable( value=ecr_repository.repository_uri), }, cache=codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM, codebuild.LocalCacheMode.SOURCE), build_spec=codebuild.BuildSpec.from_object({ 'version': '0.2', 'phases': { 'pre_build': { 'commands': [ '$(aws ecr get-login --no-include-email --region $AWS_REGION)', 'IMAGE_LATEST=${REPOSITORY_URI}:latest', 'IMAGE_VERSION=${REPOSITORY_URI}:${CODEBUILD_RESOLVED_SOURCE_VERSION:0:7}' ] }, 'build': { 'commands': [ f'docker login -u="{config.docker_user}" -p="{config.docker_password}"', 'docker build -f Dockerfile.prod -t ${IMAGE_LATEST} .', 'docker tag ${IMAGE_LATEST} ${IMAGE_VERSION}' ] }, 'post_build': { 'commands': [ 'docker push ${IMAGE_LATEST}', 'docker push ${IMAGE_VERSION}', "printf '[{\"name\":\"container\",\"imageUri\":\"%s\"}]' ${IMAGE_VERSION} > imagedefinitions.json" ] } }, 'artifacts': { 'files': ['imagedefinitions.json'] } })) ecr_repository.grant_pull_push(project) source_output = codepipeline.Artifact() source_action = actions.GitHubSourceAction( action_name='Source', owner=config.repo_owner, repo=config.repo_name, branch=config.repo_branch, oauth_token=core.SecretValue.plain_text(config.github_access_token), output=source_output, ) build_output = codepipeline.Artifact() build_action = actions.CodeBuildAction( action_name='Build', project=project, input=source_output, outputs=[build_output], type=actions.CodeBuildActionType.BUILD, ) artifact_bucket = s3.Bucket.from_bucket_name(scope, 'artifactBucket', config.artifact_bucket) deploy_actions = [ actions.EcsDeployAction( action_name='App', service=app_service, input=build_output, ) ] if worker_service: deploy_actions.append( actions.EcsDeployAction( action_name='Worker', service=worker_service, input=build_output, )) pipeline = codepipeline.Pipeline( scope, 'pipeline', pipeline_name=stack_name, restart_execution_on_update=True, artifact_bucket=artifact_bucket, ) pipeline.add_stage( stage_name='Source', actions=[source_action], ) pipeline.add_stage(stage_name='Build', actions=[build_action]) if config.enable_deploy_approval: pipeline.add_stage(stage_name='Approval', actions=[ actions.ManualApprovalAction( action_name='Approve', notify_emails=[]) ]) pipeline.add_stage( stage_name='Deploy', actions=deploy_actions, )
def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # The code that defines your stack goes here table = dynamodb.Table( self, "TheTable", table_name="cdk-table", partition_key=dynamodb.Attribute( name="id", type=dynamodb.AttributeType.STRING), removal_policy=cdk.RemovalPolicy.DESTROY, ) # compute_environment = batch.ComputeEnvironment( # self, # "MyComputeEnvironment", # compute_environment_name="cdk-env", # compute_resources=batch.ComputeResources( # vpc=Vpc.from_lookup(self, "VPC", is_default=True), # ), # enabled=True, # managed=True, # ) job_role = Role( self, "BatchJobRole", assumed_by=ServicePrincipal("ecs-tasks.amazonaws.com"), description="Role for a container in a Batch job", role_name="CDK-BatchJobRole", managed_policies=[ ManagedPolicy.from_aws_managed_policy_name( managed_policy_name="AmazonDynamoDBFullAccess"), ], ) repository = Repository( self, "MyRepository", removal_policy=cdk.RemovalPolicy.DESTROY, repository_name="cdk-my-repository", lifecycle_rules=[ LifecycleRule(max_image_count=5, description="Max 5 images") ], ) image: ContainerImage = ContainerImage.from_ecr_repository( repository=repository, tag="latest", ) container = batch.JobDefinitionContainer( image=image, job_role=job_role, command=["python", "run.py", "--help"], environment={ "READINGS_TABLE": table.table_name, "AWS_REGION": self.region, }, vcpus=1, log_configuration=batch.LogConfiguration( log_driver=batch.LogDriver.AWSLOGS), memory_limit_mib=2048, ) batch.JobDefinition( self, "JobDefinitionCreate", container=container, job_definition_name="create", retry_attempts=1, )
def __init__( self, scope: App, id: str, envs: EnvSettings, components: ComponentsStack, base_resources: BaseResources, ): super().__init__(scope, id) self.db_secret_arn = Fn.import_value( BaseResources.get_database_secret_arn_output_export_name(envs)) self.job_processing_queues = components.data_processing_queues self.vpc = base_resources.vpc self.db = base_resources.db self.app_bucket = Bucket(self, "App", versioned=True) if self.app_bucket.bucket_arn: CfnOutput( self, id="AppBucketOutput", export_name=self.get_app_bucket_arn_output_export_name(envs), value=self.app_bucket.bucket_arn, ) self.pages_bucket = Bucket(self, "Pages", public_read_access=True) self.domain_name = StringParameter.from_string_parameter_name( self, "DomainNameParameter", string_parameter_name="/schema-cms-app/DOMAIN_NAME").string_value self.certificate_arn = StringParameter.from_string_parameter_name( self, "CertificateArnParameter", string_parameter_name="/schema-cms-app/CERTIFICATE_ARN" ).string_value django_secret = Secret(self, "DjangoSecretKey", secret_name="SCHEMA_CMS_DJANGO_SECRET_KEY") lambda_auth_token_secret = Secret( self, "LambdaAuthToken", secret_name="SCHEMA_CMS_LAMBDA_AUTH_TOKEN") if lambda_auth_token_secret.secret_arn: CfnOutput( self, id="lambdaAuthTokenArnOutput", export_name=self.get_lambda_auth_token_arn_output_export_name( envs), value=lambda_auth_token_secret.secret_arn, ) self.django_secret_key = EcsSecret.from_secrets_manager(django_secret) self.lambda_auth_token = EcsSecret.from_secrets_manager( lambda_auth_token_secret) tag_from_context = self.node.try_get_context("app_image_tag") tag = tag_from_context if tag_from_context != "undefined" else None api_image = ContainerImage.from_ecr_repository( repository=Repository.from_repository_name( self, id="BackendRepository", repository_name=BaseECR.get_backend_repository_name(envs)), tag=tag, ) nginx_image = ContainerImage.from_ecr_repository( repository=Repository.from_repository_name( self, id="NginxRepository", repository_name=BaseECR.get_nginx_repository_name(envs)), tag=tag, ) self.api = ApplicationLoadBalancedFargateService( self, "ApiService", service_name=f"{envs.project_name}-api-service", cluster=Cluster.from_cluster_attributes( self, id="WorkersCluster", cluster_name="schema-ecs-cluster", vpc=self.vpc, security_groups=[], ), task_image_options=ApplicationLoadBalancedTaskImageOptions( image=nginx_image, container_name="nginx", container_port=80, enable_logging=True, ), desired_count=1, cpu=512, memory_limit_mib=1024, certificate=Certificate.from_certificate_arn( self, "Cert", certificate_arn=self.certificate_arn), domain_name=self.domain_name, domain_zone=PrivateHostedZone( self, "zone", vpc=self.vpc, zone_name=self.domain_name, ), ) self.api.task_definition.add_container( "backend", image=api_image, command=[ "sh", "-c", "/bin/chamber exec $CHAMBER_SERVICE_NAME -- ./scripts/run.sh" ], logging=AwsLogDriver(stream_prefix="backend-container"), environment={ "POSTGRES_DB": envs.data_base_name, "AWS_STORAGE_BUCKET_NAME": self.app_bucket.bucket_name, "AWS_STORAGE_PAGES_BUCKET_NAME": self.pages_bucket.bucket_name, "SQS_WORKER_QUEUE_URL": self.job_processing_queues[0].queue_url, "SQS_WORKER_EXT_QUEUE_URL": self.job_processing_queues[1].queue_url, "SQS_WORKER_MAX_QUEUE_URL": self.job_processing_queues[2].queue_url, "CHAMBER_SERVICE_NAME": "schema-cms-app", "CHAMBER_KMS_KEY_ALIAS": envs.project_name, }, secrets={ "DB_CONNECTION": EcsSecret.from_secrets_manager( Secret.from_secret_arn(self, id="DbSecret", secret_arn=self.db_secret_arn)), "DJANGO_SECRET_KEY": self.django_secret_key, "LAMBDA_AUTH_TOKEN": self.lambda_auth_token, }, cpu=512, memory_limit_mib=1024, ) self.django_secret_key.grant_read( self.api.service.task_definition.task_role) self.app_bucket.grant_read_write( self.api.service.task_definition.task_role) self.pages_bucket.grant_read_write( self.api.service.task_definition.task_role) for queue in self.job_processing_queues: queue.grant_send_messages( self.api.service.task_definition.task_role) self.api.service.connections.allow_to(self.db.connections, Port.tcp(5432)) self.api.task_definition.add_to_task_role_policy( PolicyStatement( actions=["ses:SendRawEmail", "ses:SendBulkTemplatedEmail"], resources=["*"], )) self.api.task_definition.add_to_task_role_policy( PolicyStatement( actions=[ "kms:Get*", "kms:Describe*", "kms:List*", "kms:Decrypt" ], resources=[ Fn.import_value( BaseKMS.get_kms_arn_output_export_name(envs)) ], )) self.api.task_definition.add_to_task_role_policy( PolicyStatement(actions=["ssm:DescribeParameters"], resources=["*"])) self.api.task_definition.add_to_task_role_policy( PolicyStatement( actions=["ssm:GetParameters*"], resources=[ f"arn:aws:ssm:{self.region}:{self.account}:parameter/schema-cms-app/*" ], ))
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) stack_util = StackUtil() repo = Repository.from_repository_attributes( scope=self, id='FunctionRepository', repository_name=stack_util.get_name('repo'), repository_arn= f'arn:aws:ecr:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:repository/{stack_util.get_name("repo")}' ) fail_task = Fail(self, 'FailTask', comment='failed.') succeed_task = Succeed(self, 'SucceedTask', comment='succeeded.') get_forecast_function = get_get_forecast_resource(self, repo) send_message_function = get_send_message_resource(self, repo) get_forecast_task = LambdaInvoke(self, 'GetForecastTask', lambda_function=get_forecast_function, input_path='$', result_path='$.get_forecast_task', output_path='$', payload_response_only=True) get_forecast_task.add_catch(fail_task, errors=[Errors.ALL], result_path='$.error_info') send_message_task = LambdaInvoke(self, 'SendMessageTask', lambda_function=send_message_function, input_path='$.get_forecast_task.body', result_path='$.send_message_function', output_path='$', payload_response_only=True) send_message_task.add_catch(fail_task, errors=[Errors.ALL], result_path='$.error_info') state_machine = StateMachine( self, id='StateMachine', state_machine_name=stack_util.get_upper_name('STATE-MACHINE'), definition=get_forecast_task.next(send_message_task).next( succeed_task)) today_rule = Rule( self, 'StateMachineTodayRule', description='invoking state machine for today', rule_name=stack_util.get_upper_name('INVOKE-STATE-MACHINE-TODAY'), schedule=Schedule.cron( hour='23', minute='0', )) tomorrow_rule = Rule(self, 'StateMachineTomorrowRule', description='invoking state machine for tomorrow', rule_name=stack_util.get_upper_name( 'INVOKE-STATE-MACHINE-TOMORROW'), schedule=Schedule.cron( hour='9', minute='30', )) today_target = SfnStateMachine(state_machine, input=RuleTargetInput.from_object({ 'city': '130010', 'date_label': '今日' })) today_rule.add_target(today_target) tomorrow_target = SfnStateMachine(state_machine, input=RuleTargetInput.from_object({ 'city': '130010', 'date_label': '明日' })) tomorrow_rule.add_target(tomorrow_target)