Skip to content

Commit b8d29d4

Browse files
author
Hoseong-Seo
committed
ECS and SBT stack dependencies delete
1 parent 9d35fc7 commit b8d29d4

31 files changed

+1187
-787
lines changed

client/AdminWeb/src/app/views/tenants/create/create.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
required
1313
/>
1414
<mat-error *ngIf="tenantName?.invalid">Name is required</mat-error>
15+
<mat-error *ngIf="tenantName?.errors?.['lowercaseAndNumbers']">Must start with a lowercase, and only lowercase, numbers, and hyphen</mat-error>
1516
</mat-form-field>
1617
<mat-form-field>
1718
<mat-label>Enter email</mat-label>

client/AdminWeb/src/app/views/tenants/create/create.component.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, OnInit } from '@angular/core';
2-
import { FormControl, FormGroup, Validators } from '@angular/forms';
2+
import { FormControl, FormGroup, Validators, ValidatorFn, ValidationErrors, AbstractControl } from '@angular/forms';
33
import { Router } from '@angular/router';
44
import { TenantsService } from '../tenants.service';
55
import { v4 as guid } from 'uuid';
@@ -12,8 +12,8 @@ import { v4 as guid } from 'uuid';
1212
export class CreateComponent implements OnInit {
1313
submitting = false;
1414
tenantForm = new FormGroup({
15-
tenantName: new FormControl('', [Validators.required]),
16-
email: new FormControl('', [Validators.required]),
15+
tenantName: new FormControl('', [Validators.required, this.lowercaseAndNumberValidator() ]),
16+
email: new FormControl('', [Validators.email, Validators.required]),
1717
tier: new FormControl('', [Validators.required]),
1818
});
1919
constructor(
@@ -43,6 +43,16 @@ export class CreateComponent implements OnInit {
4343
});
4444
}
4545

46+
lowercaseAndNumberValidator(): ValidatorFn {
47+
return (control: AbstractControl): ValidationErrors | null => {
48+
const value = control.value;
49+
if (value && !/^[a-z][a-z0-9-]*$/.test(value)) {
50+
return { lowercaseAndNumbers: 'Must start with a lowercase, and only lowercase, numbers, and hyphen' };
51+
}
52+
return null;
53+
}
54+
}
55+
4656
public get tenantName() {
4757
return this.tenantForm.get('tenantName');
4858
}

scripts/build-application.sh

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,62 @@
44

55
export DOCKER_DEFAULT_PLATFORM=linux/amd64
66

7-
service_repos=("user" "product" "order" "rproxy")
7+
SERVICE_REPOS=("user" "product" "order" "rproxy")
8+
# RPROXY_VERSIONS=("v1" "v2")
9+
10+
REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]')
11+
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
12+
13+
REGISTRY="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com"
14+
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin $REGISTRY
815

916
deploy_service () {
1017

1118
local SERVICE_NAME="$1"
19+
local VERSION="$2"
1220

1321
if [[ -z "$SERVICE_NAME" ]]; then
1422
echo "Please provide a SERVICE NAME"
1523
exit 1
1624
fi
1725

18-
local REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]')
19-
local ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
2026
local SERVICEECR="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/$SERVICE_NAME"
21-
22-
CWD=$(pwd)
23-
cd ../server/application
24-
local REGISTRY=$(echo $SERVICEECR| cut -d'/' -f 1)
25-
26-
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $REGISTRY
27+
# Docker Image Build
2728
docker build -t $SERVICEECR -f Dockerfile.$SERVICE_NAME .
28-
docker push $SERVICEECR:latest
29+
# Docker Image Tag
30+
docker tag "$SERVICEECR" "$SERVICEECR:$VERSION"
31+
# Docker Image Push to ECR
32+
docker push "$SERVICEECR:$VERSION"
2933

30-
cd $CWD
31-
echo '************************'
3234
echo '************************'
33-
echo ""
34-
echo "$SERVICE_NAME SERVICE_ECR_REPO:" $SERVICEECR
3535
echo "AWS_REGION:" $REGION
36+
echo "$SERVICE_NAME SERVICE_ECR_REPO: $SERVICEECR VERSION: $VERSION"
37+
3638

3739
}
3840

39-
##export service_repos;
40-
for repository in "${service_repos[@]}"
41-
do
42-
echo $repository
43-
aws ecr describe-repositories --repository-names "$repository" 2>/dev/null || echo "ECR Repository '$repository' does not exist. Creating..." &&
44-
aws ecr create-repository --repository-name "$repository"
45-
deploy_service $repository
41+
42+
CWD=$(pwd)
43+
cd ../server/application
44+
45+
for SERVICE in "${SERVICE_REPOS[@]}"; do
46+
echo "➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤➤"
47+
echo "Repository [$SERVICE] checking..."
48+
REPO_EXISTS=$(aws ecr describe-repositories --repository-names "$SERVICE" --query 'repositories[0].repositoryUri' --output text)
49+
echo "exist repo: $REPO_EXISTS"
50+
if [ "$REPO_EXISTS" == "${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/$SERVICE" ]; then
51+
echo "Repository [$SERVICE] already exists."
52+
else
53+
echo "Repository [$SERVICE] does not exist, creating it..."
54+
aws ecr create-repository --repository-name "$SERVICE" | cat
55+
echo "Repository [$SERVICE] created."
56+
fi
57+
58+
VERSION="latest"
59+
deploy_service $SERVICE $VERSION
4660
done
61+
62+
cd $CWD
63+
64+
# cloud9 SSM plugins to connect to the inside of Container
65+
# sudo dnf install -y https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm

scripts/cleanup.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,15 @@ for i in $(aws s3 ls | awk '{print $3}' | grep -E "^tenant-update-stack-*|^contr
152152
aws s3 rb --force "s3://${i}" #delete in stack
153153
done
154154

155+
#delete ecr repositories
156+
SERVICE_REPOS=("user" "product" "order" "rproxy")
157+
for SERVICE in "${SERVICE_REPOS[@]}"; do
158+
echo "Repository [$SERVICE] checking..."
159+
REPO_EXISTS=$(aws ecr describe-repositories --repository-names "$SERVICE" --query 'repositories[0].repositoryUri' --output text)
160+
if [ "$REPO_EXISTS" == "${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/$SERVICE" ]; then
161+
echo "Repository [$REPO_EXISTS] is deleting..."
162+
aws ecr delete-repository --repository-name "$SERVICE" --force | cat
163+
else
164+
echo "Repository [$SERVICE] does not exist"
165+
fi
166+
done

scripts/deprovision-tenant.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ sudo yum install -y npm
77
sudo npm install -g aws-cdk
88
sudo yum install -y jq
99
sudo yum install -y python3-pip
10-
sudo python3 -m pip install --upgrade setuptools
10+
sudo python3 -m pip install --upgrade --ignore-installed setuptools
1111

1212
# Enable nocasematch option
1313
shopt -s nocasematch
1414

15-
1615
# Parse tenant details from the input message from step function
1716
export CDK_PARAM_TENANT_ID=$tenantId
1817
export TIER=$tier

scripts/get-adv-network.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/bash
2+
3+
export IMAGE_NAME="$1"
4+
export TENANT="$2"
5+
6+
if [ "$#" -ne 2 ]; then
7+
echo "Usage: $0 <image-name> <tenant>"
8+
exit 1
9+
fi
10+
11+
SERVICE_NAME="${IMAGE_NAME}${TENANT}"
12+
13+
CLUSTER_NAME=$(aws ecs list-clusters --query 'clusterArns[*]' --output json | jq -r '.[] | select(contains("/prod-advanced-")) | split("/") | .[1]')
14+
15+
# Step 1: Get the Task ARN
16+
TASK_ARN=$(aws ecs list-tasks --cluster $CLUSTER_NAME --service-name $SERVICE_NAME --query 'taskArns[0]' --output text)
17+
TASK_ID=$(echo "$TASK_ARN" | awk -F'/' '{print $NF}' )
18+
# Check if TASK_ARN is empty
19+
if [ -z "$TASK_ARN" ]; then
20+
echo "No tasks found for service $SERVICE_NAME in cluster $CLUSTER_NAME"
21+
exit 1
22+
fi
23+
24+
export SECURITY_GROUP=$(aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME --query 'services[0].networkConfiguration.awsvpcConfiguration.securityGroups' --output text)
25+
26+
# Step 2: Get the ENI ID
27+
export PRIVATE_IP=$(aws ecs describe-tasks --cluster $CLUSTER_NAME --tasks $TASK_ARN --query 'tasks[0].attachments[?type==`ElasticNetworkInterface`][].details[?name==`privateIPv4Address`].value | [0]' --output text)
28+
29+
# Output the Private IP
30+
echo "CLUSTER_NAME : $CLUSTER_NAME"
31+
echo "TASK ID : $TASK_ID"
32+
echo "Security Group: $SECURITY_GROUP"
33+
echo "Private IP : $PRIVATE_IP"
34+
echo "curl http://$PRIVATE_IP:3010/${IMAGE_NAME}"

scripts/init-install.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash -e
2+
3+
export CDK_PARAM_SYSTEM_ADMIN_EMAIL="dummy"
4+
5+
export REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]') # Region setting
6+
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
7+
8+
# Create S3 Bucket for provision source.
9+
source ./update-provision-source.sh
10+
11+
echo "CDK_PARAM_COMMIT_ID exists: $CDK_PARAM_COMMIT_ID"
12+
13+
# Create ECS service linked role.
14+
ECS_ROLE=$(aws iam list-roles --query 'Roles[?contains(RoleName, `AWSServiceRoleForECS`)].Arn' --output text)
15+
if [ -z "$ECS_ROLE" ]; then
16+
aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com | cat
17+
else
18+
echo "ECS Service linked role exists: $ECS_ROLE"
19+
fi
20+
# Preprovision basic infrastructure
21+
cd ../server
22+
23+
sed "s/<REGION>/$REGION/g; s/<ACCOUNT_ID>/$ACCOUNT_ID/g" ./service-info.txt > ./lib/service-info.json
24+
25+
# npx cdk bootstrap
26+
export CDK_PARAM_ONBOARDING_DETAIL_TYPE='Onboarding'
27+
export CDK_PARAM_PROVISIONING_DETAIL_TYPE=$CDK_PARAM_ONBOARDING_DETAIL_TYPE
28+
export CDK_PARAM_OFFBOARDING_DETAIL_TYPE='Offboarding'
29+
export CDK_PARAM_DEPROVISIONING_DETAIL_TYPE=$CDK_PARAM_OFFBOARDING_DETAIL_TYPE
30+
export CDK_PARAM_TIER='basic'
31+
export CDK_PARAM_STAGE='prod'
32+
export CDK_ADV_CLUSTER='INACTIV'
33+
export CDK_BASIC_CLUSTER="$CDK_PARAM_STAGE-$CDK_PARAM_TIER"
34+
35+
npm install
36+
npx cdk bootstrap
37+
38+
SERVICES=$(aws ecs list-services --cluster $CDK_BASIC_CLUSTER --query 'serviceArns[*]' --output text || true)
39+
for SERVICE in $SERVICES; do
40+
SERVICE_NAME=$(echo $SERVICE | rev | cut -d '/' -f 1 | rev)
41+
echo -n "==== Service Connect re-set if any... "
42+
aws ecs update-service \
43+
--cluster $CDK_BASIC_CLUSTER \
44+
--service $SERVICE_NAME \
45+
--service-connect-configuration 'enabled=false' \
46+
--no-cli-pager --query 'service.serviceArn' --output text
47+
done
48+
49+
# npx cdk deploy shared-infra-stack --require-approval=never
50+
npx cdk deploy \
51+
tenant-template-stack-basic \
52+
tenant-template-stack-advanced --require-approval=never

scripts/install.sh

Lines changed: 24 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/bin/bash -e
22

33
export CDK_PARAM_SYSTEM_ADMIN_EMAIL="$1"
44

@@ -7,62 +7,26 @@ if [[ -z "$CDK_PARAM_SYSTEM_ADMIN_EMAIL" ]]; then
77
exit 1
88
fi
99

10-
REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]') # Region setting
11-
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
12-
13-
export CDK_PARAM_S3_BUCKET_NAME="saas-reference-architecture-ecs-$ACCOUNT_ID-$REGION"
10+
export REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]') # Region setting
11+
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
1412

1513
# Create S3 Bucket for provision source.
14+
source ./update-provision-source.sh
1615

17-
if aws s3api head-bucket --bucket $CDK_PARAM_S3_BUCKET_NAME 2>/dev/null; then
18-
echo "Bucket $CDK_PARAM_S3_BUCKET_NAME already exists."
19-
else
20-
echo "Bucket $CDK_PARAM_S3_BUCKET_NAME does not exist. Creating a new bucket in $REGION region in $ACCOUNT_ID"
21-
22-
if [ "$REGION" == "us-east-1" ]; then
23-
aws s3api create-bucket --bucket $CDK_PARAM_S3_BUCKET_NAME
24-
else
25-
aws s3api create-bucket \
26-
--bucket $CDK_PARAM_S3_BUCKET_NAME \
27-
--region "$REGION" \
28-
--create-bucket-configuration LocationConstraint="$REGION"
29-
fi
30-
31-
aws s3api put-bucket-versioning \
32-
--bucket $CDK_PARAM_S3_BUCKET_NAME \
33-
--versioning-configuration Status=Enabled
34-
35-
aws s3api put-public-access-block \
36-
--bucket $CDK_PARAM_S3_BUCKET_NAME \
37-
--public-access-block-configuration \
38-
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
39-
40-
if [ $? -eq 0 ]; then
41-
echo "Bucket $CDK_PARAM_S3_BUCKET_NAME created with versioning enabled."
42-
else
43-
echo "Error creating bucket $CDK_PARAM_S3_BUCKET_NAME with versioning enabled."
44-
exit 1
45-
fi
46-
fi
47-
48-
echo "Bucket exists: $CDK_PARAM_S3_BUCKET_NAME"
49-
50-
cd ../
51-
zip -rq source.zip . -x ".git/*" -x "**/node_modules/*" -x "**/cdk.out/*" -x "**/.aws-sam/*"
52-
export CDK_PARAM_COMMIT_ID=$(aws s3api put-object --bucket "${CDK_PARAM_S3_BUCKET_NAME}" --key "source.zip" --body "./source.zip" --output text)
53-
54-
rm source.zip
55-
echo "Source code uploaded to S3"
16+
echo "CDK_PARAM_COMMIT_ID exists: $CDK_PARAM_COMMIT_ID"
5617

5718
# Create ECS service linked role.
58-
aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com 2>/dev/null || echo "ECS Service linked role exists"
59-
19+
ECS_ROLE=$(aws iam list-roles --query 'Roles[?contains(RoleName, `AWSServiceRoleForECS`)].Arn' --output text)
20+
if [ -z "$ECS_ROLE" ]; then
21+
aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com | cat
22+
else
23+
echo "ECS Service linked role exists: $ECS_ROLE"
24+
fi
6025
# Preprovision basic infrastructure
61-
cd ./server
26+
cd ../server
27+
28+
sed "s/<REGION>/$REGION/g; s/<ACCOUNT_ID>/$ACCOUNT_ID/g" ./service-info.txt > ./lib/service-info.json
6229

63-
export ECR_REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]')
64-
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
65-
sed "s/<REGION>/$ECR_REGION/g; s/<ACCOUNT_ID>/$ACCOUNT_ID/g" ./service-info.txt > ./lib/service-info.json
6630
# npx cdk bootstrap
6731
export CDK_PARAM_ONBOARDING_DETAIL_TYPE='Onboarding'
6832
export CDK_PARAM_PROVISIONING_DETAIL_TYPE=$CDK_PARAM_ONBOARDING_DETAIL_TYPE
@@ -76,31 +40,15 @@ export CDK_BASIC_CLUSTER="$CDK_PARAM_STAGE-$CDK_PARAM_TIER"
7640
npm install
7741
npx cdk bootstrap
7842

79-
npx cdk diff tenant-template-stack-basic > ./diff_output.txt 2>&1
80-
if grep -q "There were no differences" ./diff_output.txt; then
81-
echo "No changes detected in tenant-template-stack-basic."
82-
else
83-
echo "Changes detected in tenant-template-stack-basic."
84-
85-
SERVICES=$(aws ecs list-services --cluster $CDK_BASIC_CLUSTER --query 'serviceArns[*]' --output text || true)
86-
for SERVICE in $SERVICES; do
87-
SERVICE_NAME=$(echo $SERVICE | rev | cut -d '/' -f 1 | rev)
88-
89-
echo -n "==== Service Connect Disable: "
90-
aws ecs update-service \
91-
--cluster $CDK_BASIC_CLUSTER \
92-
--service $SERVICE_NAME \
93-
--service-connect-configuration 'enabled=false' \
94-
--no-cli-pager --query 'service.serviceArn' --output text
95-
done
96-
fi
97-
rm diff_output.txt
43+
SERVICES=$(aws ecs list-services --cluster $CDK_BASIC_CLUSTER --query 'serviceArns[*]' --output text || true)
44+
for SERVICE in $SERVICES; do
45+
SERVICE_NAME=$(echo $SERVICE | rev | cut -d '/' -f 1 | rev)
46+
echo -n "==== Service Connect re-set if any... "
47+
aws ecs update-service \
48+
--cluster $CDK_BASIC_CLUSTER \
49+
--service $SERVICE_NAME \
50+
--service-connect-configuration 'enabled=false' \
51+
--no-cli-pager --query 'service.serviceArn' --output text
52+
done
9853

9954
npx cdk deploy --all --require-approval=never
100-
101-
102-
## Get SaaS application url
103-
ADMIN_SITE_URL=$(aws cloudformation describe-stacks --stack-name controlplane-stack --query "Stacks[0].Outputs[?OutputKey=='adminSiteUrl'].OutputValue" --output text)
104-
APP_SITE_URL=$(aws cloudformation describe-stacks --stack-name core-appplane-stack --query "Stacks[0].Outputs[?OutputKey=='appSiteUrl'].OutputValue" --output text)
105-
echo "Admin site url: $ADMIN_SITE_URL"
106-
echo "Application site url: $APP_SITE_URL"

0 commit comments

Comments
 (0)