Skip to content

Commit 7ab6a2e

Browse files
committed
feat: add destroy.sh script with environment-specific configuration support
- Add destroy.sh script to safely delete GenU stacks - Support same parameters as deploy.sh (-c, -p, -e, -y) - Auto-detect environment from deployed stack name - Extract and update parameter.ts with stack configuration - Filter out inferenceProfileArn from model configurations - List all stacks before deletion with cdk ls - Add confirmation prompt (skippable with -y flag) - Add documentation in English, Japanese, and Korean
1 parent d789a77 commit 7ab6a2e

File tree

5 files changed

+517
-0
lines changed

5 files changed

+517
-0
lines changed

destroy.sh

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Set Node.js memory limit
6+
export NODE_OPTIONS="--max-old-space-size=1024"
7+
8+
echo "----------------------------"
9+
echo " _____ _ _ "
10+
echo " / ____| | | | | "
11+
echo "| | __ ___ _ __ | | | | "
12+
echo "| | |_ |/ _ \ '_ \| | | | "
13+
echo "| |__| | __/ | | | |__| | "
14+
echo " \_____|\___|_| |_|\____/ "
15+
echo " DESTROY STACKS "
16+
echo "----------------------------"
17+
18+
# Process command arguments
19+
while [[ $# -gt 0 ]]; do
20+
case "$1" in
21+
-c|--cdk-context)
22+
cdk_context_path="$2"
23+
shift 2
24+
;;
25+
-p|--parameter-file)
26+
parameter_file_path="$2"
27+
shift 2
28+
;;
29+
-e|--env)
30+
env_name="$2"
31+
shift 2
32+
;;
33+
-y|--yes)
34+
skip_confirmation=true
35+
shift
36+
;;
37+
-h|--help)
38+
echo "-c, --cdk-context ... Path to the cdk.json file"
39+
echo "-p, --parameter-file ... Path to the parameter.ts file"
40+
echo "-e, --env ... Environment name (e.g., dev, prod)"
41+
echo "-y, --yes ... Skip confirmation prompt"
42+
echo "-h, --help ... Show this message"
43+
exit 0
44+
;;
45+
*)
46+
echo "Unknown option: $1"
47+
exit 1
48+
;;
49+
esac
50+
done
51+
52+
# Check if the file exists
53+
if [[ -n "$cdk_context_path" && ! -f "$cdk_context_path" ]]; then
54+
echo "Error: CDK context file not found: $cdk_context_path"
55+
exit 1
56+
fi
57+
58+
if [[ -n "$parameter_file_path" && ! -f "$parameter_file_path" ]]; then
59+
echo "Error: Parameter file not found: $parameter_file_path"
60+
exit 1
61+
fi
62+
63+
pushd /tmp
64+
65+
# Delete the repository in /tmp if it exists
66+
rm -rf generative-ai-use-cases
67+
68+
# Clone GenU
69+
git clone https://github.com/aws-samples/generative-ai-use-cases
70+
71+
pushd generative-ai-use-cases
72+
73+
# Install npm packages
74+
npm ci
75+
76+
# If cdk.json is specified, use it
77+
if [[ -n "$cdk_context_path" ]]; then
78+
echo "Using provided cdk.json from $cdk_context_path"
79+
cp -f $cdk_context_path packages/cdk/cdk.json
80+
fi
81+
82+
# If parameter.ts is specified, use it
83+
if [[ -n "$parameter_file_path" ]]; then
84+
echo "Using provided parameter.ts from $parameter_file_path"
85+
cp -f $parameter_file_path packages/cdk/parameter.ts
86+
fi
87+
88+
# Determine environment name if not specified
89+
if [[ -z "$env_name" ]]; then
90+
# Try to infer from deployed stack
91+
STACK_NAME=$(aws cloudformation list-stacks \
92+
--stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE \
93+
--query 'StackSummaries[?starts_with(StackName, `GenerativeAiUseCasesStack`)].StackName' \
94+
--output text | head -1)
95+
96+
if [[ -n "$STACK_NAME" ]]; then
97+
env_name="${STACK_NAME#GenerativeAiUseCasesStack}"
98+
echo "Detected environment from stack: ${env_name:-default}"
99+
fi
100+
fi
101+
102+
# If environment is specified, update parameter.ts
103+
if [[ -n "$env_name" && -z "$parameter_file_path" ]]; then
104+
echo "Using parameter.ts for environment: $env_name"
105+
106+
# Get stack outputs to populate parameter.ts
107+
STACK_NAME="GenerativeAiUseCasesStack${env_name}"
108+
109+
if aws cloudformation describe-stacks --stack-name "$STACK_NAME" &>/dev/null; then
110+
echo "Extracting configuration from stack: $STACK_NAME"
111+
112+
# Helper function to extract CloudFormation output values
113+
function extract_value {
114+
echo $1 | jq -r ".Stacks[0].Outputs[] | select(.OutputKey==\"$2\") | .OutputValue"
115+
}
116+
117+
# Get stack outputs
118+
stack_output=$(aws cloudformation describe-stacks --stack-name "$STACK_NAME" --output json)
119+
120+
# Extract all configuration values
121+
MODEL_REGION=$(extract_value "$stack_output" ModelRegion)
122+
MODEL_IDS=$(extract_value "$stack_output" ModelIds)
123+
IMAGE_MODEL_IDS=$(extract_value "$stack_output" ImageGenerateModelIds)
124+
VIDEO_MODEL_IDS=$(extract_value "$stack_output" VideoGenerateModelIds)
125+
SPEECH_MODEL_IDS=$(extract_value "$stack_output" SpeechToSpeechModelIds)
126+
ENDPOINT_NAMES=$(extract_value "$stack_output" EndpointNames)
127+
RAG_ENABLED=$(extract_value "$stack_output" RagEnabled)
128+
RAG_KB_ENABLED=$(extract_value "$stack_output" RagKnowledgeBaseEnabled)
129+
AGENT_ENABLED=$(extract_value "$stack_output" AgentEnabled)
130+
SELF_SIGNUP=$(extract_value "$stack_output" SelfSignUpEnabled)
131+
SAML_ENABLED=$(extract_value "$stack_output" SamlAuthEnabled)
132+
SAML_DOMAIN=$(extract_value "$stack_output" SamlCognitoDomainName)
133+
SAML_PROVIDER=$(extract_value "$stack_output" SamlCognitoFederatedIdentityProviderName)
134+
AGENTS=$(extract_value "$stack_output" Agents | base64 -d 2>/dev/null || echo "[]")
135+
INLINE_AGENTS=$(extract_value "$stack_output" InlineAgents)
136+
USE_CASE_BUILDER=$(extract_value "$stack_output" UseCaseBuilderEnabled)
137+
HIDDEN_USE_CASES=$(extract_value "$stack_output" HiddenUseCases)
138+
FLOWS=$(extract_value "$stack_output" Flows | base64 -d 2>/dev/null || echo "[]")
139+
MCP_ENABLED=$(extract_value "$stack_output" McpEnabled)
140+
AGENT_CORE_ENABLED=$(extract_value "$stack_output" AgentCoreEnabled)
141+
AGENT_BUILDER_ENABLED=$(extract_value "$stack_output" AgentCoreAgentBuilderEnabled)
142+
AGENT_CORE_EXTERNAL=$(extract_value "$stack_output" AgentCoreExternalRuntimes)
143+
144+
# Update parameter.ts
145+
export env_name MODEL_REGION MODEL_IDS IMAGE_MODEL_IDS VIDEO_MODEL_IDS SPEECH_MODEL_IDS ENDPOINT_NAMES
146+
export RAG_ENABLED RAG_KB_ENABLED AGENT_ENABLED SELF_SIGNUP SAML_ENABLED SAML_DOMAIN SAML_PROVIDER
147+
export AGENTS INLINE_AGENTS FLOWS MCP_ENABLED USE_CASE_BUILDER HIDDEN_USE_CASES
148+
export AGENT_CORE_ENABLED AGENT_BUILDER_ENABLED AGENT_CORE_EXTERNAL
149+
150+
node <<'NODESCRIPT'
151+
const fs = require('fs');
152+
let content = fs.readFileSync('packages/cdk/parameter.ts', 'utf8');
153+
154+
const filterInferenceProfileArn = (models) => {
155+
return models.map(({ inferenceProfileArn, ...rest }) => rest);
156+
};
157+
158+
const envParams = {
159+
modelRegion: process.env.MODEL_REGION,
160+
modelIds: filterInferenceProfileArn(JSON.parse(process.env.MODEL_IDS)),
161+
imageGenerationModelIds: filterInferenceProfileArn(JSON.parse(process.env.IMAGE_MODEL_IDS)),
162+
videoGenerationModelIds: filterInferenceProfileArn(JSON.parse(process.env.VIDEO_MODEL_IDS)),
163+
speechToSpeechModelIds: filterInferenceProfileArn(JSON.parse(process.env.SPEECH_MODEL_IDS)),
164+
endpointNames: filterInferenceProfileArn(JSON.parse(process.env.ENDPOINT_NAMES)),
165+
ragEnabled: process.env.RAG_ENABLED === 'true',
166+
ragKnowledgeBaseEnabled: process.env.RAG_KB_ENABLED === 'true',
167+
agentEnabled: process.env.AGENT_ENABLED === 'true',
168+
selfSignUpEnabled: process.env.SELF_SIGNUP === 'true',
169+
samlAuthEnabled: process.env.SAML_ENABLED === 'true',
170+
samlCognitoDomainName: process.env.SAML_DOMAIN,
171+
samlCognitoFederatedIdentityProviderName: process.env.SAML_PROVIDER,
172+
agents: JSON.parse(process.env.AGENTS),
173+
inlineAgents: process.env.INLINE_AGENTS === 'true',
174+
flows: JSON.parse(process.env.FLOWS),
175+
mcpEnabled: process.env.MCP_ENABLED === 'true',
176+
useCaseBuilderEnabled: process.env.USE_CASE_BUILDER === 'true',
177+
hiddenUseCases: JSON.parse(process.env.HIDDEN_USE_CASES),
178+
createGenericAgentCoreRuntime: process.env.AGENT_CORE_ENABLED === 'true',
179+
agentBuilderEnabled: process.env.AGENT_BUILDER_ENABLED === 'true',
180+
agentCoreExternalRuntimes: JSON.parse(process.env.AGENT_CORE_EXTERNAL)
181+
};
182+
183+
const envParamsStr = JSON.stringify(envParams, null, 2);
184+
const regex = new RegExp(`${process.env.env_name}:\\s*\\{[\\s\\S]*?\\n \\}`, 'm');
185+
content = content.replace(regex, `${process.env.env_name}: ${envParamsStr}`);
186+
187+
fs.writeFileSync('packages/cdk/parameter.ts', content);
188+
NODESCRIPT
189+
190+
echo "Updated parameter.ts with stack configuration"
191+
fi
192+
fi
193+
194+
# List target stacks
195+
echo ""
196+
echo "Target stacks to be deleted:"
197+
if [[ -n "$env_name" ]]; then
198+
npx -w packages/cdk cdk ls -c env="$env_name"
199+
else
200+
npx -w packages/cdk cdk ls
201+
fi
202+
echo ""
203+
204+
# Confirmation prompt
205+
if [[ "$skip_confirmation" != true ]]; then
206+
echo "WARNING: This will permanently delete all GenU stacks and resources."
207+
if [[ -n "$env_name" ]]; then
208+
echo "Environment: $env_name"
209+
else
210+
echo "Environment: default"
211+
fi
212+
echo "This action cannot be undone."
213+
echo ""
214+
read -p "Are you sure you want to continue? (yes/no): " confirmation
215+
216+
if [[ "$confirmation" != "yes" ]]; then
217+
echo "Destroy operation cancelled."
218+
exit 0
219+
fi
220+
fi
221+
222+
# Build destroy command
223+
destroy_cmd="npm run cdk:destroy -- --force"
224+
225+
# Pass environment via context flag if specified
226+
if [[ -n "$env_name" ]]; then
227+
destroy_cmd="$destroy_cmd -c env=$env_name"
228+
fi
229+
230+
# Execute destroy
231+
$destroy_cmd
232+
233+
echo "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
234+
echo "GenU has been successfully destroyed"
235+
echo "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"

docs/en/DESTROY_ON_CLOUDSHELL.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Destroy Method Using AWS CloudShell (When It's Difficult to Prepare Your Own Environment)
2+
3+
## Overview
4+
5+
Even if you don't have the configuration files used during GenU deployment, you can automatically restore the configuration from the deployed CloudFormation stack and destroy it.
6+
7+
## Launch CloudShell
8+
9+
Launch [CloudShell](https://console.aws.amazon.com/cloudshell/home).
10+
11+
If you have the `cdk.json` or `parameter.ts` used during deployment, select "Upload file" from the "Actions" dropdown list at the top right of the CloudShell terminal to upload the files.
12+
13+
## Download `destroy.sh` and Grant Execution Permission
14+
15+
Execute the following commands in CloudShell to download the `destroy.sh` script.
16+
After downloading, grant execution permission to `destroy.sh`.
17+
18+
```bash
19+
wget https://raw.githubusercontent.com/aws-samples/generative-ai-use-cases/refs/heads/main/destroy.sh -O destroy.sh
20+
chmod +x destroy.sh
21+
```
22+
23+
## Execute `destroy.sh`
24+
25+
`destroy.sh` supports the following options.
26+
27+
```bash
28+
-c, --cdk-context ... Path to the cdk.json file
29+
-p, --parameter-file ... Path to the parameter.ts file
30+
-e, --env ... Environment name (e.g., dev, prod)
31+
-y, --yes ... Skip confirmation prompt
32+
-h, --help ... Show this message
33+
```
34+
35+
If `cdk.json` or `parameter.ts` is not specified, parameters will be estimated from the deployed GenU-related stacks and `cdk.json` will be created. The parameter estimation method follows `setup-env.sh` and estimates through the following steps:
36+
37+
1. Search for deployed `GenerativeAiUseCasesStack*`
38+
2. Retrieve configuration information from CloudFormation outputs
39+
3. Automatically generate minimal cdk.json
40+
4. Destroy all related stacks
41+
42+
### Destroy Examples
43+
44+
Execute destroy.sh with the following commands.
45+
46+
#### 1. Auto-detect and Destroy
47+
48+
Automatically restores configuration from the deployed stack and destroys it. Use this method if you don't have configuration files.
49+
50+
```bash
51+
./destroy.sh
52+
```
53+
54+
If you have separate environments, set `--env`:
55+
56+
```bash
57+
./destroy.sh --env dev
58+
```
59+
60+
A confirmation prompt will be displayed. Enter `yes` to execute the destruction. If you want to skip confirmation and execute, run as follows:
61+
62+
```bash
63+
./destroy.sh --env dev --yes
64+
```
65+
66+
#### 2. Destroy Using Customized cdk.json
67+
68+
If you have the cdk.json used during deployment:
69+
70+
```bash
71+
./destroy.sh --cdk-context ~/cdk.json
72+
```
73+
74+
#### 3. Destroy Using Customized parameter.ts
75+
76+
If you have the parameter.ts used during deployment:
77+
78+
```bash
79+
./destroy.sh --parameter-file ~/parameter.ts
80+
```
81+
82+
#### 4. Destroy with parameter.ts and Environment Specification
83+
84+
```bash
85+
./destroy.sh --parameter-file ~/parameter.ts --env prod
86+
```
87+
88+
### Important Notes
89+
90+
- Destroy operations cannot be undone
91+
- A confirmation prompt is always displayed before destruction (unless using the `--yes` option)
92+
- All related resources (S3 buckets, DynamoDB tables, Lambda functions, etc.) will be deleted
93+
- If you need data backups, please obtain them before destruction

0 commit comments

Comments
 (0)