There are more AWS SDK examples available in the AWS Doc SDK Examples
Lambda examples using AWS CLI with Bash script
The following code examples show you how to perform actions and implement common scenarios by using the AWS Command Line Interface with Bash script with Lambda.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how to set up and run the code in context.
Topics
Scenarios
The following code example shows how to:
Create an IAM role for Lambda execution
Create and deploy a Lambda function
Create a REST API
Configure Lambda proxy integration
Deploy and test the API
Clean up resources
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash set -euo pipefail # Simple API Gateway Lambda Integration Script # This script creates a REST API with Lambda proxy integration # Generate random identifiers FUNCTION_NAME="GetStartedLambdaProxyIntegration-$(openssl rand -hex 4)" ROLE_NAME="GetStartedLambdaBasicExecutionRole-$(openssl rand -hex 4)" API_NAME="LambdaProxyAPI-$(openssl rand -hex 4)" # Get AWS account info ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) REGION=$(aws configure get region || echo "us-east-1") # Validate inputs if [[ -z "$ACCOUNT_ID" ]] || [[ -z "$REGION" ]]; then echo "Error: Failed to retrieve AWS account information" >&2 exit 1 fi echo "Creating Lambda function code..." # Create Lambda function code with input validation cat > lambda_function.py << 'EOF' import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): try: logger.info("Received event: %s", json.dumps(event)) greeter = 'World' # Safely retrieve greeter from query string parameters query_params = event.get('queryStringParameters') or {} if isinstance(query_params, dict) and 'greeter' in query_params: greeter_value = query_params.get('greeter') if isinstance(greeter_value, str) and greeter_value: greeter = greeter_value # Safely retrieve greeter from multi-value headers multi_headers = event.get('multiValueHeaders') or {} if isinstance(multi_headers, dict) and 'greeter' in multi_headers: greeter_list = multi_headers.get('greeter', []) if isinstance(greeter_list, list) and greeter_list: greeter = " and ".join(str(g) for g in greeter_list if g) # Safely retrieve greeter from headers headers = event.get('headers') or {} if isinstance(headers, dict) and 'greeter' in headers: greeter_value = headers.get('greeter') if isinstance(greeter_value, str) and greeter_value: greeter = greeter_value # Safely retrieve greeter from body body = event.get('body') if body and isinstance(body, str): try: body_dict = json.loads(body) if isinstance(body_dict, dict) and 'greeter' in body_dict: greeter_value = body_dict.get('greeter') if isinstance(greeter_value, str) and greeter_value: greeter = greeter_value except (json.JSONDecodeError, ValueError) as e: logger.warning("Failed to parse body: %s", str(e)) # Sanitize greeter to prevent injection greeter = greeter.replace('"', '\\"').replace("'", "\\'") response = { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": json.dumps({"message": f"Hello, {greeter}!"}) } logger.info("Response: %s", json.dumps(response)) return response except Exception as e: logger.error("Unexpected error: %s", str(e), exc_info=True) return { "statusCode": 500, "headers": { "Content-Type": "application/json" }, "body": json.dumps({"error": "Internal server error"}) } EOF # Create deployment package zip -q function.zip lambda_function.py || { echo "Error: Failed to create function.zip" >&2 exit 1 } echo "Creating IAM role..." # Create IAM trust policy cat > trust-policy.json << 'EOF' { "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF # Create IAM role with error handling aws iam create-role \ --role-name "$ROLE_NAME" \ --assume-role-policy-document file://trust-policy.json \ --description "Temporary role for Lambda execution" || { echo "Error: Failed to create IAM role" >&2 exit 1 } # Attach execution policy aws iam attach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" || { echo "Error: Failed to attach IAM policy" >&2 exit 1 } # Wait for role propagation sleep 15 echo "Creating Lambda function..." # Create Lambda function with Python 3.11 (more recent runtime) aws lambda create-function \ --function-name "$FUNCTION_NAME" \ --runtime python3.11 \ --role "arn:aws:iam::$ACCOUNT_ID:role/$ROLE_NAME" \ --handler lambda_function.lambda_handler \ --zip-file fileb://function.zip \ --timeout 30 \ --memory-size 128 \ --environment "Variables={LOG_LEVEL=INFO}" || { echo "Error: Failed to create Lambda function" >&2 exit 1 } echo "Creating API Gateway..." # Create REST API with minimum logging API_RESPONSE=$(aws apigateway create-rest-api \ --name "$API_NAME" \ --endpoint-configuration types=REGIONAL \ --description "API for Lambda proxy integration tutorial" \ --output json) API_ID=$(echo "$API_RESPONSE" | grep -o '"id": "[^"]*"' | head -1 | cut -d'"' -f4) if [[ -z "$API_ID" ]]; then echo "Error: Failed to create API Gateway" >&2 exit 1 fi # Get root resource ID ROOT_RESOURCE_ID=$(aws apigateway get-resources --rest-api-id "$API_ID" --query 'items[?path==`/`].id' --output text) # Create helloworld resource aws apigateway create-resource \ --rest-api-id "$API_ID" \ --parent-id "$ROOT_RESOURCE_ID" \ --path-part helloworld || { echo "Error: Failed to create resource" >&2 exit 1 } # Get resource ID RESOURCE_ID=$(aws apigateway get-resources --rest-api-id "$API_ID" --query "items[?pathPart=='helloworld'].id" --output text) # Create ANY method with no authorization (intentional for tutorial) aws apigateway put-method \ --rest-api-id "$API_ID" \ --resource-id "$RESOURCE_ID" \ --http-method ANY \ --authorization-type NONE || { echo "Error: Failed to create method" >&2 exit 1 } # Set up Lambda proxy integration LAMBDA_URI="arn:aws:apigateway:$REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:$REGION:$ACCOUNT_ID:function:$FUNCTION_NAME/invocations" aws apigateway put-integration \ --rest-api-id "$API_ID" \ --resource-id "$RESOURCE_ID" \ --http-method ANY \ --type AWS_PROXY \ --integration-http-method POST \ --uri "$LAMBDA_URI" || { echo "Error: Failed to create integration" >&2 exit 1 } # Grant API Gateway permission to invoke Lambda STATEMENT_ID="apigateway-invoke-$(openssl rand -hex 4)" SOURCE_ARN="arn:aws:execute-api:$REGION:$ACCOUNT_ID:$API_ID/*/*" aws lambda add-permission \ --function-name "$FUNCTION_NAME" \ --statement-id "$STATEMENT_ID" \ --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "$SOURCE_ARN" || { echo "Error: Failed to add Lambda permission" >&2 exit 1 } # Deploy API aws apigateway create-deployment \ --rest-api-id "$API_ID" \ --stage-name test \ --description "Test deployment" || { echo "Error: Failed to deploy API" >&2 exit 1 } echo "Testing API..." # Test the API INVOKE_URL="https://$API_ID.execute-api.$REGION.amazonaws.com/test/helloworld" echo "API URL: $INVOKE_URL" # Test with query parameter (with proper URL encoding) echo "Testing with query parameter:" curl -s -X GET "$INVOKE_URL?greeter=John" | jq . 2>/dev/null || curl -s -X GET "$INVOKE_URL?greeter=John" echo "" # Test with header echo "Testing with header:" curl -s -X GET "$INVOKE_URL" \ -H 'content-type: application/json' \ -H 'greeter: John' | jq . 2>/dev/null || curl -s -X GET "$INVOKE_URL" \ -H 'content-type: application/json' \ -H 'greeter: John' echo "" # Test with body echo "Testing with POST body:" curl -s -X POST "$INVOKE_URL" \ -H 'content-type: application/json' \ -d '{"greeter": "John"}' | jq . 2>/dev/null || curl -s -X POST "$INVOKE_URL" \ -H 'content-type: application/json' \ -d '{"greeter": "John"}' echo "" echo "Tutorial completed! API is available at: $INVOKE_URL" # Cleanup echo "Cleaning up resources..." # Delete API aws apigateway delete-rest-api --rest-api-id "$API_ID" || echo "Warning: Failed to delete API" >&2 # Delete Lambda function aws lambda delete-function --function-name "$FUNCTION_NAME" || echo "Warning: Failed to delete Lambda function" >&2 # Detach policy and delete role aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" || echo "Warning: Failed to detach policy" >&2 aws iam delete-role --role-name "$ROLE_NAME" || echo "Warning: Failed to delete role" >&2 # Clean up local files securely rm -f lambda_function.py function.zip trust-policy.json echo "Cleanup completed!"-
For API details, see the following topics in AWS CLI Command Reference.
-
The following code example shows how to:
Create a CloudWatch dashboard
Add Lambda metrics widgets with a function name variable
Verify the dashboard
Clean up resources
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash # Script to create a CloudWatch dashboard with Lambda function name as a variable # This script creates a CloudWatch dashboard that allows you to switch between different Lambda functions # Set up logging with secure permissions LOG_FILE="${HOME}/.cloudwatch-dashboard-script.log" touch "$LOG_FILE" && chmod 600 "$LOG_FILE" exec > >(tee -a "$LOG_FILE") 2>&1 echo "$(date): Starting CloudWatch dashboard creation script" # Security: Set strict error handling set -euo pipefail trap 'handle_error "Script failed at line $LINENO"' ERR # Function to handle errors handle_error() { local error_msg="${1:-Unknown error}" echo "ERROR: $error_msg" >&2 echo "Resources created:" echo "- CloudWatch Dashboard: LambdaMetricsDashboard" echo "" echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "An error occurred. Proceeding with automatic cleanup..." echo "Cleaning up resources..." aws cloudwatch delete-dashboards --dashboard-names LambdaMetricsDashboard 2>/dev/null || true # Clean up temporary files if [ -n "${TEMP_DIR:-}" ] && [ -d "$TEMP_DIR" ]; then rm -rf "$TEMP_DIR" fi rm -f dashboard-body.json echo "Cleanup complete." exit 1 } # Security: Validate AWS CLI is installed if ! command -v aws &> /dev/null; then handle_error "AWS CLI is not installed. Please install it and try again." fi # Check if AWS CLI is installed and configured echo "Checking AWS CLI configuration..." if ! aws sts get-caller-identity > /dev/null 2>&1; then handle_error "AWS CLI is not properly configured. Please configure it with 'aws configure' and try again." fi # Get the current region securely REGION=$(aws configure get region 2>/dev/null || echo "") if [ -z "$REGION" ]; then REGION="us-east-1" echo "No region found in AWS config, defaulting to $REGION" fi echo "Using region: $REGION" # Validate region format if ! [[ "$REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]{1}$ ]]; then handle_error "Invalid AWS region format: $REGION" fi # Check if there are any Lambda functions in the account echo "Checking for Lambda functions..." LAMBDA_FUNCTIONS=$(aws lambda list-functions --region "$REGION" --query "Functions[*].FunctionName" --output text 2>/dev/null || echo "") if [ -z "$LAMBDA_FUNCTIONS" ]; then echo "No Lambda functions found in your account. Creating a simple test function..." # Create a temporary directory for Lambda function code with secure permissions TEMP_DIR=$(mktemp -d) chmod 700 "$TEMP_DIR" trap 'rm -rf "$TEMP_DIR"' EXIT # Create a simple Lambda function cat > "$TEMP_DIR/index.js" << 'EOF' exports.handler = async (event) => { console.log('Event:', JSON.stringify(event, null, 2)); return { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; }; EOF # Zip the function code if ! cd "$TEMP_DIR"; then handle_error "Failed to change to temporary directory" fi if ! zip -q function.zip index.js; then handle_error "Failed to create zip file" fi # Create a role for the Lambda function with restricted trust policy ROLE_NAME="LambdaDashboardTestRole-$(date +%s)" TRUST_POLICY='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}' if ! ROLE_ARN=$(aws iam create-role \ --role-name "$ROLE_NAME" \ --assume-role-policy-document "$TRUST_POLICY" \ --query "Role.Arn" \ --output text 2>/dev/null); then handle_error "Failed to create IAM role for Lambda function" fi echo "Waiting for role to be available..." sleep 10 # Attach basic Lambda execution policy if ! aws iam attach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"; then aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true handle_error "Failed to attach policy to IAM role" fi # Create the Lambda function FUNCTION_NAME="DashboardTestFunction-$(date +%s)" if ! aws lambda create-function \ --function-name "$FUNCTION_NAME" \ --runtime nodejs18.x \ --role "$ROLE_ARN" \ --handler index.handler \ --zip-file fileb://function.zip \ --region "$REGION" > /dev/null 2>&1; then aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true handle_error "Failed to create Lambda function" fi # Invoke the function to generate some metrics echo "Invoking Lambda function to generate metrics..." for i in {1..5}; do aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null --region "$REGION" > /dev/null 2>&1 || true sleep 1 done # Go back to original directory cd - > /dev/null # Set the function name for the dashboard DEFAULT_FUNCTION="$FUNCTION_NAME" else # Use the first Lambda function as default DEFAULT_FUNCTION=$(echo "$LAMBDA_FUNCTIONS" | awk '{print $1}') echo "Found Lambda functions. Using $DEFAULT_FUNCTION as default." FUNCTION_NAME="" ROLE_NAME="" fi # Create a dashboard with Lambda metrics and a function name variable echo "Creating CloudWatch dashboard with Lambda function name variable..." # Create a JSON file for the dashboard body with secure permissions DASHBOARD_JSON="dashboard-body-$$.json" touch "$DASHBOARD_JSON" && chmod 600 "$DASHBOARD_JSON" # Escape special characters in region and function name for JSON REGION_ESCAPED=$(printf '%s\n' "$REGION" | sed 's:[\/&]:\\&:g') FUNCTION_ESCAPED=$(printf '%s\n' "$DEFAULT_FUNCTION" | sed 's:[\/&]:\\&:g') cat > "$DASHBOARD_JSON" << EOF { "widgets": [ { "type": "metric", "x": 0, "y": 0, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "Invocations", "FunctionName", "\${FunctionName}" ], [ ".", "Errors", ".", "." ], [ ".", "Throttles", ".", "." ] ], "view": "timeSeries", "stacked": false, "region": "$REGION_ESCAPED", "title": "Lambda Function Metrics for \${FunctionName}", "period": 300 } }, { "type": "metric", "x": 0, "y": 6, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "Duration", "FunctionName", "\${FunctionName}", { "stat": "Average" } ] ], "view": "timeSeries", "stacked": false, "region": "$REGION_ESCAPED", "title": "Duration for \${FunctionName}", "period": 300 } }, { "type": "metric", "x": 12, "y": 0, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "\${FunctionName}" ] ], "view": "timeSeries", "stacked": false, "region": "$REGION_ESCAPED", "title": "Concurrent Executions for \${FunctionName}", "period": 300 } } ], "periodOverride": "auto", "variables": [ { "type": "property", "id": "FunctionName", "property": "FunctionName", "label": "Lambda Function", "inputType": "select", "values": [ { "value": "$FUNCTION_ESCAPED", "label": "$FUNCTION_ESCAPED" } ] } ] } EOF # Validate JSON before sending if ! jq empty "$DASHBOARD_JSON" 2>/dev/null; then handle_error "Invalid JSON generated for dashboard" fi # Create the dashboard using the JSON file if ! DASHBOARD_RESULT=$(aws cloudwatch put-dashboard \ --dashboard-name "LambdaMetricsDashboard-$(date +%s)" \ --dashboard-body file://"$DASHBOARD_JSON" \ --region "$REGION" 2>&1); then # If we created resources, clean them up if [ -n "${FUNCTION_NAME:-}" ]; then aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true fi handle_error "Failed to create CloudWatch dashboard." fi # Display any validation messages but continue if echo "$DASHBOARD_RESULT" | grep -q "DashboardValidationMessages"; then echo "Dashboard created with validation messages:" echo "$DASHBOARD_RESULT" echo "These validation messages are warnings and the dashboard should still function." else echo "Dashboard created successfully!" fi # Extract dashboard name from result DASHBOARD_NAME=$(echo "$DASHBOARD_RESULT" | grep -oP '"DashboardName"\s*:\s*"\K[^"]+' || echo "LambdaMetricsDashboard") # Verify the dashboard was created echo "Verifying dashboard creation..." if ! DASHBOARD_INFO=$(aws cloudwatch get-dashboard --dashboard-name "$DASHBOARD_NAME" --region "$REGION" 2>&1); then # If we created resources, clean them up if [ -n "${FUNCTION_NAME:-}" ]; then aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true fi handle_error "Failed to verify dashboard creation." fi echo "Dashboard verification successful!" echo "Dashboard details:" echo "$DASHBOARD_INFO" # List all dashboards to confirm echo "Listing all dashboards:" if ! DASHBOARDS=$(aws cloudwatch list-dashboards --region "$REGION" 2>&1); then # If we created resources, clean them up if [ -n "${FUNCTION_NAME:-}" ]; then aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true fi handle_error "Failed to list dashboards." fi echo "$DASHBOARDS" # Show instructions for accessing the dashboard echo "" echo "Dashboard created successfully! To access it:" echo "1. Open the CloudWatch console at https://console.aws.amazon.com/cloudwatch/" echo "2. In the navigation pane, choose Dashboards" echo "3. Select $DASHBOARD_NAME" echo "4. You should see a dropdown menu labeled 'Lambda Function' at the top of the dashboard" echo "5. Use this dropdown to select different Lambda functions and see their metrics" echo "" # Create a list of resources for cleanup RESOURCES=("- CloudWatch Dashboard: $DASHBOARD_NAME") if [ -n "${FUNCTION_NAME:-}" ]; then RESOURCES+=("- Lambda Function: $FUNCTION_NAME") RESOURCES+=("- IAM Role: $ROLE_NAME") fi # Prompt for cleanup with automatic yes echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "Resources created:" for resource in "${RESOURCES[@]}"; do echo "$resource" done echo "" echo "Proceeding with automatic cleanup..." CLEANUP_CHOICE="y" if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then echo "Cleaning up resources..." # Delete the dashboard if aws cloudwatch delete-dashboards --dashboard-names "$DASHBOARD_NAME" --region "$REGION" 2>/dev/null; then echo "Dashboard deleted successfully." else echo "WARNING: Failed to delete dashboard. You may need to delete it manually." fi # If we created a Lambda function, delete it and its role if [ -n "${FUNCTION_NAME:-}" ]; then echo "Deleting Lambda function..." if aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null; then echo "Lambda function deleted successfully." else echo "WARNING: Failed to delete Lambda function. You may need to delete it manually." fi echo "Detaching role policy..." if aws iam detach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null; then echo "Role policy detached successfully." else echo "WARNING: Failed to detach role policy. You may need to detach it manually." fi echo "Deleting IAM role..." if aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null; then echo "IAM role deleted successfully." else echo "WARNING: Failed to delete IAM role. You may need to delete it manually." fi fi # Clean up the JSON file rm -f "$DASHBOARD_JSON" echo "Cleanup complete." fi echo "Script completed successfully!"-
For API details, see the following topics in AWS CLI Command Reference.
-
The following code example shows how to:
Create an IAM role for Lambda
Create function code
Create a Lambda function
Test your Lambda function
Clean up resources
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash # AWS Lambda - Create Your First Function # This script creates a Lambda function, invokes it with a test event, # views CloudWatch logs, and cleans up all resources. # # Source: https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html # # Resources created: # - IAM role (Lambda execution role with basic logging permissions) # - Lambda function (Python 3.13 or Node.js 22.x runtime) # - CloudWatch log group (created automatically by Lambda on invocation) set -eE -o pipefail ############################################################################### # Setup ############################################################################### UNIQUE_ID=$(head -c 8 /dev/urandom | od -An -tx1 | tr -d ' ') FUNCTION_NAME="my-lambda-function-${UNIQUE_ID}" ROLE_NAME="lambda-execution-role-${UNIQUE_ID}" LOG_GROUP_NAME="/aws/lambda/${FUNCTION_NAME}" TEMP_DIR=$(mktemp -d) readonly TEMP_DIR LOG_FILE="${TEMP_DIR}/lambda-gettingstarted.log" exec > >(tee -a "$LOG_FILE") 2>&1 declare -a CREATED_RESOURCES ############################################################################### # Helper functions ############################################################################### cleanup_resources() { # Disable error trap to prevent recursion during cleanup trap - ERR set +eE echo "" echo "Cleaning up resources..." echo "" for ((i=${#CREATED_RESOURCES[@]}-1; i>=0; i--)); do local RESOURCE="${CREATED_RESOURCES[$i]}" local TYPE="${RESOURCE%%:*}" local NAME="${RESOURCE#*:}" case "$TYPE" in log-group) echo "Deleting CloudWatch log group: ${NAME}" aws logs delete-log-group \ --log-group-name "$NAME" 2>&1 || echo " WARNING: Could not delete log group ${NAME}." ;; lambda-function) echo "Deleting Lambda function: ${NAME}" aws lambda delete-function \ --function-name "$NAME" 2>&1 || echo " WARNING: Could not delete Lambda function ${NAME}." echo " Waiting for function deletion to complete..." local DELETE_WAIT=0 while aws lambda get-function --function-name "$NAME" > /dev/null 2>&1; do sleep 2 DELETE_WAIT=$((DELETE_WAIT + 2)) if [ "$DELETE_WAIT" -ge 60 ]; then echo " WARNING: Timed out waiting for function deletion." break fi done ;; iam-role-policy) local ROLE_PART="${NAME%%|*}" local POLICY_PART="${NAME#*|}" echo "Detaching policy from role: ${ROLE_PART}" aws iam detach-role-policy \ --role-name "$ROLE_PART" \ --policy-arn "$POLICY_PART" 2>&1 || echo " WARNING: Could not detach policy from role ${ROLE_PART}." ;; iam-role) echo "Deleting IAM role: ${NAME}" aws iam delete-role \ --role-name "$NAME" 2>&1 || echo " WARNING: Could not delete IAM role ${NAME}." ;; esac done if [ -d "$TEMP_DIR" ]; then rm -rf "$TEMP_DIR" fi echo "" echo "Cleanup complete." } handle_error() { echo "" echo "===========================================" echo "ERROR: Script failed at $1" echo "===========================================" echo "" if [ ${#CREATED_RESOURCES[@]} -gt 0 ]; then echo "Attempting to clean up ${#CREATED_RESOURCES[@]} resource(s)..." cleanup_resources fi exit 1 } trap 'handle_error "line $LINENO"' ERR wait_for_resource() { local DESCRIPTION="$1" local COMMAND="$2" local TARGET_VALUE="$3" local TIMEOUT=300 local ELAPSED=0 local INTERVAL=5 echo "Waiting for ${DESCRIPTION}..." while true; do local RESULT RESULT=$(eval "$COMMAND" 2>&1) || true if echo "$RESULT" | grep -q "$TARGET_VALUE"; then echo " ${DESCRIPTION} is ready." return 0 fi if [ "$ELAPSED" -ge "$TIMEOUT" ]; then echo "ERROR: Timed out waiting for ${DESCRIPTION} after ${TIMEOUT} seconds." return 1 fi sleep "$INTERVAL" ELAPSED=$((ELAPSED + INTERVAL)) done } validate_input() { local input="$1" local pattern="$2" if ! [[ "$input" =~ $pattern ]]; then echo "ERROR: Invalid input: $input" return 1 fi return 0 } ############################################################################### # Region pre-check ############################################################################### CONFIGURED_REGION=$(aws configure get region 2>/dev/null || true) if [ -z "$CONFIGURED_REGION" ] && [ -z "$AWS_DEFAULT_REGION" ] && [ -z "$AWS_REGION" ]; then echo "ERROR: No AWS region configured." echo "Run 'aws configure set region <region>' or export AWS_DEFAULT_REGION." exit 1 fi ############################################################################### # Runtime selection ############################################################################### echo "" echo "===========================================" echo "AWS Lambda - Create Your First Function" echo "===========================================" echo "" echo "Select a runtime for your Lambda function:" echo " 1) Python 3.13" echo " 2) Node.js 22.x" echo "" echo "Using default: Python 3.13" RUNTIME_CHOICE="1" case "$RUNTIME_CHOICE" in 1) RUNTIME="python3.13" HANDLER="lambda_function.lambda_handler" CODE_FILE="lambda_function.py" cat > "${TEMP_DIR}/${CODE_FILE}" << 'PYTHON_EOF' import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): if not isinstance(event, dict) or 'length' not in event or 'width' not in event: raise ValueError('Event must contain length and width') try: length = float(event['length']) width = float(event['width']) if length < 0 or width < 0: raise ValueError('Length and width must be non-negative') area = calculate_area(length, width) print(f'The area is {area}') logger.info(f'CloudWatch logs group: {context.log_group_name}') return json.dumps({'area': area}) except (TypeError, ValueError) as e: logger.error(f'Error processing input: {str(e)}') raise def calculate_area(length, width): return length * width PYTHON_EOF echo "Selected runtime: Python 3.13" ;; 2) RUNTIME="nodejs22.x" HANDLER="index.handler" CODE_FILE="index.mjs" cat > "${TEMP_DIR}/${CODE_FILE}" << 'NODEJS_EOF' export const handler = async (event, context) => { if (!event || typeof event.length !== 'number' || typeof event.width !== 'number') { throw new Error('Event must contain numeric length and width'); } if (event.length < 0 || event.width < 0) { throw new Error('Length and width must be non-negative'); } const area = event.length * event.width; console.log(`The area is ${area}`); console.log('CloudWatch log group: ', context.logGroupName); return JSON.stringify({area}); }; NODEJS_EOF echo "Selected runtime: Node.js 22.x" ;; *) echo "ERROR: Invalid choice. Please enter 1 or 2." exit 1 ;; esac ############################################################################### # Step 1: Create IAM execution role ############################################################################### echo "" echo "===========================================" echo "Step 1: Create IAM execution role" echo "===========================================" echo "" TRUST_POLICY='{ "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }' echo "Creating IAM role: ${ROLE_NAME}" ROLE_OUTPUT=$(aws iam create-role \ --role-name "$ROLE_NAME" \ --assume-role-policy-document "$TRUST_POLICY" \ --query 'Role.Arn' \ --output text 2>&1) if ! validate_input "$ROLE_OUTPUT" "^arn:aws:iam::[0-9]+:role/"; then echo "ERROR: Failed to create IAM role" exit 1 fi echo "$ROLE_OUTPUT" ROLE_ARN="$ROLE_OUTPUT" CREATED_RESOURCES+=("iam-role:${ROLE_NAME}") echo "Role ARN: ${ROLE_ARN}" echo "" echo "Attaching AWSLambdaBasicExecutionRole policy..." aws iam attach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>&1 CREATED_RESOURCES+=("iam-role-policy:${ROLE_NAME}|arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole") echo "Policy attached." # IAM roles can take a few seconds to propagate echo "Waiting for IAM role to propagate..." sleep 10 ############################################################################### # Step 2: Create Lambda function ############################################################################### echo "" echo "===========================================" echo "Step 2: Create Lambda function" echo "===========================================" echo "" echo "Creating deployment package..." ORIGINAL_DIR=$(pwd) cd "$TEMP_DIR" || exit 1 zip -j function.zip "$CODE_FILE" > /dev/null 2>&1 || { echo "ERROR: Failed to create deployment package" exit 1 } cd "$ORIGINAL_DIR" || exit 1 if [ ! -f "${TEMP_DIR}/function.zip" ]; then echo "ERROR: Deployment package creation failed" exit 1 fi echo "Creating Lambda function: ${FUNCTION_NAME}" echo " Runtime: ${RUNTIME}" echo " Handler: ${HANDLER}" echo "" CREATE_OUTPUT=$(aws lambda create-function \ --function-name "$FUNCTION_NAME" \ --runtime "$RUNTIME" \ --role "$ROLE_ARN" \ --handler "$HANDLER" \ --architectures x86_64 \ --zip-file "fileb://${TEMP_DIR}/function.zip" \ --query '[FunctionName, FunctionArn, Runtime, State]' \ --output text 2>&1) if [ -z "$CREATE_OUTPUT" ]; then echo "ERROR: Failed to create Lambda function" exit 1 fi echo "$CREATE_OUTPUT" CREATED_RESOURCES+=("lambda-function:${FUNCTION_NAME}") wait_for_resource "Lambda function to become Active" \ "aws lambda get-function-configuration --function-name ${FUNCTION_NAME} --query State --output text" \ "Active" ############################################################################### # Step 3: Invoke the function ############################################################################### echo "" echo "===========================================" echo "Step 3: Invoke the function" echo "===========================================" echo "" TEST_EVENT='{"length": 6, "width": 7}' echo "Invoking function with test event: ${TEST_EVENT}" echo "" echo "$TEST_EVENT" > "${TEMP_DIR}/test-event.json" if ! validate_input "$TEST_EVENT" '"length": [0-9]+, "width": [0-9]+'; then echo "ERROR: Invalid test event format" exit 1 fi INVOKE_OUTPUT=$(aws lambda invoke \ --function-name "$FUNCTION_NAME" \ --payload "fileb://${TEMP_DIR}/test-event.json" \ --cli-read-timeout 30 \ "${TEMP_DIR}/response.json" 2>&1) echo "$INVOKE_OUTPUT" if [ ! -f "${TEMP_DIR}/response.json" ]; then echo "ERROR: No response file generated" exit 1 fi RESPONSE=$(cat "${TEMP_DIR}/response.json") echo "" echo "Function response: ${RESPONSE}" echo "" if echo "$INVOKE_OUTPUT" | grep -qi "functionerror"; then echo "WARNING: Function returned an error." fi ############################################################################### # Step 4: View CloudWatch logs ############################################################################### echo "" echo "===========================================" echo "Step 4: View CloudWatch Logs" echo "===========================================" echo "" echo "Log group: ${LOG_GROUP_NAME}" echo "" echo "Waiting for CloudWatch logs to be available..." LOG_STREAMS="" for i in $(seq 1 6); do LOG_STREAMS=$(aws logs describe-log-streams \ --log-group-name "$LOG_GROUP_NAME" \ --order-by LastEventTime \ --descending \ --query 'logStreams[0].logStreamName' \ --output text 2>/dev/null) || true if [ -n "$LOG_STREAMS" ] && [ "$LOG_STREAMS" != "None" ]; then break fi LOG_STREAMS="" sleep 5 done if [ -n "$LOG_STREAMS" ] && [ "$LOG_STREAMS" != "None" ]; then echo "Latest log stream: ${LOG_STREAMS}" echo "" echo "--- Log events ---" LOG_EVENTS=$(aws logs get-log-events \ --log-group-name "$LOG_GROUP_NAME" \ --log-stream-name "$LOG_STREAMS" \ --query 'events[].message' \ --output text 2>&1) || true echo "$LOG_EVENTS" echo "--- End of log events ---" else echo "No log streams found yet. Logs may take a moment to appear." echo "You can view them in the CloudWatch console:" echo " Log group: ${LOG_GROUP_NAME}" fi CREATED_RESOURCES+=("log-group:${LOG_GROUP_NAME}") ############################################################################### # Summary and cleanup ############################################################################### echo "" echo "===========================================" echo "SUMMARY" echo "===========================================" echo "" echo "Resources created:" echo " IAM role: ${ROLE_NAME}" echo " Lambda function: ${FUNCTION_NAME}" echo " CloudWatch logs: ${LOG_GROUP_NAME}" echo "" echo "===========================================" echo "CLEANUP" echo "===========================================" echo "" echo "Cleaning up all created resources..." cleanup_resources echo "" echo "Done."-
For API details, see the following topics in AWS CLI Command Reference.
-
The following code example shows how to:
Create Lambda functions for monitoring
Create a CloudWatch dashboard
Add a property variable to the dashboard
Clean up resources
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash # CloudWatch Dashboard with Lambda Function Variable Script # This script creates a CloudWatch dashboard with a property variable for Lambda function names set -euo pipefail # Security: Set restrictive umask umask 0077 # Set up logging with secure permissions LOG_FILE="cloudwatch-dashboard-script-v4.log" touch "$LOG_FILE" chmod 600 "$LOG_FILE" echo "Starting script execution at $(date)" >> "$LOG_FILE" # Function to log commands and their output (with sensitive data sanitization) log_cmd() { local cmd="$1" local sanitized_cmd="${cmd//--password*/--password [REDACTED]}" sanitized_cmd="${sanitized_cmd//--secret*/--secret [REDACTED]}" echo "$(date): Running command: $sanitized_cmd" >> "$LOG_FILE" eval "$cmd" 2>&1 | tee -a "$LOG_FILE" return ${PIPESTATUS[0]} } # Function to check for errors in command output check_error() { local cmd_output="$1" local cmd_status="$2" local error_msg="$3" if [ $cmd_status -ne 0 ] || echo "$cmd_output" | grep -qi "error"; then echo "ERROR: $error_msg" | tee -a "$LOG_FILE" # Sanitize output before logging local sanitized_output="${cmd_output//arn:aws:iam::[0-9]*/arn:aws:iam::ACCOUNT_ID}" echo "Command output: $sanitized_output" | tee -a "$LOG_FILE" cleanup_resources exit 1 fi } # Trap errors and cleanup trap 'cleanup_resources' EXIT ERR INT TERM # Function to clean up resources cleanup_resources() { local exit_code=$? echo "" | tee -a "$LOG_FILE" echo "==========================================" | tee -a "$LOG_FILE" echo "CLEANUP PROCESS" | tee -a "$LOG_FILE" echo "==========================================" | tee -a "$LOG_FILE" if [ -n "${DASHBOARD_NAME:-}" ]; then echo "Deleting CloudWatch dashboard: $DASHBOARD_NAME" | tee -a "$LOG_FILE" aws cloudwatch delete-dashboards --dashboard-names "$DASHBOARD_NAME" 2>&1 >> "$LOG_FILE" || true fi if [ -n "${LAMBDA_FUNCTION1:-}" ]; then echo "Deleting Lambda function: $LAMBDA_FUNCTION1" | tee -a "$LOG_FILE" aws lambda delete-function --function-name "$LAMBDA_FUNCTION1" 2>&1 >> "$LOG_FILE" || true fi if [ -n "${LAMBDA_FUNCTION2:-}" ]; then echo "Deleting Lambda function: $LAMBDA_FUNCTION2" | tee -a "$LOG_FILE" aws lambda delete-function --function-name "$LAMBDA_FUNCTION2" 2>&1 >> "$LOG_FILE" || true fi if [ -n "${ROLE_NAME:-}" ]; then echo "Detaching policy from role: $ROLE_NAME" | tee -a "$LOG_FILE" aws iam detach-role-policy --role-name "$ROLE_NAME" --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole 2>&1 >> "$LOG_FILE" || true echo "Deleting IAM role: $ROLE_NAME" | tee -a "$LOG_FILE" aws iam delete-role --role-name "$ROLE_NAME" 2>&1 >> "$LOG_FILE" || true fi # Clean up temporary files securely shred -vfz -n 3 trust-policy.json lambda_function.py lambda_function.zip 2>/dev/null || rm -f trust-policy.json lambda_function.py lambda_function.zip echo "Cleanup completed." | tee -a "$LOG_FILE" return $exit_code } # Validate AWS CLI is installed and authenticated if ! command -v aws &> /dev/null; then echo "ERROR: AWS CLI is not installed" | tee -a "$LOG_FILE" exit 1 fi if ! aws sts get-caller-identity &> /dev/null; then echo "ERROR: AWS CLI is not properly authenticated" | tee -a "$LOG_FILE" exit 1 fi # Get AWS region with validation AWS_REGION=$(aws configure get region 2>/dev/null || echo "") if [ -z "$AWS_REGION" ]; then AWS_REGION="us-east-1" echo "No region found in AWS config, defaulting to $AWS_REGION" | tee -a "$LOG_FILE" else echo "Using AWS region: $AWS_REGION" | tee -a "$LOG_FILE" fi # Validate region format if ! [[ "$AWS_REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]$ ]]; then echo "ERROR: Invalid AWS region format: $AWS_REGION" | tee -a "$LOG_FILE" exit 1 fi # Generate unique identifiers using secure random with validation RANDOM_ID=$(openssl rand -hex 6) if [ -z "$RANDOM_ID" ] || [ ${#RANDOM_ID} -ne 12 ]; then echo "ERROR: Failed to generate valid random identifier" | tee -a "$LOG_FILE" exit 1 fi DASHBOARD_NAME="LambdaMetricsDashboard-${RANDOM_ID}" LAMBDA_FUNCTION1="TestFunction1-${RANDOM_ID}" LAMBDA_FUNCTION2="TestFunction2-${RANDOM_ID}" ROLE_NAME="LambdaExecutionRole-${RANDOM_ID}" # Validate resource names don't exceed AWS limits if [ ${#DASHBOARD_NAME} -gt 128 ] || [ ${#LAMBDA_FUNCTION1} -gt 64 ] || [ ${#ROLE_NAME} -gt 64 ]; then echo "ERROR: Generated resource names exceed AWS limits" | tee -a "$LOG_FILE" exit 1 fi echo "Using random identifier: $RANDOM_ID" | tee -a "$LOG_FILE" echo "Dashboard name: $DASHBOARD_NAME" | tee -a "$LOG_FILE" echo "Lambda function names: $LAMBDA_FUNCTION1, $LAMBDA_FUNCTION2" | tee -a "$LOG_FILE" echo "IAM role name: $ROLE_NAME" | tee -a "$LOG_FILE" # Create IAM role for Lambda functions echo "Creating IAM role for Lambda..." | tee -a "$LOG_FILE" TRUST_POLICY='{ "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }' echo "$TRUST_POLICY" > trust-policy.json chmod 600 trust-policy.json # Validate JSON before use if ! python3 -m json.tool trust-policy.json > /dev/null 2>&1; then echo "ERROR: Invalid trust policy JSON" | tee -a "$LOG_FILE" exit 1 fi ROLE_OUTPUT=$(log_cmd "aws iam create-role --role-name '$ROLE_NAME' --assume-role-policy-document file://trust-policy.json --output json") check_error "$ROLE_OUTPUT" $? "Failed to create IAM role" ROLE_ARN=$(echo "$ROLE_OUTPUT" | python3 -c "import sys, json; print(json.load(sys.stdin)['Role']['Arn'])" 2>/dev/null) if [ -z "$ROLE_ARN" ]; then echo "ERROR: Failed to extract Role ARN" | tee -a "$LOG_FILE" exit 1 fi echo "Role ARN: $ROLE_ARN" | tee -a "$LOG_FILE" # Attach Lambda basic execution policy to the role echo "Attaching Lambda execution policy to role..." | tee -a "$LOG_FILE" POLICY_OUTPUT=$(log_cmd "aws iam attach-role-policy --role-name '$ROLE_NAME' --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole") check_error "$POLICY_OUTPUT" $? "Failed to attach policy to role" # Wait for role to propagate echo "Waiting for IAM role to propagate..." | tee -a "$LOG_FILE" sleep 10 # Create simple Python Lambda function code with security validation echo "Creating Lambda function code..." | tee -a "$LOG_FILE" cat > lambda_function.py << 'LAMBDA_EOF' def handler(event, context): print("Lambda function executed successfully") return { 'statusCode': 200, 'body': 'Success' } LAMBDA_EOF chmod 600 lambda_function.py # Validate Python syntax if ! python3 -m py_compile lambda_function.py 2>/dev/null; then echo "ERROR: Invalid Python syntax in Lambda function" | tee -a "$LOG_FILE" exit 1 fi # Zip the Lambda function code zip -j -q lambda_function.zip lambda_function.py if [ ! -f lambda_function.zip ]; then echo "ERROR: Failed to create lambda_function.zip" | tee -a "$LOG_FILE" exit 1 fi chmod 600 lambda_function.zip # Validate zip file integrity if ! unzip -t lambda_function.zip > /dev/null 2>&1; then echo "ERROR: Created zip file is corrupted" | tee -a "$LOG_FILE" exit 1 fi # Create first Lambda function echo "Creating first Lambda function: $LAMBDA_FUNCTION1..." | tee -a "$LOG_FILE" LAMBDA1_OUTPUT=$(log_cmd "aws lambda create-function --function-name '$LAMBDA_FUNCTION1' --runtime python3.11 --role '$ROLE_ARN' --handler lambda_function.handler --zip-file fileb://lambda_function.zip --timeout 30 --memory-size 128") check_error "$LAMBDA1_OUTPUT" $? "Failed to create first Lambda function" # Create second Lambda function echo "Creating second Lambda function: $LAMBDA_FUNCTION2..." | tee -a "$LOG_FILE" LAMBDA2_OUTPUT=$(log_cmd "aws lambda create-function --function-name '$LAMBDA_FUNCTION2' --runtime python3.11 --role '$ROLE_ARN' --handler lambda_function.handler --zip-file fileb://lambda_function.zip --timeout 30 --memory-size 128") check_error "$LAMBDA2_OUTPUT" $? "Failed to create second Lambda function" # Invoke Lambda functions to generate some metrics echo "Invoking Lambda functions to generate metrics..." | tee -a "$LOG_FILE" log_cmd "aws lambda invoke --function-name '$LAMBDA_FUNCTION1' --payload '{}' /dev/null" || true log_cmd "aws lambda invoke --function-name '$LAMBDA_FUNCTION2' --payload '{}' /dev/null" || true # Create CloudWatch dashboard with property variable echo "Creating CloudWatch dashboard with property variable..." | tee -a "$LOG_FILE" # Create dashboard body with proper escaping and validation DASHBOARD_BODY=$(cat <<EOF { "widgets": [ { "type": "metric", "x": 0, "y": 0, "width": 12, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", "Invocations", "FunctionName", "$LAMBDA_FUNCTION1" ] ], "view": "timeSeries", "stacked": false, "region": "$AWS_REGION", "title": "Lambda Invocations", "period": 300, "stat": "Sum" } } ] } EOF ) # Validate JSON before sending if ! echo "$DASHBOARD_BODY" | python3 -m json.tool > /dev/null 2>&1; then echo "ERROR: Dashboard body is not valid JSON" | tee -a "$LOG_FILE" exit 1 fi # First create a basic dashboard without variables echo "Creating initial dashboard without variables..." | tee -a "$LOG_FILE" DASHBOARD_OUTPUT=$(aws cloudwatch put-dashboard --dashboard-name "$DASHBOARD_NAME" --dashboard-body "$DASHBOARD_BODY" --output json 2>&1) check_error "$DASHBOARD_OUTPUT" $? "Failed to create initial CloudWatch dashboard" # Now let's try to add a property variable using the console instructions echo "To complete the tutorial, please follow these steps in the CloudWatch console:" | tee -a "$LOG_FILE" echo "1. Open the CloudWatch console at https://console.aws.amazon.com/cloudwatch/" | tee -a "$LOG_FILE" echo "2. Navigate to Dashboards and select your dashboard: $DASHBOARD_NAME" | tee -a "$LOG_FILE" echo "3. Choose Actions > Variables > Create a variable" | tee -a "$LOG_FILE" echo "4. Choose Property variable" | tee -a "$LOG_FILE" echo "5. For Property that the variable changes, choose FunctionName" | tee -a "$LOG_FILE" echo "6. For Input type, choose Select menu (dropdown)" | tee -a "$LOG_FILE" echo "7. Choose Use the results of a metric search" | tee -a "$LOG_FILE" echo "8. Choose Pre-built queries > Lambda > Errors" | tee -a "$LOG_FILE" echo "9. Choose By Function Name and then choose Search" | tee -a "$LOG_FILE" echo "10. (Optional) Configure any secondary settings as desired" | tee -a "$LOG_FILE" echo "11. Choose Add variable" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" echo "The dashboard has been created and can be accessed at:" | tee -a "$LOG_FILE" echo "https://console.aws.amazon.com/cloudwatch/home#dashboards:name=$DASHBOARD_NAME" | tee -a "$LOG_FILE" # Verify dashboard creation echo "Verifying dashboard creation..." | tee -a "$LOG_FILE" VERIFY_OUTPUT=$(aws cloudwatch get-dashboard --dashboard-name "$DASHBOARD_NAME" --output json 2>&1) check_error "$VERIFY_OUTPUT" $? "Failed to verify dashboard creation" echo "" | tee -a "$LOG_FILE" echo "==========================================" | tee -a "$LOG_FILE" echo "DASHBOARD CREATED SUCCESSFULLY" | tee -a "$LOG_FILE" echo "==========================================" | tee -a "$LOG_FILE" echo "Dashboard Name: $DASHBOARD_NAME" | tee -a "$LOG_FILE" echo "Lambda Functions: $LAMBDA_FUNCTION1, $LAMBDA_FUNCTION2" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" echo "You can view your dashboard in the CloudWatch console:" | tee -a "$LOG_FILE" echo "https://console.aws.amazon.com/cloudwatch/home#dashboards:name=$DASHBOARD_NAME" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" # Auto-confirm cleanup echo "" | tee -a "$LOG_FILE" echo "==========================================" | tee -a "$LOG_FILE" echo "CLEANUP CONFIRMATION" | tee -a "$LOG_FILE" echo "==========================================" | tee -a "$LOG_FILE" echo "The following resources were created:" | tee -a "$LOG_FILE" echo "- CloudWatch Dashboard: $DASHBOARD_NAME" | tee -a "$LOG_FILE" echo "- Lambda Function: $LAMBDA_FUNCTION1" | tee -a "$LOG_FILE" echo "- Lambda Function: $LAMBDA_FUNCTION2" | tee -a "$LOG_FILE" echo "- IAM Role: $ROLE_NAME" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" echo "Auto-confirming cleanup of all created resources..." | tee -a "$LOG_FILE" echo "Script completed successfully." | tee -a "$LOG_FILE" exit 0-
For API details, see the following topics in AWS CLI Command Reference.
-