Shell script syntax, escape character - shell

I have a shell script as given below. This script actually add AWS instance in autoscalling scale in protection group. When I run individual commands that went fine. But when I created a shell file and tried to execute same there are error. See below script
set -x
INSTANCE_ID=$(wget -q -O - http://169.254.169.254/latest/meta-data/instance-id)
ASG_NAME=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" --region us-east-2 | jq '.Tags[] | select(.["Key"] | contains("a:autoscaling:groupName")) | .Value')
ASG_NAME=$(echo $ASG_NAME | tr -d '"')
aws autoscaling set-instance-protection --instance-ids $INSTANCE_ID --auto-scaling-group-name $ASG_NAME --protected-from-scale-in --region us-east-2
error is as given below. I think issue is with second line. It is not able to get ASG_NAME, I tried some of escape character but nothing is working.
+++ wget -q -O - http://169.254.169.254/latest/meta-data/instance-id
++ INSTANCE_ID=i-----
+++ aws ec2 describe-tags --filters Name=resource-id,Values=i------ --region us-east-2
+++ jq '.Tags[] | select(.["Key"] | contains("a:autoscaling:groupName")) | .Value'
++ ASG_NAME=
+++ echo
+++ tr -d '"'
++ ASG_NAME=
++ aws autoscaling set-instance-protection --instance-ids i---- --auto-scaling-group-name --protected-from-scale-in --region us-east-2
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:
aws help
aws <command> help
aws <command> <subcommand> help
aws: error: argument --auto-scaling-group-name: expected one argument
> Blockquote

Solved issue by recommendation of #chepner. Modified second line by
ASG_NAME=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" --region us-east-2 --query 'Tags[1].Value')

Related

List all EC2 Instances - AWSCLI

I want to list all ec2 instances for each account we have on ~/.aws/credentials, but the aws ec2 describe-instances doesn't return anything.
ACC=$(cat ~/.aws/credentials | egrep "\[.*\]" | cut -d '[' -f2 | cut -d ']' -f1 | grep -v default | sort)
FILE="${HOME}/ec2.csv"
echo -e "ACCOUNT;EC2" > ${FILE}
for account in ${ACC}
do
for region in $(aws ec2 describe-regions --profile default --region sa-east-1 --output text | cut -f3)
do
EC2=$(aws ec2 describe-instances --profile ${account} --region ${region} --query "Reservations[*].Instances[*].{PrivateIP:PrivateDnsName,Name:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output text)
echo -e "${account};${EC2}" >> ${FILE}
done
done
i solved this issue replacing the default profile on the second for.
for region in $(aws ec2 describe-regions --profile ${account} --region sa-east-1 --output text | cut -f3)
This script works, i hope this script can help's.

xargs not splitting on whitespace from aws cli output

This commands returns all the AWS regions separated by whitespace:
aws ec2 describe-regions --query 'Regions[*].RegionName' --output text
eu-north-1 ap-south-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2
I'm trying to pipe this to xargs but it's seeing it as a single string:
aws ec2 describe-regions --query 'Regions[*].RegionName' --output text | gxargs -I {} aws cloudformation list-stacks --region {}
Invalid endpoint: https://cloudformation.eu-north-1 ap-south-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2.amazonaws.com
gxargs: aws: exited with status 255; aborting
gxargs is just gnu xargs (I'm on Mac).
Also, tried this to use jmespath to create a string from an array with a specific delimiter (which I could use with xargs):
aws ec2 describe-regions --query 'Regions[*].join(",",#.RegionName)'
In function join(), invalid type for value: None, expected one of: ['string'], received: "null"
EDIT: just following up, this is what I wound up with. It insists on throwing an error when it doesn't find a stack- probably the same for other aws cli commands
aws ec2 describe-regions --query 'Regions[*].RegionName' --output text | gxargs -n 1 sh -c 'aws cloudformation describe-stacks --stack-name findme --region $0 || true'
Here's man xargs for -I:
-I replace-str
Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks
do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.
You can use xargs -n 1 aws cloudformation list-stacks --region instead

To run aws ECR scan commands in jenkinsfile

Trying to run below 2 commands in Jenkins file
NOTE: below commands are working fine locally where Jenkins is installed
sh ''' aws ecr start-image-scan --registry-id 123 \
--repository-name test1 \
--image-id imageTag=${BUILD_NUMBER} --output json | tee ecr_start_scan_${BUILD_NUMBER}.txt'''
sh ''' aws ecr describe-image-scan-findings --registry-id 123 \
--repository-name test \
--image-id imageTag=${BUILD_NUMBER} --output json | tee ecr_scanResult_${BUILD_NUMBER}.txt'''
Below is the output for both the commands:
+ aws ecr start-image-scan --repository-name valhalla --image-id imageTag=13 --region ap-southeast-1 --output json
+ tee ecr_start_scan_13.txt
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:
aws help
aws <command> help
aws <command> <subcommand> help
aws: error: argument operation: Invalid choice, valid choices are:
batch-check-layer-availability | batch-delete-image
batch-get-image | complete-layer-upload
create-repository | delete-lifecycle-policy
delete-repository | delete-repository-policy
describe-images | describe-repositories
get-authorization-token | get-download-url-for-layer
get-lifecycle-policy | get-lifecycle-policy-preview
get-repository-policy | initiate-layer-upload
list-images | put-image
put-lifecycle-policy | set-repository-policy
start-lifecycle-policy-preview | upload-layer-part
get-login | help
Update AWS CLI version. I had the same issue with aws-cli/1.11.13. But got the expected result in aws-cli/1.18.16
Yes updating the AWS CLI Version fixes the problem but I think there's a missing step in the middle which is aws ecr wait image-scan-complete because scan results don't show up instantaneously so this command waits till results are accessible.

passing command from awk to the next command using xargs

I am using AWS EC2 CLI to perform a filter on stopped instances, then create an AMI out of these with the AMI name taken from the instance tag.
aws ec2 describe-instances --output text --profile proj --query 'Reservations[*].[Instances[*].[InstanceId, InstanceType, State.Name, Platform, Placement.AvailabilityZone, PublicIpAddress, PrivateIpAddress,[Tags[?Key==`Name`].Value][0][0]]]' --filter --filters Name=instance-state-name,Values=stopped | awk '{print $1, $8}' | xargs -n2 aws ec2 create-image --profile proj --instance-id {} --name {} --no-reboot
how to let args differentiate the two different parameters from AWK (instnaceid, instance name tag), thereby it can be correctly pumped into the ec2 create-image on the instance-id and --name parameter accordingly
You do not need awk.Using AWS CLI, you are extracting 8 values first and then using awk to extract 2 values from that 8 values. Why? Just extract the 2 values from AWS CLI without using awk.
--query 'Reservations[*].[Instances[*].[InstanceId, [Tags[?Key==`Name`].Value][0][0]]]'
will return only the values you are interested in. Then use xargs to pass the arguments to your next command.
xargs -n2 command --arg1 $1 --arg2 $2
Your entire command becomes:
aws ec2 describe-instances --output text --profile proj --query 'Reservations[*].[Instances[*].[InstanceId, [Tags[?Key==`Name`].Value][0][0]]]' --filter --filters Name=instance-state-name,Values=stopped | xargs -n2 aws ec2 create-image --profile proj --instance-id $1 --name $2 --no-reboot

Select tag of Autoscaling Group inside of instance using AWS CLI

When I inside of instance that have Autoscaling Group. I'm trying to select some specific tag of Autoscaling Group. i know that I can use AWS CLI command "aws autoscaling describe-tags".
So I wrote some .sh file. Than contain:
#!/bin/sh
#Instance ID
InstanceID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`
#Allocation ID from Autoscaling tags
Autoscaling=`aws ec2 describe-tags --filters "Name=resource-id,Values=$InstanceID" "Name=key,Values=aws:autoscaling:groupName"`
AllocationID=`aws autoscaling describe-tags --filter "Name=key,Values=$Autoscaling"| select(["Value"] | contains("eipalloc"))`
#Assigning VPC Elastic IP to Instance via Allocation ID
aws ec2 associate-address --instance-id $InstanceID --allocation-id $AllocationID
It doesn't work only because I can't select value in this way. Who can tell me how I can properly select some specific tag?
Thanks!
Looks terrible, but it works:
#!/bin/sh
#Instance ID
InstanceID=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id`
#Elastic IP captured through the AllocationID Autoscaling tag
ScalingGroup=`aws ec2 describe-tags --filters "Name=resource-id,Values=$InstanceID" "Name=key,Values=aws:autoscaling:groupName" | jq '.Tags[] | .Value'`
AllocationID=`aws autoscaling describe-tags --filters "Name=auto-scaling-group,Values=$ScalingGroup" | jq '.Tags[] | select(.["Key"] | contains("AllocationID")) | .Value'`
AllocationID=`echo $AllocationID | tr -d '"'`
#Assigning Elastic IP to Instance
aws ec2 associate-address --instance-id $InstanceID --allocation-id $AllocationID

Resources