Reputation: 249
The background of my question is loaded; but I'd like to focus on just the jq
portion in this current piece (although if you could help in its entirety, it'd be so very much welcomed and appreciated).
I have a Terraform spec that I've successfully applied to create an autoscaling group in AWS (re: Terraform provisioning I will ask on a separate question, if perhaps there's a better way than what I'm doing). I had wanted to run some provisioning in each of the produced instances, and in so doing, I decided to couple it with an ansible
command.
Ansible, as you may know, runs on inventory/host file. Consequently, I'd have to update my host file each time AWS scales up or down in order to successfully run the following ansible ad-hoc command ansible -i ./myansible.hostfile myawsinstances -a "reprovisioning_command"
(which itself has a different set of issues, tbd.)
On the part of creating the ansible host file, I got what I needed using the following command:
command sample 1
aws ec2 describe-instances | jq .Reservations[].Instances[].PublicIpAddress | sed 's/"//g' | awk '{print "inst"$1 " ansible_ssh_host="$1 " ansible_ssh_user=ubuntu"}' > myansible.hostfile
output sample 1 in myansible.hostfile
inst[ip_no1] ansible_ssh_host=[ip_no1] ansible_ssh_user=ubuntu
inst[ip_no2] ansible_ssh_host=[ip_no2] ansible_ssh_user=ubuntu
It seems to me rather long and somewhat convoluted.
If I were to just use jq
alone along with its string operation facilities, such as:
command sample 2
aws ec2 describe-instances | jq '"inst" + .Reservations[].Instances[].PublicIpAddress + " ansible_ssh_hosts=" + .Reservations[].Instances[].PublicIpAddress + " ansible_ssh_user=ubuntu"' > myansible.hostfile
I would receive dupes of the output like so:
output sample 2 in myansible.hostfile
inst[ip_no1] ansible_ssh_host=[ip_no1] ansible_ssh_user=ubuntu
inst[ip_no2] ansible_ssh_host=[ip_no2] ansible_ssh_user=ubuntu
inst[ip_no1] ansible_ssh_host=[ip_no1] ansible_ssh_user=ubuntu
inst[ip_no2] ansible_ssh_host=[ip_no2] ansible_ssh_user=ubuntu
Presumably because I'm calling the object selectors twice in the same command. The question is:
a. Is there a cleaner command expression that I could use instead of (command sample 1) to achieve the same (output sample 1)?
b. What would be the correct way to strictly use jq
command like in (command sample 2) in order to produce the desired (output sample 1) without dupes like in the (output sample 2)?
Thanks much in advance.
Upvotes: 1
Views: 370
Reputation: 56877
I'm not sure why you're setting an Ansible inventory name that includes the IP address as this seems pretty pointless to me as it doesn't give it a human readable name or add anything useful compared to just using the IP address.
If you're happy with ditching that requirement then in reality you can just use the query
option of the AWS CLI and ditch jq
and your formatting:
cat <<EOF > hosts-file.ini
[all:vars]
ansible_ssh_user=ubuntu
[all]
EOF
aws ec2 describe-instances --query 'Reservations[*].Instances[*].PublicIpAddress' --output text >> hosts-file.ini
This will set some inline vars at the all level to set the SSH user to be ubuntu
and then dump all of the EC2 instance's public IP addresses under the all
block.
Upvotes: 1
Reputation: 116780
First, jq's -r
option will remove the outermost quotation marks from JSON string outputs.
Second, the following jq filter, used in conjunction with the aforementioned -r
option, should be sufficient to achieve your goals, though it's hard to verify since you haven't provided an MCVE:
.Reservations[].Instances[].PublicIpAddress
| "inst" + . + " ansible_ssh_hosts=" + . + " ansible_ssh_user=ubuntu"
Upvotes: 2