Amazon Cloud Map examples using Amazon CLI with Bash script - Amazon Command Line Interface
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Amazon Cloud Map examples using Amazon CLI with Bash script

The following code examples show you how to perform actions and implement common scenarios by using the Amazon Command Line Interface with Bash script with Amazon Cloud Map.

Scenarios are code examples that show you how to accomplish specific tasks by calling multiple functions within a service or combined with other Amazon Web Services 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 HTTP namespace for API-based service discovery

  • Create a DynamoDB table and register it as a data service with custom attributes

  • Create Lambda functions for reading and writing data

  • Register Lambda functions as service instances with custom attributes for action-based discovery

  • Build client applications that discover services using custom attributes

  • Clean up all resources including Lambda functions, DynamoDB table, and Cloud Map services

Amazon 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 Cloud Map Tutorial Script # This script demonstrates how to use AWS Cloud Map for service discovery with custom attributes # Set up logging LOG_FILE="cloudmap-tutorial.log" echo "AWS Cloud Map Tutorial Script" > $LOG_FILE echo "Started at $(date)" >> $LOG_FILE # Array to track created resources for cleanup CREATED_RESOURCES=() # Function to log commands and their output log_cmd() { echo "$ $1" | tee -a $LOG_FILE eval "$1" | tee -a $LOG_FILE } # Function to handle errors handle_error() { local LINE=$1 echo "An error occurred at line $LINE" | tee -a $LOG_FILE echo "Resources created so far:" | tee -a $LOG_FILE for resource in "${CREATED_RESOURCES[@]}"; do echo "- $resource" | tee -a $LOG_FILE done echo "Attempting to clean up resources..." | tee -a $LOG_FILE cleanup exit 1 } # Set up error handling trap 'handle_error $LINENO' ERR # Helper function to wait for Cloud Map operations to complete wait_for_operation() { local OPERATION_ID=$1 local TIMEOUT=300 # 5 minutes timeout local START_TIME=$(date +%s) while true; do local STATUS=$(aws servicediscovery get-operation --operation-id $OPERATION_ID --query 'Operation.Status' --output text) if [ "$STATUS" == "SUCCESS" ]; then echo "Operation completed successfully" | tee -a $LOG_FILE break elif [ "$STATUS" == "FAIL" ]; then echo "Operation failed" | tee -a $LOG_FILE return 1 fi local CURRENT_TIME=$(date +%s) if [ $((CURRENT_TIME - START_TIME)) -gt $TIMEOUT ]; then echo "Operation timed out" | tee -a $LOG_FILE return 1 fi sleep 5 done return 0 } # Function to clean up resources cleanup() { echo "Cleaning up resources..." | tee -a $LOG_FILE # Reverse the order of created resources for proper deletion for ((i=${#CREATED_RESOURCES[@]}-1; i>=0; i--)); do resource="${CREATED_RESOURCES[$i]}" echo "Deleting $resource..." | tee -a $LOG_FILE if [[ $resource == "instance:"* ]]; then # Extract service ID and instance ID SERVICE_ID=$(echo $resource | cut -d':' -f2) INSTANCE_ID=$(echo $resource | cut -d':' -f3) # Check if instance exists before trying to deregister INSTANCE_EXISTS=$(aws servicediscovery list-instances --service-id $SERVICE_ID --query "Instances[?Id=='$INSTANCE_ID'].Id" --output text 2>/dev/null || echo "") if [[ -n "$INSTANCE_EXISTS" ]]; then OPERATION_ID=$(aws servicediscovery deregister-instance --service-id $SERVICE_ID --instance-id $INSTANCE_ID --query 'OperationId' --output text) # Wait for deregistration to complete echo "Waiting for instance deregistration to complete..." | tee -a $LOG_FILE wait_for_operation $OPERATION_ID else echo "Instance $INSTANCE_ID already deregistered" | tee -a $LOG_FILE fi elif [[ $resource == "lambda:"* ]]; then # Extract function name FUNCTION_NAME=$(echo $resource | cut -d':' -f2) aws lambda delete-function --function-name $FUNCTION_NAME elif [[ $resource == "role:"* ]]; then # Extract role name ROLE_NAME=$(echo $resource | cut -d':' -f2) # Detach all policies first for POLICY_ARN in $(aws iam list-attached-role-policies --role-name $ROLE_NAME --query 'AttachedPolicies[*].PolicyArn' --output text); do aws iam detach-role-policy --role-name $ROLE_NAME --policy-arn $POLICY_ARN done # Delete the role aws iam delete-role --role-name $ROLE_NAME elif [[ $resource == "dynamodb:"* ]]; then # Extract table name TABLE_NAME=$(echo $resource | cut -d':' -f2) aws dynamodb delete-table --table-name $TABLE_NAME # Wait for table deletion to complete echo "Waiting for DynamoDB table deletion to complete..." | tee -a $LOG_FILE aws dynamodb wait table-not-exists --table-name $TABLE_NAME fi done # Handle services separately to ensure all instances are deregistered first for ((i=${#CREATED_RESOURCES[@]}-1; i>=0; i--)); do resource="${CREATED_RESOURCES[$i]}" if [[ $resource == "service:"* ]]; then # Extract service ID SERVICE_ID=$(echo $resource | cut -d':' -f2) echo "Deleting service $SERVICE_ID..." | tee -a $LOG_FILE # Make sure all instances are deregistered INSTANCES=$(aws servicediscovery list-instances --service-id $SERVICE_ID --query 'Instances[*].Id' --output text) if [[ -n "$INSTANCES" ]]; then echo "Service still has instances. Waiting before deletion..." | tee -a $LOG_FILE sleep 10 fi # Try to delete the service aws servicediscovery delete-service --id $SERVICE_ID sleep 5 fi done # Handle namespaces last to ensure all services are deleted first for ((i=${#CREATED_RESOURCES[@]}-1; i>=0; i--)); do resource="${CREATED_RESOURCES[$i]}" if [[ $resource == "namespace:"* ]]; then # Extract namespace ID NAMESPACE_ID=$(echo $resource | cut -d':' -f2) echo "Deleting namespace $NAMESPACE_ID..." | tee -a $LOG_FILE # Check if namespace still has services SERVICES=$(aws servicediscovery list-services --filters "Name=NAMESPACE_ID,Values=$NAMESPACE_ID,Condition=EQ" --query 'Services[*].Id' --output text) if [[ -n "$SERVICES" ]]; then echo "Namespace still has services. Deleting them first..." | tee -a $LOG_FILE for SERVICE_ID in $SERVICES; do echo "Deleting service $SERVICE_ID..." | tee -a $LOG_FILE aws servicediscovery delete-service --id $SERVICE_ID done sleep 5 fi # Try to delete the namespace OPERATION_ID=$(aws servicediscovery delete-namespace --id $NAMESPACE_ID --query 'OperationId' --output text 2>/dev/null || echo "") if [[ -n "$OPERATION_ID" ]]; then echo "Waiting for namespace deletion to complete..." | tee -a $LOG_FILE wait_for_operation $OPERATION_ID else echo "Failed to delete namespace or namespace already deleted" | tee -a $LOG_FILE fi fi done echo "Cleanup complete" | tee -a $LOG_FILE } # Step 1: Create an AWS Cloud Map namespace echo "Step 1: Creating AWS Cloud Map namespace..." | tee -a $LOG_FILE # Check if namespace already exists NAMESPACE_ID=$(aws servicediscovery list-namespaces --query "Namespaces[?Name=='cloudmap-tutorial'].Id" --output text) if [[ -z "$NAMESPACE_ID" || "$NAMESPACE_ID" == "None" ]]; then log_cmd "aws servicediscovery create-http-namespace --name cloudmap-tutorial --creator-request-id namespace-request" OPERATION_ID=$(aws servicediscovery create-http-namespace --name cloudmap-tutorial --creator-request-id namespace-request --query 'OperationId' --output text) # Wait for namespace creation to complete echo "Waiting for namespace creation to complete..." | tee -a $LOG_FILE wait_for_operation $OPERATION_ID # Get the namespace ID NAMESPACE_ID=$(aws servicediscovery list-namespaces --query "Namespaces[?Name=='cloudmap-tutorial'].Id" --output text) echo "Namespace created with ID: $NAMESPACE_ID" | tee -a $LOG_FILE else echo "Namespace cloudmap-tutorial already exists with ID: $NAMESPACE_ID" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("namespace:$NAMESPACE_ID") # Step 2: Create a DynamoDB table echo "Step 2: Creating DynamoDB table..." | tee -a $LOG_FILE # Check if table already exists TABLE_EXISTS=$(aws dynamodb describe-table --table-name cloudmap 2>&1 || echo "NOT_EXISTS") if [[ $TABLE_EXISTS == *"ResourceNotFoundException"* || $TABLE_EXISTS == "NOT_EXISTS" ]]; then log_cmd "aws dynamodb create-table --table-name cloudmap --attribute-definitions AttributeName=id,AttributeType=S --key-schema AttributeName=id,KeyType=HASH --billing-mode PAY_PER_REQUEST" # Wait for DynamoDB table to become active echo "Waiting for DynamoDB table to become active..." | tee -a $LOG_FILE aws dynamodb wait table-exists --table-name cloudmap else echo "DynamoDB table cloudmap already exists" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("dynamodb:cloudmap") # Step 3: Create an AWS Cloud Map data service echo "Step 3: Creating AWS Cloud Map data service..." | tee -a $LOG_FILE # Get all services in the namespace echo "Listing all services in namespace $NAMESPACE_ID..." | tee -a $LOG_FILE SERVICES=$(aws servicediscovery list-services --filters "Name=NAMESPACE_ID,Values=$NAMESPACE_ID,Condition=EQ" --query 'Services[*].[Id,Name]' --output text) echo "Services found: $SERVICES" | tee -a $LOG_FILE # Check if data service already exists DATA_SERVICE_ID="" while read -r id name || [[ -n "$id" ]]; do echo "Checking service: ID=$id, Name=$name" | tee -a $LOG_FILE if [[ "$name" == "data-service" ]]; then DATA_SERVICE_ID="$id" break fi done <<< "$SERVICES" if [[ -z "$DATA_SERVICE_ID" ]]; then echo "Data service does not exist, creating it..." | tee -a $LOG_FILE # Create the service and capture the ID directly echo "$ aws servicediscovery create-service --name data-service --namespace-id $NAMESPACE_ID --creator-request-id data-service-request" | tee -a $LOG_FILE CREATE_OUTPUT=$(aws servicediscovery create-service --name data-service --namespace-id $NAMESPACE_ID --creator-request-id data-service-request) echo "$CREATE_OUTPUT" | tee -a $LOG_FILE # Extract the service ID using AWS CLI query DATA_SERVICE_ID=$(aws servicediscovery list-services --filters "Name=NAMESPACE_ID,Values=$NAMESPACE_ID,Condition=EQ" --query "Services[?Name=='data-service'].Id" --output text) echo "Data service created with ID: $DATA_SERVICE_ID" | tee -a $LOG_FILE else echo "Data service already exists with ID: $DATA_SERVICE_ID" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("service:$DATA_SERVICE_ID") # Register DynamoDB table as a service instance echo "Registering DynamoDB table as a service instance..." | tee -a $LOG_FILE # Check if instance already exists INSTANCE_EXISTS=$(aws servicediscovery list-instances --service-id $DATA_SERVICE_ID --query "Instances[?Id=='data-instance'].Id" --output text) if [[ -z "$INSTANCE_EXISTS" ]]; then log_cmd "aws servicediscovery register-instance --service-id $DATA_SERVICE_ID --instance-id data-instance --attributes tablename=cloudmap,region=$(aws configure get region)" OPERATION_ID=$(aws servicediscovery register-instance --service-id $DATA_SERVICE_ID --instance-id data-instance --attributes tablename=cloudmap,region=$(aws configure get region) --query 'OperationId' --output text) # Wait for instance registration to complete echo "Waiting for instance registration to complete..." | tee -a $LOG_FILE wait_for_operation $OPERATION_ID else echo "Instance data-instance already exists" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("instance:$DATA_SERVICE_ID:data-instance") # Step 4: Create an IAM role for Lambda echo "Step 4: Creating IAM role for Lambda..." | tee -a $LOG_FILE # Create a trust policy for Lambda cat > lambda-trust-policy.json << EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF # Check if role already exists echo "Checking if IAM role already exists..." | tee -a $LOG_FILE ROLE_EXISTS=$(aws iam get-role --role-name cloudmap-tutorial-role 2>&1 || echo "NOT_EXISTS") if [[ $ROLE_EXISTS == *"NoSuchEntity"* || $ROLE_EXISTS == "NOT_EXISTS" ]]; then log_cmd "aws iam create-role --role-name cloudmap-tutorial-role --assume-role-policy-document file://lambda-trust-policy.json" else echo "Role cloudmap-tutorial-role already exists, using existing role" | tee -a $LOG_FILE fi # FIXED: Create a custom policy with least privilege instead of using PowerUserAccess cat > cloudmap-policy.json << EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:Scan" ], "Resource": "arn:aws:dynamodb:*:*:table/cloudmap" }, { "Effect": "Allow", "Action": [ "servicediscovery:DiscoverInstances" ], "Resource": "*" } ] } EOF # Check if policy already exists POLICY_ARN=$(aws iam list-policies --query "Policies[?PolicyName=='CloudMapTutorialPolicy'].Arn" --output text) if [[ -z "$POLICY_ARN" ]]; then echo "Creating CloudMapTutorialPolicy..." | tee -a $LOG_FILE echo "$ aws iam create-policy --policy-name CloudMapTutorialPolicy --policy-document file://cloudmap-policy.json" | tee -a $LOG_FILE CREATE_OUTPUT=$(aws iam create-policy --policy-name CloudMapTutorialPolicy --policy-document file://cloudmap-policy.json) echo "$CREATE_OUTPUT" | tee -a $LOG_FILE POLICY_ARN=$(aws iam list-policies --query "Policies[?PolicyName=='CloudMapTutorialPolicy'].Arn" --output text) else echo "Policy CloudMapTutorialPolicy already exists with ARN: $POLICY_ARN" | tee -a $LOG_FILE fi echo "$ aws iam attach-role-policy --role-name cloudmap-tutorial-role --policy-arn $POLICY_ARN" | tee -a $LOG_FILE aws iam attach-role-policy --role-name cloudmap-tutorial-role --policy-arn $POLICY_ARN | tee -a $LOG_FILE echo "$ aws iam attach-role-policy --role-name cloudmap-tutorial-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" | tee -a $LOG_FILE aws iam attach-role-policy --role-name cloudmap-tutorial-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole | tee -a $LOG_FILE # Wait for role to propagate echo "Waiting for IAM role to propagate..." | tee -a $LOG_FILE sleep 10 ROLE_ARN=$(aws iam get-role --role-name cloudmap-tutorial-role --query 'Role.Arn' --output text) CREATED_RESOURCES+=("role:cloudmap-tutorial-role") # Step 5: Create an AWS Cloud Map app service echo "Step 5: Creating AWS Cloud Map app service..." | tee -a $LOG_FILE # Get all services in the namespace SERVICES=$(aws servicediscovery list-services --filters "Name=NAMESPACE_ID,Values=$NAMESPACE_ID,Condition=EQ" --query 'Services[*].[Id,Name]' --output text) # Check if app service already exists APP_SERVICE_ID="" while read -r id name || [[ -n "$id" ]]; do if [[ "$name" == "app-service" ]]; then APP_SERVICE_ID="$id" break fi done <<< "$SERVICES" if [[ -z "$APP_SERVICE_ID" ]]; then echo "App service does not exist, creating it..." | tee -a $LOG_FILE # Create the service and capture the ID directly echo "$ aws servicediscovery create-service --name app-service --namespace-id $NAMESPACE_ID --creator-request-id app-service-request" | tee -a $LOG_FILE CREATE_OUTPUT=$(aws servicediscovery create-service --name app-service --namespace-id $NAMESPACE_ID --creator-request-id app-service-request) echo "$CREATE_OUTPUT" | tee -a $LOG_FILE # Extract the service ID using AWS CLI query APP_SERVICE_ID=$(aws servicediscovery list-services --filters "Name=NAMESPACE_ID,Values=$NAMESPACE_ID,Condition=EQ" --query "Services[?Name=='app-service'].Id" --output text) echo "App service created with ID: $APP_SERVICE_ID" | tee -a $LOG_FILE else echo "App service already exists with ID: $APP_SERVICE_ID" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("service:$APP_SERVICE_ID") # Step 6: Create a Lambda function to write data echo "Step 6: Creating Lambda function to write data..." | tee -a $LOG_FILE # Create Lambda function code cat > writefunction.py << EOF import boto3 import json import random def lambda_handler(event, context): # Use AWS Cloud Map to discover the DynamoDB table serviceclient = boto3.client('servicediscovery') # Discover the data service instance response = serviceclient.discover_instances( NamespaceName='cloudmap-tutorial', ServiceName='data-service' ) # Extract table name and region from the instance attributes tablename = response['Instances'][0]['Attributes']['tablename'] region = response['Instances'][0]['Attributes']['region'] # Create DynamoDB client in the specified region dynamodb = boto3.resource('dynamodb', region_name=region) table = dynamodb.Table(tablename) # Write data to the table table.put_item( Item={ 'id': str(random.randint(1,100)), 'todo': event } ) return { 'statusCode': 200, 'body': json.dumps('Data written successfully!') } EOF # Zip the function code log_cmd "zip writefunction.zip writefunction.py" # Create the Lambda function FUNCTION_EXISTS=$(aws lambda list-functions --query "Functions[?FunctionName=='writefunction'].FunctionName" --output text) if [[ -z "$FUNCTION_EXISTS" ]]; then log_cmd "aws lambda create-function --function-name writefunction --runtime python3.12 --role $ROLE_ARN --handler writefunction.lambda_handler --zip-file fileb://writefunction.zip --architectures x86_64" # Wait for the Lambda function to be active before updating echo "Waiting for Lambda function to become active..." | tee -a $LOG_FILE function_state="Pending" while [ "$function_state" == "Pending" ]; do sleep 5 function_state=$(aws lambda get-function --function-name writefunction --query 'Configuration.State' --output text) echo "Current function state: $function_state" | tee -a $LOG_FILE done # Update the function timeout log_cmd "aws lambda update-function-configuration --function-name writefunction --timeout 5" else echo "Lambda function writefunction already exists" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("lambda:writefunction") # Step 7: Register the Lambda write function as an AWS Cloud Map service instance echo "Step 7: Registering Lambda write function as a service instance..." | tee -a $LOG_FILE # Check if instance already exists INSTANCE_EXISTS=$(aws servicediscovery list-instances --service-id $APP_SERVICE_ID --query "Instances[?Id=='write-instance'].Id" --output text) if [[ -z "$INSTANCE_EXISTS" ]]; then log_cmd "aws servicediscovery register-instance --service-id $APP_SERVICE_ID --instance-id write-instance --attributes action=write,functionname=writefunction" OPERATION_ID=$(aws servicediscovery register-instance --service-id $APP_SERVICE_ID --instance-id write-instance --attributes action=write,functionname=writefunction --query 'OperationId' --output text) # Wait for instance registration to complete echo "Waiting for write instance registration to complete..." | tee -a $LOG_FILE wait_for_operation $OPERATION_ID else echo "Instance write-instance already exists" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("instance:$APP_SERVICE_ID:write-instance") # Step 8: Create a Lambda function to read data echo "Step 8: Creating Lambda function to read data..." | tee -a $LOG_FILE # Create Lambda function code cat > readfunction.py << EOF import boto3 import json def lambda_handler(event, context): # Use AWS Cloud Map to discover the DynamoDB table serviceclient = boto3.client('servicediscovery') # Discover the data service instance response = serviceclient.discover_instances( NamespaceName='cloudmap-tutorial', ServiceName='data-service' ) # Extract table name and region from the instance attributes tablename = response['Instances'][0]['Attributes']['tablename'] region = response['Instances'][0]['Attributes']['region'] # Create DynamoDB client in the specified region dynamodb = boto3.resource('dynamodb', region_name=region) table = dynamodb.Table(tablename) # Read data from the table response = table.scan() return { 'statusCode': 200, 'body': json.dumps(response['Items']) } EOF # Zip the function code log_cmd "zip readfunction.zip readfunction.py" # Create the Lambda function FUNCTION_EXISTS=$(aws lambda list-functions --query "Functions[?FunctionName=='readfunction'].FunctionName" --output text) if [[ -z "$FUNCTION_EXISTS" ]]; then log_cmd "aws lambda create-function --function-name readfunction --runtime python3.12 --role $ROLE_ARN --handler readfunction.lambda_handler --zip-file fileb://readfunction.zip --architectures x86_64" # Wait for the Lambda function to be active before updating echo "Waiting for Lambda function to become active..." | tee -a $LOG_FILE function_state="Pending" while [ "$function_state" == "Pending" ]; do sleep 5 function_state=$(aws lambda get-function --function-name readfunction --query 'Configuration.State' --output text) echo "Current function state: $function_state" | tee -a $LOG_FILE done # Update the function timeout log_cmd "aws lambda update-function-configuration --function-name readfunction --timeout 5" else echo "Lambda function readfunction already exists" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("lambda:readfunction") # Step 9: Register the Lambda read function as an AWS Cloud Map service instance echo "Step 9: Registering Lambda read function as a service instance..." | tee -a $LOG_FILE # Check if instance already exists INSTANCE_EXISTS=$(aws servicediscovery list-instances --service-id $APP_SERVICE_ID --query "Instances[?Id=='read-instance'].Id" --output text) if [[ -z "$INSTANCE_EXISTS" ]]; then log_cmd "aws servicediscovery register-instance --service-id $APP_SERVICE_ID --instance-id read-instance --attributes action=read,functionname=readfunction" OPERATION_ID=$(aws servicediscovery register-instance --service-id $APP_SERVICE_ID --instance-id read-instance --attributes action=read,functionname=readfunction --query 'OperationId' --output text) # Wait for read instance registration to complete echo "Waiting for read instance registration to complete..." | tee -a $LOG_FILE wait_for_operation $OPERATION_ID else echo "Instance read-instance already exists" | tee -a $LOG_FILE fi CREATED_RESOURCES+=("instance:$APP_SERVICE_ID:read-instance") # Step 10: Create Python clients to interact with the services echo "Step 10: Creating Python clients..." | tee -a $LOG_FILE cat > writeclient.py << EOF import boto3 serviceclient = boto3.client('servicediscovery') response = serviceclient.discover_instances(NamespaceName='cloudmap-tutorial', ServiceName='app-service', QueryParameters={ 'action': 'write' }) functionname = response["Instances"][0]["Attributes"]["functionname"] lambdaclient = boto3.client('lambda') resp = lambdaclient.invoke(FunctionName=functionname, Payload='"This is a test data"') print(resp["Payload"].read()) EOF cat > readclient.py << EOF import boto3 serviceclient = boto3.client('servicediscovery') response = serviceclient.discover_instances(NamespaceName='cloudmap-tutorial', ServiceName='app-service', QueryParameters={ 'action': 'read' }) functionname = response["Instances"][0]["Attributes"]["functionname"] lambdaclient = boto3.client('lambda') resp = lambdaclient.invoke(FunctionName=functionname, InvocationType='RequestResponse') print(resp["Payload"].read()) EOF echo "Running write client..." | tee -a $LOG_FILE log_cmd "python3 writeclient.py" echo "Running read client..." | tee -a $LOG_FILE log_cmd "python3 readclient.py" # Step 11: Clean up resources echo "Resources created:" | tee -a $LOG_FILE for resource in "${CREATED_RESOURCES[@]}"; do echo "- $resource" | tee -a $LOG_FILE done echo "" | tee -a $LOG_FILE echo "==========================================" | tee -a $LOG_FILE echo "CLEANUP CONFIRMATION" | tee -a $LOG_FILE echo "==========================================" | tee -a $LOG_FILE echo "Do you want to clean up all created resources? (y/n): " | tee -a $LOG_FILE read -r CLEANUP_CONFIRM if [[ $CLEANUP_CONFIRM == "y" || $CLEANUP_CONFIRM == "Y" ]]; then cleanup else echo "Resources were not cleaned up. You can manually clean them up later." | tee -a $LOG_FILE fi echo "Script completed at $(date)" | tee -a $LOG_FILE

The following code example shows how to:

  • Create a public DNS namespace with Route 53 hosted zone integration

  • Create services discoverable via DNS queries and API calls

  • Register service instances with different discovery configurations

  • Discover services using both DNS queries and Cloud Map API

  • Verify service discovery using dig command and API calls

  • Clean up resources in proper order (instances, services, namespace)

Amazon 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 Cloud Map Private Namespace Tutorial Script # This script demonstrates how to use AWS Cloud Map for service discovery # with DNS queries and API calls # Exit on error set -e # Configuration REGION="us-east-2" NAMESPACE_NAME="cloudmap-tutorial.com" LOG_FILE="cloudmap-tutorial.log" CREATOR_REQUEST_ID=$(date +%s) # Function to log messages log() { local message="$1" echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" | tee -a "$LOG_FILE" } # Function to check operation status check_operation() { local operation_id="$1" local status="" log "Checking operation status for $operation_id..." while [[ "$status" != "SUCCESS" ]]; do sleep 5 status=$(aws servicediscovery get-operation \ --operation-id "$operation_id" \ --region "$REGION" \ --query "Operation.Status" \ --output text) log "Operation status: $status" if [[ "$status" == "FAIL" ]]; then log "Operation failed. Exiting." exit 1 fi done log "Operation completed successfully." } # Function to clean up resources cleanup() { log "Starting cleanup process..." if [[ -n "$FIRST_INSTANCE_ID" ]]; then log "Deregistering first service instance..." aws servicediscovery deregister-instance \ --service-id "$PUBLIC_SERVICE_ID" \ --instance-id "$FIRST_INSTANCE_ID" \ --region "$REGION" || log "Failed to deregister first instance" fi if [[ -n "$SECOND_INSTANCE_ID" ]]; then log "Deregistering second service instance..." aws servicediscovery deregister-instance \ --service-id "$BACKEND_SERVICE_ID" \ --instance-id "$SECOND_INSTANCE_ID" \ --region "$REGION" || log "Failed to deregister second instance" fi if [[ -n "$PUBLIC_SERVICE_ID" ]]; then log "Deleting public service..." aws servicediscovery delete-service \ --id "$PUBLIC_SERVICE_ID" \ --region "$REGION" || log "Failed to delete public service" fi if [[ -n "$BACKEND_SERVICE_ID" ]]; then log "Deleting backend service..." aws servicediscovery delete-service \ --id "$BACKEND_SERVICE_ID" \ --region "$REGION" || log "Failed to delete backend service" fi if [[ -n "$NAMESPACE_ID" ]]; then log "Deleting namespace..." aws servicediscovery delete-namespace \ --id "$NAMESPACE_ID" \ --region "$REGION" || log "Failed to delete namespace" fi log "Cleanup completed." } # Set up trap for cleanup on script exit trap cleanup EXIT INT TERM # Initialize log file > "$LOG_FILE" log "Starting AWS Cloud Map tutorial script" # Step 1: Create an AWS Cloud Map namespace log "Creating AWS Cloud Map namespace: $NAMESPACE_NAME" OPERATION_RESULT=$(aws servicediscovery create-public-dns-namespace \ --name "$NAMESPACE_NAME" \ --creator-request-id "cloudmap-tutorial-$CREATOR_REQUEST_ID" \ --region "$REGION") OPERATION_ID=$(echo "$OPERATION_RESULT" | jq -r '.OperationId') log "Namespace creation initiated. Operation ID: $OPERATION_ID" # Check operation status check_operation "$OPERATION_ID" # Get the namespace ID log "Getting namespace ID..." NAMESPACE_ID=$(aws servicediscovery list-namespaces \ --region "$REGION" \ --query "Namespaces[?Name=='$NAMESPACE_NAME'].Id" \ --output text) log "Namespace ID: $NAMESPACE_ID" # Get the hosted zone ID log "Getting Route 53 hosted zone ID..." HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \ --dns-name "$NAMESPACE_NAME" \ --query "HostedZones[0].Id" \ --output text | sed 's|/hostedzone/||') log "Hosted Zone ID: $HOSTED_ZONE_ID" # Step 2: Create the AWS Cloud Map services log "Creating public service..." PUBLIC_SERVICE_RESULT=$(aws servicediscovery create-service \ --name "public-service" \ --namespace-id "$NAMESPACE_ID" \ --dns-config "RoutingPolicy=MULTIVALUE,DnsRecords=[{Type=A,TTL=300}]" \ --region "$REGION") PUBLIC_SERVICE_ID=$(echo "$PUBLIC_SERVICE_RESULT" | jq -r '.Service.Id') log "Public service created. Service ID: $PUBLIC_SERVICE_ID" log "Creating backend service..." BACKEND_SERVICE_RESULT=$(aws servicediscovery create-service \ --name "backend-service" \ --namespace-id "$NAMESPACE_ID" \ --type "HTTP" \ --region "$REGION") BACKEND_SERVICE_ID=$(echo "$BACKEND_SERVICE_RESULT" | jq -r '.Service.Id') log "Backend service created. Service ID: $BACKEND_SERVICE_ID" # Step 3: Register the AWS Cloud Map service instances log "Registering first service instance..." FIRST_INSTANCE_RESULT=$(aws servicediscovery register-instance \ --service-id "$PUBLIC_SERVICE_ID" \ --instance-id "first" \ --attributes "AWS_INSTANCE_IPV4=192.168.2.1" \ --region "$REGION") FIRST_INSTANCE_ID="first" FIRST_OPERATION_ID=$(echo "$FIRST_INSTANCE_RESULT" | jq -r '.OperationId') log "First instance registration initiated. Operation ID: $FIRST_OPERATION_ID" # Check operation status check_operation "$FIRST_OPERATION_ID" log "Registering second service instance..." SECOND_INSTANCE_RESULT=$(aws servicediscovery register-instance \ --service-id "$BACKEND_SERVICE_ID" \ --instance-id "second" \ --attributes "service-name=backend" \ --region "$REGION") SECOND_INSTANCE_ID="second" SECOND_OPERATION_ID=$(echo "$SECOND_INSTANCE_RESULT" | jq -r '.OperationId') log "Second instance registration initiated. Operation ID: $SECOND_OPERATION_ID" # Check operation status check_operation "$SECOND_OPERATION_ID" # Step 4: Discover the AWS Cloud Map service instances log "Getting Route 53 name servers..." NAME_SERVERS=$(aws route53 get-hosted-zone \ --id "$HOSTED_ZONE_ID" \ --query "DelegationSet.NameServers[0]" \ --output text) log "Name server: $NAME_SERVERS" log "Using dig to query DNS records (this will be simulated)..." log "Command: dig @$NAME_SERVERS public-service.$NAMESPACE_NAME" log "Expected output would show: public-service.$NAMESPACE_NAME. 300 IN A 192.168.2.1" log "Using AWS CLI to discover backend service instances..." DISCOVER_RESULT=$(aws servicediscovery discover-instances \ --namespace-name "$NAMESPACE_NAME" \ --service-name "backend-service" \ --region "$REGION") log "Discovery result: $(echo "$DISCOVER_RESULT" | jq -c '.')" # Display created resources log "Resources created:" log "- Namespace: $NAMESPACE_NAME (ID: $NAMESPACE_ID)" log "- Public Service: public-service (ID: $PUBLIC_SERVICE_ID)" log "- Backend Service: backend-service (ID: $BACKEND_SERVICE_ID)" log "- Service Instance: first (Service: public-service)" log "- Service Instance: second (Service: backend-service)" # Ask user if they want to clean up resources read -p "Do you want to clean up all created resources? (y/n): " CLEANUP_RESPONSE if [[ "$CLEANUP_RESPONSE" == "y" || "$CLEANUP_RESPONSE" == "Y" ]]; then log "User confirmed cleanup. Proceeding with resource deletion." # Cleanup function will be called automatically on exit else log "User chose not to clean up resources. Exiting without cleanup." trap - EXIT exit 0 fi