def __init__(self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, **kwargs) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) if deployment == Deployment.PRODUCTION: desired_count = 1 # Currently this pod is stateful, and as such cannot be run more than once priority = 46 else: desired_count = 1 priority = 146 api_fqdn = dns.subdomain_to_fqdn("api.bananas") api_url = f"https://{api_fqdn}" frontend_fqdn = dns.subdomain_to_fqdn(self.subdomain_name) frontend_url = f"https://{frontend_fqdn}" sentry_dsn = parameter_store.add_secure_string( f"/BananasFrontendWeb/{deployment.value}/SentryDSN").parameter ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/bananas-frontend-web", port=80, memory_limit_mib=64, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--api-url", api_url, "--frontend-url", frontend_url, "run", "-p", "80", "-h", "0.0.0.0", ], environment={ "WEBCLIENT_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "WEBCLIENT_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), }, )
def __init__(self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, **kwargs) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) if deployment == Deployment.PRODUCTION: desired_count = 2 priority = 62 else: desired_count = 1 priority = 162 api_fqdn = dns.subdomain_to_fqdn("api.master") api_url = f"https://{api_fqdn}" sentry_dsn = parameter_store.add_secure_string( f"/MasterServerWeb/{deployment.value}/SentryDSN").parameter ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/master-server-web", port=80, memory_limit_mib=96, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--api-url", api_url, "run", "-p", "80", "-h", "0.0.0.0", ], environment={ "WEBCLIENT_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "WEBCLIENT_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), }, )
def __init__( self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, bucket: Bucket, **kwargs, ) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) if deployment == Deployment.PRODUCTION: desired_count = 2 priority = 44 memory = 256 github_url = "https://github.com/OpenTTD/BaNaNaS" content_port = 3978 bootstrap_command = ["--bootstrap-unique-id", "4f474658"] else: desired_count = 1 priority = 144 memory = 128 github_url = "https://github.com/OpenTTD/BaNaNaS-staging" content_port = 4978 bootstrap_command = [] cdn_fqdn = dns.subdomain_to_fqdn("bananas.cdn") cdn_url = f"http://{cdn_fqdn}" sentry_dsn = parameter_store.add_secure_string(f"/BananasServer/{deployment.value}/SentryDSN").parameter reload_secret = parameter_store.add_secure_string(f"/BananasServer/{deployment.value}/ReloadSecret").parameter command = [ "--storage", "s3", "--storage-s3-bucket", bucket.bucket_name, "--index", "github", "--index-github-url", github_url, "--cdn-url", cdn_url, "--bind", "0.0.0.0", "--content-port", str(content_port), "--proxy-protocol", ] command.extend(bootstrap_command) self.container = ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, path_pattern=self.path_pattern, allow_via_http=True, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/bananas-server", port=80, memory_limit_mib=memory, desired_count=desired_count, cluster=cluster, priority=priority, command=command, environment={ "BANANAS_SERVER_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "BANANAS_SERVER_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), "BANANAS_SERVER_RELOAD_SECRET": Secret.from_ssm_parameter(reload_secret), }, ) self.container.add_port(content_port) nlb.add_nlb(self, self.container.service, Port.tcp(content_port), self.nlb_subdomain_name, "BaNaNaS Server") self.container.task_role.add_to_policy( PolicyStatement( actions=[ "s3:GetObject", "s3:ListBucket", ], resources=[ bucket.bucket_arn, StringConcat().join(bucket.bucket_arn, "/*"), ], ) )
def __init__( self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, bucket: Bucket, **kwargs, ) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) if deployment == Deployment.PRODUCTION: desired_count = 1 # Currently this pod is stateful, and as such cannot be run more than once tus_priority = 40 priority = 42 memory = 256 github_url = "[email protected]:OpenTTD/BaNaNaS.git" client_file = "clients-production.yaml" else: desired_count = 1 tus_priority = 140 priority = 142 memory = 96 github_url = "[email protected]:OpenTTD/BaNaNaS-staging.git" client_file = "clients-staging.yaml" sentry_dsn = parameter_store.add_secure_string(f"/BananasApi/{deployment.value}/SentryDSN").parameter user_github_client_id = parameter_store.add_secure_string(f"/BananasApi/{deployment.value}/UserGithubClientId").parameter user_github_client_secret = parameter_store.add_secure_string(f"/BananasApi/{deployment.value}/UserGithubClientSecret").parameter index_github_private_key = parameter_store.add_secure_string(f"/BananasApi/{deployment.value}/IndexGithubPrivateKey").parameter reload_secret = parameter_store.add_secure_string(f"/BananasApi/{deployment.value}/ReloadSecret").parameter self.container = ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/bananas-api", port=80, memory_limit_mib=memory, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--storage", "s3", "--storage-s3-bucket", bucket.bucket_name, "--index", "github", "--index-github-url", github_url, "--client-file", client_file, "--user", "github", "--bind", "0.0.0.0", "--behind-proxy", ], environment={ "BANANAS_API_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "BANANAS_API_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), "BANANAS_API_USER_GITHUB_CLIENT_ID": Secret.from_ssm_parameter(user_github_client_id), "BANANAS_API_USER_GITHUB_CLIENT_SECRET": Secret.from_ssm_parameter(user_github_client_secret), "BANANAS_API_INDEX_GITHUB_PRIVATE_KEY": Secret.from_ssm_parameter(index_github_private_key), "BANANAS_API_RELOAD_SECRET": Secret.from_ssm_parameter(reload_secret), }, ) self.container.add_port(1080) self.container.add_target( subdomain_name=self.subdomain_name, port=1080, priority=tus_priority, path_pattern="/new-package/tus/*", ) self.container.task_role.add_to_policy( PolicyStatement( actions=[ "s3:PutObject", "s3:PutObjectAcl", ], resources=[ StringConcat().join(bucket.bucket_arn, "/*"), ], ) )
def __init__( self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, vpc: IVpc, **kwargs, ) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) efs_cache = FileSystem( self, "WikiCacheEFS", vpc=vpc, ) efs_cache.connections.allow_default_port_from(cluster) if deployment == Deployment.PRODUCTION: desired_count = 1 # Currently this pod is stateful, and as such cannot be run more than once priority = 80 memory = 384 github_url = "[email protected]:OpenTTD/wiki-data.git" github_history_url = "https://github.com/OpenTTD/wiki-data" frontend_url = "https://wiki.openttd.org" else: desired_count = 1 priority = 180 memory = 128 github_url = "[email protected]:OpenTTD/wiki-data-staging.git" github_history_url = "https://github.com/OpenTTD/wiki-data-staging" frontend_url = "https://wiki.staging.openttd.org" sentry_dsn = parameter_store.add_secure_string(f"/Wiki/{deployment.value}/SentryDSN").parameter user_github_client_id = parameter_store.add_secure_string(f"/Wiki/{deployment.value}/UserGithubClientId").parameter user_github_client_secret = parameter_store.add_secure_string(f"/Wiki/{deployment.value}/UserGithubClientSecret").parameter storage_github_private_key = parameter_store.add_secure_string(f"/Wiki/{deployment.value}/StorageGithubPrivateKey").parameter reload_secret = parameter_store.add_secure_string(f"/Wiki/{deployment.value}/ReloadSecret").parameter self.container = ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/truebrain/truewiki", port=80, memory_limit_mib=memory, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--storage", "github", "--storage-github-url", github_url, "--storage-github-history-url", github_history_url, "--storage-folder", "/data", "--user", "github", "--frontend-url", frontend_url, "--cache-metadata-file", "/cache/metadata.json", "--cache-page-folder", "/cache-pages", "--bind", "0.0.0.0", ], environment={ "TRUEWIKI_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "TRUEWIKI_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), "TRUEWIKI_USER_GITHUB_CLIENT_ID": Secret.from_ssm_parameter(user_github_client_id), "TRUEWIKI_USER_GITHUB_CLIENT_SECRET": Secret.from_ssm_parameter(user_github_client_secret), "TRUEWIKI_STORAGE_GITHUB_PRIVATE_KEY": Secret.from_ssm_parameter(storage_github_private_key), "TRUEWIKI_RELOAD_SECRET": Secret.from_ssm_parameter(reload_secret), }, volumes={ "/cache": Volume( name="cache", efs_volume_configuration=EfsVolumeConfiguration( file_system_id=efs_cache.file_system_id, ), ), }, )
def __init__( self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, vpc: IVpc, **kwargs, ) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) efs = FileSystem( self, "EintsEFS", vpc=vpc, ) efs.connections.allow_default_port_from(cluster) if deployment == Deployment.PRODUCTION: desired_count = 1 # Currently this pod is stateful, and as such cannot be run more than once priority = 70 memory = 512 else: desired_count = 1 priority = 170 memory = 128 github_org_api_token = parameter_store.add_secure_string( f"/Eints/{deployment.value}/GithubOrgApiToken").parameter github_oauth2_client_id = parameter_store.add_secure_string( f"/Eints/{deployment.value}/GithubOauth2ClientId").parameter github_oauth2_client_secret = parameter_store.add_secure_string( f"/Eints/{deployment.value}/GithubOauth2ClientSecret").parameter translators_password = parameter_store.add_secure_string( f"/Eints/{deployment.value}/TranslatorsPassword").parameter sentry_dsn = parameter_store.add_secure_string( f"/Eints/{deployment.value}/SentryDSN").parameter ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/eints-openttd-github", port=80, memory_limit_mib=memory, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--server-host", "0.0.0.0", "--server-port", "80", "--server-mode", "production", "--authentication", "github", "--stable-languages", "stable_languages", "--unstable-languages", "unstable_languages", "--project-cache", "1", "--project-types", "openttd", "--storage-format", "split-languages", "--data-format", "json", "--language-file-size", "10000000", "--num-backup-files", "1", "--max-num-changes", "5", "--min-num-changes", "2", "--change-stable-age", "600", "--github-organization", "OpenTTD", ], environment={ "EINTS_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "EINTS_GITHUB_ORG_API_TOKEN": Secret.from_ssm_parameter(github_org_api_token), "EINTS_GITHUB_OAUTH2_CLIENT_ID": Secret.from_ssm_parameter(github_oauth2_client_id), "EINTS_GITHUB_OAUTH2_CLIENT_SECRET": Secret.from_ssm_parameter(github_oauth2_client_secret), "EINTS_TRANSLATORS_PASSWORD": Secret.from_ssm_parameter(translators_password), "EINTS_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), }, volumes={ "/data": Volume( name="data", efs_volume_configuration=EfsVolumeConfiguration( file_system_id=efs.file_system_id, ), ) }, )
def __init__( self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, vpc: IVpc, **kwargs, ) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) efs_seen = FileSystem( self, "DorpsGekSeenEFS", vpc=vpc, ) efs_seen.connections.allow_default_port_from(cluster) efs_logs = FileSystem( self, "DorpsGekLogsEFS", vpc=vpc, ) efs_logs.connections.allow_default_port_from(cluster) if deployment == Deployment.PRODUCTION: desired_count = 1 priority = 30 addressed_by = "@" irc_username = "******" channels = [ "--channel", "dorpsgek", "--channel", "openttd,public", "--channel", "openttd.dev,public", "--channel", "openttd.notice", "--channel", "openttd.tgp", "--channel", "opendune,public", ] else: desired_count = 1 priority = 130 addressed_by = "%" irc_username = "******" channels = [ "--channel", "dorpsgek", "--channel", "dorpsgek-test,public", ] sentry_dsn = parameter_store.add_secure_string( f"/Dorpsgek/{deployment.value}/SentryDSN").parameter github_app_id = parameter_store.add_secure_string( f"/Dorpsgek/{deployment.value}/GithubAppId").parameter github_app_private_key = parameter_store.add_secure_string( f"/Dorpsgek/{deployment.value}/GithubAppPrivateKey").parameter github_app_secret = parameter_store.add_secure_string( f"/Dorpsgek/{deployment.value}/GithubAppSecret").parameter nickserv_password = parameter_store.add_secure_string( f"/Dorpsgek/{deployment.value}/NickservPassword").parameter ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/dorpsgek", port=80, memory_limit_mib=96, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--irc-username", irc_username, "--nickserv-username", irc_username, "--addressed-by", addressed_by, ] + channels, environment={ "DORPSGEK_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "DORPSGEK_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), "DORPSGEK_GITHUB_APP_ID": Secret.from_ssm_parameter(github_app_id), "DORPSGEK_GITHUB_APP_PRIVATE_KEY": Secret.from_ssm_parameter(github_app_private_key), "DORPSGEK_GITHUB_APP_SECRET": Secret.from_ssm_parameter(github_app_secret), "DORPSGEK_NICKSERV_PASSWORD": Secret.from_ssm_parameter(nickserv_password), }, volumes={ "/code/data": Volume( name="data", efs_volume_configuration=EfsVolumeConfiguration( file_system_id=efs_seen.file_system_id, ), ), "/code/logs/ChannelLogger": Volume( name="logs", efs_volume_configuration=EfsVolumeConfiguration( file_system_id=efs_logs.file_system_id, ), ), }, )
def __init__(self, scope: Construct, id: str, *, deployment: Deployment, policy: Policy, cluster: ICluster, **kwargs) -> None: super().__init__(scope, id, **kwargs) Tags.of(self).add("Application", self.application_name) Tags.of(self).add("Deployment", deployment.value) policy.add_stack(self) if deployment == Deployment.PRODUCTION: desired_count = 2 priority = 60 dynamodb_prefix = "P-" else: desired_count = 1 priority = 160 dynamodb_prefix = "S-" sentry_dsn = parameter_store.add_secure_string( f"/MasterServerApi/{deployment.value}/SentryDSN").parameter self.container = ECSHTTPSContainer( self, self.application_name, subdomain_name=self.subdomain_name, deployment=deployment, policy=policy, application_name=self.application_name, image_name="ghcr.io/openttd/master-server", port=80, memory_limit_mib=96, desired_count=desired_count, cluster=cluster, priority=priority, command=[ "--app", "web_api", "--bind", "0.0.0.0", "--db", "dynamodb", "--dynamodb-region", "eu-central-1", "--dynamodb-prefix", dynamodb_prefix, ], environment={ "MASTER_SERVER_SENTRY_ENVIRONMENT": deployment.value.lower(), }, secrets={ "MASTER_SERVER_SENTRY_DSN": Secret.from_ssm_parameter(sentry_dsn), }, ) table_and_index = [] for table in ("S-MSU-ip-port", "S-MSU-server", "P-MSU-ip-port", "P-MSU-server"): table_and_index.extend([ f"arn:aws:dynamodb:{self.region}:{self.account}:table/{table}", f"arn:aws:dynamodb:{self.region}:{self.account}:table/{table}/index/online_view", f"arn:aws:dynamodb:{self.region}:{self.account}:table/{table}/index/time_last_seen_view", ]) self.container.task_role.add_to_policy( PolicyStatement( actions=[ "dynamodb:CreateTable", "dynamodb:UpdateTimeToLive", "dynamodb:PutItem", "dynamodb:DescribeTable", "dynamodb:ListTables", "dynamodb:GetItem", "dynamodb:Query", "dynamodb:UpdateItem", ], resources=table_and_index, ))
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/*" ], ))