Skip to content

Commit 6bbc2d5

Browse files
authored
Merge pull request #37 from UCEAP/aws
Terraform AWS
2 parents 1507a8f + 60379e7 commit 6bbc2d5

33 files changed

+2955
-469
lines changed

.devcontainer/onCreate.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://
1616
sudo apt update
1717
sudo apt-get install -y terraform
1818

19-
# Install Azure CLI
19+
# Install AWS CLI
2020
# TODO move this into base image
21-
sudo apt-get install -y azure-cli
21+
sudo apt-get install -y awscli

.github/workflows/build_deploy_and_test.yml

Lines changed: 47 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -69,76 +69,32 @@ jobs:
6969
build_for_aws:
7070
name: Build for AWS
7171
runs-on: ubuntu-latest
72-
if: false
73-
permissions:
74-
contents: read
75-
packages: write
76-
steps:
77-
- uses: actions/checkout@v4
78-
- name: Set up Docker Buildx
79-
uses: docker/setup-buildx-action@v3
80-
- name: Log in to GitHub container registry
81-
uses: docker/login-action@v3
82-
with:
83-
registry: ghcr.io
84-
username: ${{ github.actor }}
85-
password: ${{ github.token }}
86-
- name: Lowercase the repo name and username
87-
run: echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
88-
- name: Build and push container image to registry
89-
uses: docker/build-push-action@v6
90-
with:
91-
push: true
92-
tags: |
93-
ghcr.io/${{ env.REPO }}-aws:${{ github.sha }}
94-
ghcr.io/${{ env.REPO }}-aws:latest
95-
file: ./Dockerfile
96-
build-args: |
97-
MYSQL_HOST=${{ vars.AWS_MYSQL_HOST }}
98-
MYSQL_TCP_PORT=${{ vars.AWS_MYSQL_TCP_PORT }}
99-
MYSQL_USER=${{ vars.AWS_MYSQL_USER }}
100-
MYSQL_PASSWORD=${{ secrets.AWS_MYSQL_PASSWORD }}
101-
MYSQL_DATABASE=${{ vars.AWS_MYSQL_DATABASE }}
102-
REDIS_HOST=${{ vars.AWS_REDIS_HOST }}
103-
REDIS_AUTH=${{ secrets.AWS_REDIS_AUTH }}
104-
HASH_SALT=${{ secrets.AWS_HASH_SALT }}
105-
106-
build_for_azure:
107-
name: Build for Azure
108-
runs-on: ubuntu-latest
10972
if: github.ref_name == 'main'
11073
permissions:
11174
contents: read
112-
packages: write
75+
id-token: write
11376
steps:
11477
- uses: actions/checkout@v4
11578
- name: Set up Docker Buildx
11679
uses: docker/setup-buildx-action@v3
117-
- name: Log in to GitHub container registry
118-
uses: docker/login-action@v3
80+
- name: Configure AWS credentials
81+
uses: aws-actions/configure-aws-credentials@v4
82+
with:
83+
aws-access-key-id: ${{ vars.AWS_ACCESS_KEY_ID }}
84+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
85+
aws-region: ${{ vars.AWS_REGION }}
86+
- name: Log in to Amazon ECR
87+
uses: aws-actions/amazon-ecr-login@v2
11988
with:
120-
registry: ghcr.io
121-
username: ${{ github.actor }}
122-
password: ${{ github.token }}
123-
- name: Lowercase the repo name and username
124-
run: echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
125-
- name: Build and push container image to registry
89+
mask-password: 'true'
90+
- name: Build and push container image to ECR
12691
uses: docker/build-push-action@v6
12792
with:
12893
push: true
12994
tags: |
130-
ghcr.io/${{ env.REPO }}-azure:${{ github.sha }}
131-
ghcr.io/${{ env.REPO }}-azure:latest
95+
${{ vars.ECR_REPOSITORY_URL }}:${{ github.sha }}
96+
${{ vars.ECR_REPOSITORY_URL }}:latest
13297
file: ./Dockerfile
133-
build-args: |
134-
MYSQL_HOST=${{ vars.AZURE_MYSQL_HOST }}
135-
MYSQL_TCP_PORT=${{ vars.AZURE_MYSQL_TCP_PORT }}
136-
MYSQL_USER=${{ vars.AZURE_MYSQL_USER }}
137-
MYSQL_PASSWORD=${{ secrets.AZURE_MYSQL_PASSWORD }}
138-
MYSQL_DATABASE=${{ vars.AZURE_MYSQL_DATABASE }}
139-
REDIS_HOST=${{ vars.AZURE_REDIS_HOST }}
140-
REDIS_AUTH=${{ secrets.AZURE_REDIS_AUTH }}
141-
HASH_SALT=${{ secrets.AZURE_HASH_SALT }}
14298

14399
lint:
144100
name: Check lint
@@ -312,36 +268,43 @@ jobs:
312268
if: github.ref_name == 'main'
313269
runs-on: ubuntu-latest
314270
needs: [build_for_aws]
271+
permissions:
272+
contents: read
315273
steps:
316-
- name: Deploy to AWS
317-
run: echo "Hello, world!"
318-
319-
deploy_to_azure:
320-
name: Deploy to Azure
321-
if: github.ref_name == 'main'
322-
runs-on: ubuntu-latest
323-
needs: [build_for_azure]
324-
environment:
325-
name: 'Development'
326-
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
327-
steps:
328-
- name: Lowercase the repo name and username
329-
run: echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
330-
- name: Deploy to Azure Web App
331-
id: deploy-to-webapp
332-
uses: azure/webapps-deploy@v2
274+
- name: Configure AWS credentials
275+
uses: aws-actions/configure-aws-credentials@v4
333276
with:
334-
app-name: ${{ env.AZURE_WEBAPP_NAME }}
335-
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
336-
images: 'ghcr.io/${{ env.REPO }}-azure:${{ github.sha }}'
337-
- name: Drush deploy
277+
aws-access-key-id: ${{ vars.AWS_ACCESS_KEY_ID }}
278+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
279+
aws-region: ${{ vars.AWS_REGION }}
280+
- name: Update ECS service with new image
338281
run: |
339-
az webapp create-remote-connection \
340-
--resource-group drupal-example-stirred-dove \
341-
--name drupal-example-precious-seasnail \
342-
--port 16385 &
343-
sleep 30
344-
sshpass -pDocker\! ssh root@127.0.0.1 -m hmac-sha1 -p 16385 -o "StrictHostKeyChecking no" /var/www/vendor/bin/drush deploy
282+
# Get the current task definition
283+
TASK_DEF=$(aws ecs describe-task-definition \
284+
--task-definition ${{ vars.AWS_ECS_TASK_DEFINITION }} \
285+
--region ${{ vars.AWS_REGION }} \
286+
--query 'taskDefinition' --output json)
287+
288+
# Update the image in the task definition
289+
NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
290+
--arg IMAGE "${{ vars.ECR_REPOSITORY_URL }}:${{ github.sha }}" \
291+
'.containerDefinitions[0].image = $IMAGE |
292+
del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy)')
293+
294+
# Register the new task definition
295+
NEW_TASK_DEF_ARN=$(aws ecs register-task-definition \
296+
--region ${{ vars.AWS_REGION }} \
297+
--cli-input-json "$(echo "$NEW_TASK_DEF" | jq -c .)" \
298+
--query 'taskDefinition.taskDefinitionArn' \
299+
--output text)
300+
301+
# Update the ECS service to use the new task definition
302+
aws ecs update-service \
303+
--cluster ${{ vars.AWS_ECS_CLUSTER }} \
304+
--service ${{ vars.AWS_ECS_SERVICE }} \
305+
--task-definition "$NEW_TASK_DEF_ARN" \
306+
--region ${{ vars.AWS_REGION }} \
307+
--force-new-deployment
345308
346309
e2e_test:
347310
name: Feature tests

Dockerfile

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# check=skip=SecretsUsedInArgOrEnv
2-
31
FROM ghcr.io/uceap/devcontainer-drupal:v2.3.0
42

53
# Install SSH server
@@ -12,23 +10,13 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
1210
COPY docker-uceap-entrypoint /usr/local/bin/docker-uceap-entrypoint
1311
ENTRYPOINT ["docker-uceap-entrypoint"]
1412

15-
ARG MYSQL_HOST
16-
ARG MYSQL_TCP_PORT
17-
ARG MYSQL_USER
18-
ARG MYSQL_PASSWORD
19-
ARG MYSQL_DATABASE
20-
ARG REDIS_HOST
21-
ARG REDIS_AUTH
22-
ARG HASH_SALT
23-
2413
COPY build /var/www/build
2514
COPY config /var/www/config
2615
COPY composer.json /var/www/
2716
COPY web /var/www/web
2817

2918
WORKDIR /var/www
3019

31-
RUN composer initialize-container && \
32-
composer install --no-dev --no-interaction --no-progress --optimize-autoloader && \
20+
RUN composer install --no-dev --no-interaction --no-progress --optimize-autoloader && \
3321
sed -i 's-/var/www/html-/var/www/web-' /etc/apache2/sites-available/*.conf && \
3422
sed -i 's/# Listen\s*80$/Listen 80/' /etc/apache2/ports.conf

docker-uceap-entrypoint

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/bin/sh
22
set -e
33

4+
# Initialize Drupal container with runtime environment variables
5+
# This runs at container startup with secrets from AWS Secrets Manager
6+
cd /var/www && composer initialize-container
7+
48
service ssh start
59

610
exec apache2-foreground

terraform/.terraform.lock.hcl

Lines changed: 68 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

terraform/CIDR_ALLOCATION.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# CIDR Allocation Registry
2+
3+
## 10.0.0.0/8 - Internal Infrastructure Space
4+
5+
This document tracks IP address allocation for all internal applications and infrastructure.
6+
7+
## CIDR Block Allocation
8+
9+
| CIDR Block | Purpose | Status | Notes |
10+
|-----------------|----------------------------------|----------|-------|
11+
| 10.0.0.0/16 | Shared Services (Reserved) | Reserved | VPN, monitoring, shared infrastructure |
12+
| 10.1.0.0/16 - 10.100.0.0/16 | Additional shared infrastructure | Reserved | Future use |
13+
| 10.101.0.0/16 | drupal-example (app_number=101) | Active | Drupal CMS application |
14+
| 10.102.0.0/16 | (Next app, app_number=102) | Available | |
15+
| 10.103.0.0/16 | (Next app, app_number=103) | Available | |
16+
| ... | ... | Available | |
17+
| 10.254.0.0/16 | (Last app, app_number=254) | Available | |
18+
19+
## Application VPC Subnet Structure
20+
21+
Each application VPC uses a consistent internal structure for predictable IP allocation.
22+
23+
### Example: drupal-example (10.101.0.0/16)
24+
25+
| CIDR Block | Tier | AZ | Use Case | Hosts | Gateway |
26+
|-----------------|----------|--------|----------------|-------|---------|
27+
| 10.101.0.0/24 | Public | us-west-2a | ALB | ~254 | IGW |
28+
| 10.101.1.0/24 | Public | us-west-2b | ALB (HA) | ~254 | IGW |
29+
| 10.101.10.0/24 | Private | us-west-2a | ECS Tasks | ~254 | NAT-GW |
30+
| 10.101.11.0/24 | Private | us-west-2b | ECS Tasks (HA) | ~254 | NAT-GW |
31+
| 10.101.20.0/24 | Database | us-west-2a | RDS/Redis | ~254 | None |
32+
| 10.101.21.0/24 | Database | us-west-2b | RDS/Redis (HA) | ~254 | None |
33+
34+
### Template for New Apps
35+
36+
When deploying a new application, use this template with your assigned `app_number`:
37+
38+
| CIDR Block | Tier | AZ | Use Case |
39+
|---------------------|----------|--------|----------------|
40+
| 10.{app_number}.0.0/24 | Public | AZ1 | Load Balancer |
41+
| 10.{app_number}.1.0/24 | Public | AZ2 | Load Balancer |
42+
| 10.{app_number}.10.0/24 | Private | AZ1 | Application |
43+
| 10.{app_number}.11.0/24 | Private | AZ2 | Application |
44+
| 10.{app_number}.20.0/24 | Database | AZ1 | Data Layer |
45+
| 10.{app_number}.21.0/24 | Database | AZ2 | Data Layer |
46+
47+
## Network Tiers
48+
49+
### Public Tier (X.0.0/24, X.1.0/24)
50+
- Internet-facing resources (ALB, NAT gateways)
51+
- Ingress from internet allowed
52+
- Routed through Internet Gateway
53+
54+
### Private Tier (X.10.0/24, X.11.0/24)
55+
- Application compute (ECS tasks)
56+
- No direct internet access
57+
- Egress through NAT Gateway for outbound internet access
58+
- Ingress only from ALB
59+
60+
### Database Tier (X.20.0/24, X.21.0/24)
61+
- Data layer resources (RDS, ElastiCache)
62+
- No internet access
63+
- Ingress only from application tier
64+
- No outbound internet access
65+
66+
## Deployment Instructions
67+
68+
To deploy a new application with this convention:
69+
70+
1. **Assign an app_number**: Choose a number between 101-254 (update this registry first)
71+
2. **Update this registry**: Add the app and its status
72+
3. **Deploy with Terraform**:
73+
```bash
74+
terraform apply -var="app_number=101" # For drupal-example
75+
terraform apply -var="app_number=102" # For next app
76+
```
77+
78+
4. **Verify CIDR blocks** in AWS console match expected values
79+
80+
## Benefits
81+
82+
- **Predictable**: Each app's CIDR space is deterministic and easy to calculate
83+
- **Readable**: Simple numeric offsets (0, 1, 10, 11, 20, 21) are easy to remember
84+
- **Scalable**: Supports up to 154 applications
85+
- **Reserved**: Lower CIDR space (10.0-10.100) reserved for shared infrastructure
86+
- **Non-overlapping**: Each app completely isolated in its own /16

0 commit comments

Comments
 (0)