How to open shell with colours using AWS ECS execute-command? - bash

I'm using execute-command to open a shell in a AWS Fargate container:
aws ecs execute-command --cluster MtStack-MyCluster7G3C63FE-D8338439438C \
--task d5d35723871267123672312a \
--interactive \
--command "/bin/bash"
The does not show any colours. Is there a way to enable colours?

Related

how to iterate over aws cli result using bash for loop ? [describe-images]

Goal: find specific AMI's and copy them to another AWS region.
using describe-images and its filter i get a list of ImageId and Name,
AMI_LIST=$(aws ec2 describe-images --filters "Name=tag:Name,Values=*one*,*two*,*three*,*four*" \
"Name=state,Values=available" "Name=tag:Name,Values=${CUSTOMER_NAME}*" \
--query 'Images[*].{ID:ImageId,NAME:Name}' --output text)
echo $AMI_LIST
result:
ami-036ba4ef9fa1d148d big394_one_1 ami-06d13684f11138f1f big394_two_3 ami-0706803a11e21946d big394_two_1 ami-094043f896db39243 big394_two_2 ami-0c11ff60c981c2273 big394_three_1 ami-0d0b30fcc69f30af8 big394_four_1
then i want to copy the images to another AWS region using a loop:
for ami in $AMI_LIST; do
aws ec2 copy-image --source-image-id ${ami[0]} --source-region us-east-1 --region us-west-2 --name ${ami[2]}
done
ofc it does not work because ${ami[0]} and ${ami[1]} has no meaning, but they represent what i would like to achieve.
i did try to play with converting the list to array but without success.
Thanks.
This should achieve what you expected :
aws ec2 describe-images --filters "Name=tag:Name,Values=*one*,*two*,*three*,*four*" \
"Name=state,Values=available" "Name=tag:Name,Values=${CUSTOMER_NAME}*" \
--query 'Images[*].{ID:ImageId,NAME:Name}' --output text \
| while read ami name; do
aws ec2 copy-image --source-image-id $ami --source-region us-east-1\
--region us-west-2 --name $name
done

Create Jenkinsfile from "execute shell" commands

I have a series of Execute shell boxes on a Jenkins build. After 3 days of Google and watching videos I need help. I am more a sysadmin than a coder so I'm having difficulty in creating a Jenkinsfile with the correct options and syntax. Can anyone advise? I need to create a pipeline. Anything in <name> is like that for security reasons, I have the real values in the files.
Execute shell
mkdir -p deploy
Execute shell
cp -R code/api deploy/
cp docker/Dockerfile.dev deploy/
(cd deploy/api/<Name>.<Name>.Web/ && aws s3 cp --recursive --region=eu-west-1 s3://config.<name>/audience-view/atg/dev/API/ .)
Execute shell
cd deploy && docker build -t <name> -f Dockerfile.dev .
Execute shell
aws ecr get-login --region eu-west-1 > docker_login.sh && chmod +x
docker_login.sh && ./docker_login.sh
docker tag <name>:latest 543573289192.dkr.ecr.eu-west-
1.amazonaws.com/<name>:latest
docker push <name>.dkr.ecr.eu-west-1.amazonaws.com/<name>:latest
Execute shell
docker rmi audience-view-dev-api
docker rmi 543573289192.dkr.ecr.eu-west-1.amazonaws.com/<name>:latest
Execute shell
RUNNING_TASKS=$(aws ecs list-tasks --region=eu-west-1 --cluster <name> --family <name> --query 'taskArns')
if [ "$RUNNING_TASKS" != "[]" ]; then
TASK_ARN=$(aws ecs list-tasks --region=eu-west-1 --cluster a<name> --family <name> --query 'taskArns[0]' | sed 's/\"//g')
aws ecs stop-task --region=eu-west-1 --cluster=<name> --task=$TASK_ARN --reason="Deployment from Jenkins"
while [ $RUNNING_TASKS != "[]" ]; do
sleep 5
RUNNING_TASKS=$(aws ecs list-tasks --region=eu-west-1 --cluster <name> --family <name> --query 'taskArns')
done
fi
Execute shell
TASK_ARN=$(aws ecs start-task --region=eu-west-1 --cluster <name> --task-definition <name> --container-instances 5f0c5b75-64a2-45cf-8ced-d6a6d13d2666 --query 'tasks[0].taskArn' | sed 's/arn:aws:ecs:eu-west-1:543573289192:task\///' | sed 's/\"//g')
TASK_STATUS=$(aws ecs describe-tasks --region=eu-west-1 --cluster <name> --tasks $TASK_ARN --query 'tasks[0].lastStatus')
while [ $TASK_STATUS == "PENDING" ]; do
echo $TASK_STATUS
TASK_STATUS=$(aws ecs describe-tasks --region=eu-west-1 --cluster <name> --tasks $TASK_ARN --query 'tasks[0].lastStatus' | sed 's/\"//g')
if [ $TASK_STATUS == "STOPPED" ]; then
echo $(aws ecs describe-tasks --region=eu-west-1 --cluster <name> --tasks $TASK_ARN --query 'tasks[0].containers[0].exitCode')
exit 1
fi
done
Jenkins is best used as the glue to connect all the build pieces together, not the build script itself. As Alfe mentioned, it would be best to have this all in a shell script and then run the shell script with Jenkins.
BUT, if you really want to do this in a Pipeline job, it would look something like this (declarative pipeline):
pipeline {
agent any
stages {
stage('setup') {
steps {
sh "mkdir -p deploy"
}
stage('nextStage') {
steps {
sh """
cp -R code/api deploy/
cp docker/Dockerfile.dev deploy/
(cd deploy/api/<Name>.<Name>.Web/ && aws s3 cp --recursive --region=eu-west-1 s3://config.<name>/audience-view/atg/dev/API/ .)
"""
}
}
stage('anotherStage') {
steps {
echo "repeat for all your shell steps"
}
}
}
}

Stopping task on AWS ECS via CLI (program output as argument input bash)

I'm trying to kill a task in ECS via the CLI.
I can fetch the task name by executing:
aws ecs list-tasks --cluster "my-cluster" --service-name "my-service" | jq .taskArns[0]
which outputs:
"arn:aws:ecs:REGION:ACCOUNT-ID:task/TASK-GUID"
the full ARN of the task as a string (I have a global defaulting output to JSON).
I can kill the task by executing:
aws ecs stop-task --cluster "my-cluster" --task "task-arn"
However when I try and combine it:
aws ecs stop-task --cluster "my-cluster" --task $(aws ecs list-tasks --cluster "my-cluster" --service-name "my-service" | jq .taskArns[0])
I get:
An error occurred (InvalidParameterException) when calling the StopTask operation: taskId longer than 36.
I know this is probably bash program output/argument input interpolation but I've looked that up and cannot get to the bottom of it.
AWS cli essentially has jq built in so a better (simpler) way to query your task arn would be with:
aws ecs list-tasks --cluster "my-cluster" --service "my-service" --output text --query taskArns[0]
Maybe that helps someone:
Killing task with unique task definition name:
OLD_TASK_ID=$(aws ecs list-tasks --cluster ${ecsClusterName} --desired-status RUNNING --family ${nameTaskDefinition} | egrep "task/" | sed -E "s/.*task\/(.*)\"/\1/")
aws ecs stop-task --cluster ${ecsClusterName} --task ${OLD_TASK_ID}
Killing multiple tasks (same task definition name but different task ids):
OLD_TASK_IDS=$(aws ecs list-tasks --cluster ${ecsClusterName} --desired-status RUNNING --family ${nameTaskDefinition} | egrep "task/" | sed -E "s/.*task\/(.*)\"/\1/" | sed -z 's/\n/ /g')
IFS=', ' read -r -a array <<< "$OLD_TASK_IDS"
for element in "${array[#]}"
do
aws ecs stop-task --cluster ${ecsClusterName} --task ${element}
done
One-liner command to stop tasks in cluster/service
for taskarn in $(aws ecs list-tasks --cluster ${YOUR_CLUSTER} --service ${YOUR_SERVICE} --desired-status RUNNING --output text --query 'taskArns'); do aws ecs stop-task --cluster ${YOUR_CLUSTER} --task $taskarn; done;
One-liner version of nathanpecks great answer:
aws ecs stop-task --cluster "my-cluster" --task $(aws ecs list-tasks --cluster "my-cluster" --service "my-service" --output text --query taskArns[0])

Deleting multiple Auto scaling groups in one shot: AWS CLI

I have multiple Autoscaling groups which needs to be deleted. For eg: I have ASGs awsLC1 xyzLC2 aLC3. I have found them using AWS CLI with below query:
aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[? contains(AutoScalingGroupName,'LC')].AutoScalingGroupName" --output text
It gives me a list on console. However delete-auto-scaling-group only takes 1 ASG (auto scaling group) name in parameter.
How can I do that?
Any way to automate this using bash programming?
Thanks!
The CLI doesn't support deleting multiple ASGs. You can try a simple bash script:
$ for group in `aws autoscaling describe-launch-configurations --query "LaunchConfigurations[?contains(LaunchConfigurationName,'LC')].[LaunchConfigurationName]" --output text`
> do
> echo $group
> done
Once you verify the groups, delete them:
$ for group in `aws autoscaling describe-launch-configurations --query "LaunchConfigurations[?contains(LaunchConfigurationName,'LC')].[LaunchConfigurationName]" --output text`
> do
> aws autoscaling delete-auto-scaling-group --auto-scaling-group-name $group
> done
EDIT
Based on #JordonPhillips input, you can use -I option of xargs to come up with a one liner:
aws autoscaling describe-launch-configurations --query "LaunchConfigurations[?contains(LaunchConfigurationName,'LC')].[LaunchConfigurationName]" --output text | xargs -I aws autoscaling delete-auto-scaling-group --auto-scaling-group-name

Bash script to update docker login not functioning correctly

I'm trying to script updating of the login keys to the AWS docker ECR on a CoreOS instance.
If I run:
docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws ecr get-login
I get as output:
docker login -u AWS -p CiBwm0YaISJeRtJ ... -e none https://123456789012.us-east-1.amazonaws.com
If I copy and run that, it works perfectly. If I don't but instead use this form:
$(docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws ecr get-login)
It fails with an error.
/v0/: unable to ping registry endpoint https://123456789012.us-east-1.amazonaws.com
If I try to assign it to a variable, things get weird.
var=$(docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws ecr get-login)
echo "'$var' string"
Oddly, when I try to quote the string and echo it, the final quote appears in an unexpected place.
docker login -u AWS -p CiBwmEwHgYJ ... YIZIAWUDBAEuMisGdv0KB' stringivOyPO+qNJ3zo87RXwWlOW8TnCtGRd6k6tb0Z35xL2IKMO194+1va56lH0am -e none https://123456789012.dkr.ecr.us-east-1.amazonaws.com
It's quite a long string, is there perhaps some sort of buffer overflow problem here?
How might I get around it?
I've used aws ecr get-login before as input to eval to accomplish an actual login. Doing the same on my CoreOS machine with a command like yours fails with a similar problem to yours:
$ eval $(docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login)
/v0/: unable to ping registry endpoint https://123456789012.dkr.ecr.us-east-1.amazonaws.com1.amazonaws.com
: no such host: lookup 123456789012.dkr.ecr.us-east-1.amazonaws.com.us-east-1.amazonaws.com
/ca.crte daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/123456789012.dkr.ecr.us-east-1.amazonaws.com
I used good ol' set -x to turn on debugging so I could see exactly what commands were being executed:
$ docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login
+ docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login
docker login -u AWS -p CiBwm...hb9E= -e none https://123456789012.dkr.ecr.us-east-1.amazonaws.com
$ eval $(docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login)
++ docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login
+ eval docker login -u AWS -p CiBwm...DES0= -e none $'https://123456789012.dkr.ecr.us-east-1.amazonaws.com\r'
++ docker login -u AWS -p CiBwm...DES0= -e none $'https://123456789012.dkr.ecr.us-east-1.amazonaws.com\r'
/v0/: unable to ping registry endpoint https://123456789012.dkr.ecr.us-east-1.amazonaws.com1.amazonaws.com
: no such host: lookup 123456789012.dkr.ecr.us-east-1.amazonaws.com.us-east-1.amazonaws.com
/ca.crte daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/123456789012.dkr.ecr.us-east-1.amazonaws.com
Wait, what? The repository URL is being turned into $'https://123456789012.dkr.ecr.us-east-1.amazonaws.com\r' when the command is fed into eval, which is causing it to be evaluated in a very bizarre manner. That \r seemed like the problem, so I fed the output of the docker command into a text file and then opened it in binary mode with Vim to check. Sure enough, it's a pesky carriage return character. Removing that character with sed did the trick for me:
$ eval $(docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login | sed -e 's/^M//')
++ sed -e $'s/\r//'
++ docker run --rm --env-file=/etc/aws/environment -ti xueshanf/awscli:latest aws --region=us-east-1 ecr get-login
+ eval docker login -u AWS -p CiBwm...88A8= -e none https://123456789012.dkr.ecr.us-east-1.amazonaws.com
++ docker login -u AWS -p CiBwm...88A8= -e none https://123456789012.dkr.ecr.us-east-1.amazonaws.com
WARNING: login credentials saved in /home/core/.docker/config.json
Login Succeeded
Note: to remove the carriage return, you'll need to type Ctrl+V Ctrl+M to correctly insert the ^M character.
Hope this helps! =]
Docker is inserting the extra carriage return, because you've told it to allocate a a pseudo-tty (with the option -t). If you remove the -ti, you won't need to use sed.
eval $(docker run --rm --env-file=/etc/aws/environment \
xueshanf/awscli:latest aws ecr get-login)

Resources