Assign output from AWS CLI command to 2nd AWS CLI command - bash

I am writing automation task for creating AWS AMI image, the goal is get output from aws import-image (.ova to ami convert) and add the name in 2nd command:
importaskid=$(aws ec2 import-image --disk-containers Format=ova,UserBucket="{S3Bucket=acp17,S3Key=XXXXX.ova}" | jq -r '.ImportTaskId')
aws ec2 create-tags --resources echo $importaskid --tags 'Key=Name, Value=acp_ami_test'
I am able to $importaskid and see needed output but when use aws ec2 create-tags the AMI image created without name and the output from 2nd command is empty.
Appreciate your assistance.

This should work for you:
# set bash variable "importaskid":
importaskid=$(aws ec2 import-image --disk-containers Format=ova,UserBucket="{S3Bucket=acp17,S3Key=XXXXX.ova}" | jq -r '.ImportTaskId')
# Verify that importaskid is set correctly
echo $importaskid
# Now use it:
aws ec2 create-tags --resources "$importaskid" --tags 'Key=Name, Value=acp_ami_test'
The "$()" syntax for assigning the output of a command to a variable is discussed here: https://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/
The double quotes in "$importaskid" would be necessary if
the value of "$importaskid" happens to have spaces in it.
'Hope that helps!

thanks for reply, so when i run the command without echo $ImportTaskId
see below
aws ec2 create-tags --resource import-ami-XXXXXXXXXXXXX --tags Key=Name,Value='name_ami_test'
i got empty response and the name is not assigned in aws console so i will speak to AWS support/check syntax /check after the assign name to AMI ID and not to import-ami-XXXXXXXXXXXXXXXX

Related

Running aws secretsmanager get-secret-value --secret-id $test_env_variable --query "SecretString" throws error. what I am doing wrong here

when I run the following aws cli command and pass environment variable as --secret-id. aws cli throws the error. however when i pass the hardcoded value instead of environment variable, it start working just fine.
aws secretsmanager get-secret-value --secret-id $test_env_variable --query "SecretString"
ERROR:
usage: aws [options] [ ...] [parameters]
To see help text, you can run:
aws help
aws help
aws help
aws.exe: error: argument --secret-id: expected one argument
This happens, because your test_env_variable is most likely empty. Thus you have to ensure that it actually has secret id in the correct format.

SSH ProxyCommand using aws SSM session manager and bash script with select command

In my company when we SSH to our AWS EC2 instances we are required to use the aws CLI session-manager plugin for auth. Using this SSH config snippet works:
Host my-aws-host
ProxyCommand bash -c "aws ssm start-session --target 'i-0abc123def456hij' \
--document-name AWS-StartSSHSession --parameters 'portNumber=22' \
--region us-west-1 --profile MAIN"
However, when the EC2 instance is relaunched, which happens semi-regularly, the 'target' instance ID changes. When this happens, all users need to update their SSH config with the new ID. We don't have any sort of DNS that resolves these instances to a static hostname unfortunately, and so would need to somehow publish the new instance ID to all interested users.
So instead I wrote a bash script (ssh_proxy_command.sh) that first queries our AWS account to grab the current instance ID based on a known tag value, and use that for the target - here's a cut-down version:
#!/bin/bash
INSTANCE_ID=$(aws ec2 describe-instances --region us-west-1 \
--filters Name=tag:Name,Values=my-server-nametag* \
--query "Reservations[*].Instances[*].{Instance:InstanceId}" --output text)
aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartSSHSession --parameters 'portNumber=22' --region us-west-1 --profile MAIN
Now the SSH config looks like
Host my-aws-host
ProxyCommand bash -c "/path/to/my/ssh_proxy_command.sh %h"
This has been working fine. However, we have just started running multiple instances built from the same base image (AMI), and which use the same tags, etc. so the given describe-instances query now returns multiple instance IDs. So I tried wrapping the output returned by the query in a bash select loop, thinking I could offer the user a list of instance IDs and let them choose the one they want. This works when running the script directly, but not when it's used as the ProxyCommand. In the latter case when it reaches the select statement it prints out the options as expected, but doesn't wait for the user input - it just continues straight to the end of the script with an empty $INSTANCE_ID variable, which makes the aws ssm command fail.
I'm guessing this is a side-effect of the way SSH runs its ProxyCommands — from the ssh_config man page:
[the proxy command] is executed using the user's shell ‘exec’ directive [...]
I'm hoping I can find a way around this problem while still using SSH config and ProxyCommand, rather than resorting to a complete stand-alone wrapper around the ssh executable and requiring everyone use that. Any suggestions gratefully accepted...
host my-aws-host
ProxyCommand aws ssm start-session --target $(aws ec2 describe-instances --filter "Name=tag:Name,Values=%h" --query "Reservations[].Instances[?State.Name == 'running'].InstanceId[]" --output text) --document-name AWS-StartSSHSession --parameters portNumber=%p
The above will dynamically filter for your target-id based on host name (%h) provided so you can login using ssh my-aws-host. I personally have a prefix for all my machines in AWS so I ssh config is as follows:
host your-custom-prefix-*
ProxyCommand aws ssm start-session --target $(aws ec2 describe-instances --filter "Name=tag:Name,Values=%h" --query "Reservations[].Instances[?State.Name == 'running'].InstanceId[]" --output text) --document-name AWS-StartSSHSession --parameters portNumber=%p
This works only when the name of your machines in AWS match the host name provided.

Problem with creating EBS snapshot on server(Linux EC2 instance)

I am working on a task that required to run a script on a server, The script will grab instance id, create snapshot and run yum update -y command and reboot the server.
#!/bin/bash
set -eu
# Set Vars
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export REGION=$(curl --silent http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/[a-z]$//')
export INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
echo $AWS_ACCOUNT_ID
echo $REGION
# Fetch VolumeId
volumeid=$(aws ec2 describe-instances --region $REGION --instance-id "$INSTANCE_ID" --filters Name=instance-state-name,Values=running --query "Reservations[*].Instances[].[BlockDeviceMappings[*].{VolumeName:Ebs.VolumeId}]" --output text)
echo $INSTANCE_ID
echo $volumeid
# Create snapshot
aws ec2 create-snapshot --region $REGION --volume-id $volumeid --description "Test-Snapshot-$INSTANCE_ID"
read -p "waiting a while to complete creation of EBS snapshot" -t 100
echo -e "\x1B[01;36m Snapshot has been created \x1B[0m"
I can get the Instance id but when I am trying to create snapshot id from Instance id, I am getting following error:
ERROR
us-east-1
An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
Thank you so much in advance for your support.
Your instance, and with that your script is missing the ec2:DescribeInstances permission to run the aws ec2 describe-instances command.
You should attach that permission to the instance role that is assigned to the instance (or create a new role with the permissions attached if there is none assigned yet).
Your IAM permissions do not grant access to DescribeInstances.
If you’re using an IAM role for the instance check it’s policies.
If it’s a user then make sure the credentials are being retrieved, either via aws credentials file or via environment variable

shell script to start ec2 instances and ssh and introducing delay in second command

I have written a small shell script to automate the starting and loggin in to my aws instances via terminal.
#!/bin/bash
aws ec2 start-instances --instance-ids i-070107834ab273992
public_ip=aws ec2 describe-instances --instance-ids i-070107834ab273992 \
--query 'Reservations[*].Instances[*].PublicDnsName' --output text
AWS_KEY="/home/debian/cs605 data management/assignment6/mumbai instance keys"
ssh -v -i "$AWS_KEY"/mumbai-instance-1.pem\
ec2-user#$public_ip
~
~
The problem is public_ip variable I want it to be used in line ssh
1) how do I get value of a variable to use in a command.
2) The instance takes some time to boot when it is switched on from power off to power on so how do I keep checking that instances has been powered on after aws start instance command in the script or retrieve the public ip once it has started fully and then ssh into it.
I am not good at python know just basics so is there a pythonic way of doing it.If there is an example script some where that would be better for me to have a look at it.
You do not set the variable public_ip in your script. It would not surprise me if the script complained about "ec2: command not found".
To set the variable:
public_ip=$(aws ec2 describe-instances --instance-ids i-070107834ab273992 --query 'Reservations[*].Instances[*].PublicDnsName' --output text)
(disclaimer: I have not used aws so I assume that the command is correct).
The information on whether an instance is running should be available with
aws ec2 describe-instance-status
You may want to apply some filters and/or grep for a specific result. You could try polling with a while loop:
while ! aws ec2 describe-instance-statusv --instance-ids i-070107834ab273992 | grep 'something that characterizes running' ; do
sleep 5
done

Bash quotes being tricky

I have this command
aws --profile whatever ec2 describe-instances
The short story is that I no choice but to have this '--profile ' section in this command, but I need to be able to use this feature/bug using quotes:
aws --profile "" ec2 describe-instances
BUT the quotes must also be an environment variable, like so
aws --profile $AWS_PROFILE ec2 describe-instances
But I need that variable to resolve the exact same way as the line above it.
I have tried
AWS_PROFILE='""'
and
AWS_PROFILE=
and
AWS_PROFILE=""
And it never resolves the same way. Is there anything I can do?
Any quotes you put inside the variable are literal. However, in your desired command aws --profile "" ec2 describe-instances, the quotes are syntactic: That is, they're shell syntax describing how the shell is going to create a literal array of C strings to pass to the execv syscall (and how one of those strings needs to be empty); the quotation marks aren't actually passed to the aws command themselves.
So:
AWS_PROFILE=
aws --profile "$AWS_PROFILE" ec2 describe-instances
...will behave identically to
aws --profile "" ec2 describe-instances

Resources