This is nearly working in all Pulumi.
Permissions are not correct in code to allow the images to be pulled by the ECS tasks. As such, they will not start and run without some manual intervention. Pulumi will happily let the process sit at this stage forever.
This commit is contained in:
commit
cf369c6a3a
2
air-tech/.gitignore
vendored
Normal file
2
air-tech/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.pyc
|
||||||
|
venv/
|
2
air-tech/Pulumi.prod.yaml
Normal file
2
air-tech/Pulumi.prod.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
config:
|
||||||
|
aws:region: us-east-2
|
6
air-tech/Pulumi.yaml
Normal file
6
air-tech/Pulumi.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
name: air-tech
|
||||||
|
runtime:
|
||||||
|
name: python
|
||||||
|
options:
|
||||||
|
virtualenv: venv
|
||||||
|
description: A technical assessment
|
216
air-tech/__main__.py
Normal file
216
air-tech/__main__.py
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
import pulumi
|
||||||
|
from pulumi import Config, Output, export
|
||||||
|
import pulumi_aws as aws
|
||||||
|
from pulumi_aws import acm, alb, ecs, ec2, lb, iam, ecr
|
||||||
|
import pulumi_awsx as awsx
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
config = Config()
|
||||||
|
# container_port = config.get_int("containerPort", 80)
|
||||||
|
cpu = config.get_int("cpu", 512)
|
||||||
|
memory = config.get_int("memory", 128)
|
||||||
|
# Create a VPC
|
||||||
|
vpc = ec2.Vpc("production", cidr_block="10.0.0.0/16")
|
||||||
|
|
||||||
|
# Create a Gateway
|
||||||
|
ig = ec2.InternetGateway("internet-gateway", vpc_id=vpc.id)
|
||||||
|
|
||||||
|
cert = acm.Certificate(
|
||||||
|
"air-tech",
|
||||||
|
domain_name="air-tech.ahosking.com",
|
||||||
|
validation_method="DNS",
|
||||||
|
)
|
||||||
|
# Public Subnet
|
||||||
|
public_subnet = ec2.Subnet(
|
||||||
|
"public-subnet",
|
||||||
|
vpc_id=vpc.id,
|
||||||
|
cidr_block="10.0.1.0/26",
|
||||||
|
availability_zone="us-east-2a",
|
||||||
|
|
||||||
|
# Allow the Internet Gateway to handle public traffic
|
||||||
|
map_public_ip_on_launch=True
|
||||||
|
)
|
||||||
|
public_subnet2 = ec2.Subnet(
|
||||||
|
"public-subnet2",
|
||||||
|
vpc_id=vpc.id,
|
||||||
|
cidr_block="10.0.2.0/26",
|
||||||
|
availability_zone="us-east-2b",
|
||||||
|
|
||||||
|
# Allow the Internet Gateway to handle public traffic
|
||||||
|
map_public_ip_on_launch=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Associate the Gateway to a route
|
||||||
|
route_table = ec2.RouteTable('route-table', vpc_id=vpc.id)
|
||||||
|
route = ec2.Route('route', route_table_id=route_table.id,
|
||||||
|
destination_cidr_block='0.0.0.0/0', gateway_id=ig.id)
|
||||||
|
|
||||||
|
# Private Subnet
|
||||||
|
private_subnet = ec2.Subnet(
|
||||||
|
"private-subnet",
|
||||||
|
vpc_id=vpc.id,
|
||||||
|
cidr_block="10.0.3.0/26",
|
||||||
|
availability_zone="us-east-2a",
|
||||||
|
map_public_ip_on_launch=False
|
||||||
|
)
|
||||||
|
private_subnet2 = ec2.Subnet(
|
||||||
|
"private-subnet2",
|
||||||
|
vpc_id=vpc.id,
|
||||||
|
cidr_block="10.0.4.0/26",
|
||||||
|
availability_zone="us-east-2b",
|
||||||
|
map_public_ip_on_launch=False
|
||||||
|
)
|
||||||
|
repo = ecr.Repository("repo")
|
||||||
|
|
||||||
|
# Create an IAM role
|
||||||
|
ecs_task_execution_role = iam.Role("ecsExecutionRole",
|
||||||
|
path="/",
|
||||||
|
assume_role_policy=iam.get_policy_document(statements=[{
|
||||||
|
"actions": ["sts:AssumeRole"],
|
||||||
|
"principals": {
|
||||||
|
"type": "Service",
|
||||||
|
"identifiers": ["ecs-tasks.amazonaws.com"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]).json,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Attach a policy to the execution role that will allow it to pull images from ECR
|
||||||
|
iam.RolePolicy("accessECRImages",
|
||||||
|
role=ecs_task_execution_role.id,
|
||||||
|
policy={
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"ecr:GetDownloadUrlForLayer",
|
||||||
|
"ecr:BatchGetImage",
|
||||||
|
"ecr:BatchCheckLayerAvailability",
|
||||||
|
],
|
||||||
|
"Resource": repo.repository_arn
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
image_web = awsx.ecr.Image(
|
||||||
|
"image_web",
|
||||||
|
repository_url=repo.url,
|
||||||
|
path=".",
|
||||||
|
dockerfile=".\infra-web\Dockerfile")
|
||||||
|
|
||||||
|
image_api = awsx.ecr.Image(
|
||||||
|
"image_api",
|
||||||
|
repository_url=repo.url,
|
||||||
|
path=".",
|
||||||
|
dockerfile=".\infra-api\Dockerfile")
|
||||||
|
|
||||||
|
security_group = aws.ec2.SecurityGroup(
|
||||||
|
"securityGroup",
|
||||||
|
vpc_id=vpc.id,
|
||||||
|
egress=[aws.ec2.SecurityGroupEgressArgs(
|
||||||
|
from_port=0,
|
||||||
|
to_port=0,
|
||||||
|
protocol="-1",
|
||||||
|
cidr_blocks=["0.0.0.0/0"],
|
||||||
|
ipv6_cidr_blocks=["::/0"],
|
||||||
|
)])
|
||||||
|
# Create an ECS Cluster
|
||||||
|
cluster = ecs.Cluster("cluster")
|
||||||
|
|
||||||
|
pulumi.export("certificateArn", cert.arn)
|
||||||
|
loadbalancer = lb.LoadBalancer(
|
||||||
|
"loadbalancer",
|
||||||
|
load_balancer_type="application",
|
||||||
|
security_groups=[security_group.id],
|
||||||
|
subnets=[public_subnet.id, public_subnet2.id])
|
||||||
|
|
||||||
|
|
||||||
|
target_group = lb.TargetGroup('target-group',
|
||||||
|
port=5000,
|
||||||
|
protocol="HTTP",
|
||||||
|
target_type="ip",
|
||||||
|
vpc_id=vpc.id)
|
||||||
|
|
||||||
|
# Create a listener for the ALB at port 80
|
||||||
|
listener = lb.Listener('listener',
|
||||||
|
load_balancer_arn=loadbalancer.arn,
|
||||||
|
port=80,
|
||||||
|
default_actions=[{
|
||||||
|
'type': "forward",
|
||||||
|
'target_group_arn': target_group.arn # Forward to our target group
|
||||||
|
}])
|
||||||
|
|
||||||
|
|
||||||
|
web_sg = ec2.SecurityGroup('web-sg',
|
||||||
|
vpc_id=vpc.id,
|
||||||
|
ingress=[
|
||||||
|
{
|
||||||
|
'protocol': 'tcp',
|
||||||
|
'from_port': 80,
|
||||||
|
'to_port': 80,
|
||||||
|
'cidr_blocks': ['0.0.0.0/0'],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
egress=[
|
||||||
|
{
|
||||||
|
'protocol': '-1',
|
||||||
|
'from_port': 0,
|
||||||
|
'to_port': 0,
|
||||||
|
'cidr_blocks': ['0.0.0.0/0'],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
api = awsx.ecs.FargateService(
|
||||||
|
"api",
|
||||||
|
cluster=cluster.arn,
|
||||||
|
network_configuration={
|
||||||
|
'assignPublicIp': "false",
|
||||||
|
'subnets': [private_subnet.id],
|
||||||
|
'securityGroups': [web_sg.id]
|
||||||
|
},
|
||||||
|
task_definition_args=awsx.ecs.FargateServiceTaskDefinitionArgs(
|
||||||
|
container=awsx.ecs.TaskDefinitionContainerDefinitionArgs(
|
||||||
|
name="theApi",
|
||||||
|
image=image_api.image_uri,
|
||||||
|
cpu=cpu,
|
||||||
|
memory=memory,
|
||||||
|
essential=True,
|
||||||
|
port_mappings=[awsx.ecs.TaskDefinitionPortMappingArgs(
|
||||||
|
container_port=5000,
|
||||||
|
host_port=5000,
|
||||||
|
)],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
service = awsx.ecs.FargateService(
|
||||||
|
"web",
|
||||||
|
cluster=cluster.arn,
|
||||||
|
network_configuration={
|
||||||
|
'assignPublicIp': "true",
|
||||||
|
'subnets': [public_subnet.id],
|
||||||
|
'securityGroups': [web_sg.id]
|
||||||
|
},
|
||||||
|
# assign_public_ip=True,
|
||||||
|
task_definition_args=awsx.ecs.FargateServiceTaskDefinitionArgs(
|
||||||
|
container=awsx.ecs.TaskDefinitionContainerDefinitionArgs(
|
||||||
|
name="theOne",
|
||||||
|
image=image_web.image_uri,
|
||||||
|
cpu=cpu,
|
||||||
|
memory=memory,
|
||||||
|
essential=True,
|
||||||
|
port_mappings=[awsx.ecs.TaskDefinitionPortMappingArgs(
|
||||||
|
container_port=5000,
|
||||||
|
host_port=5000,
|
||||||
|
target_group=target_group,
|
||||||
|
)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
opts=pulumi.ResourceOptions(depends_on=[api, target_group])
|
||||||
|
)
|
2
air-tech/requirements.txt
Normal file
2
air-tech/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pulumi>=3.0.0,<4.0.0
|
||||||
|
pulumi-aws>=6.0.2,<7.0.0
|
Loading…
Reference in New Issue
Block a user