OpsFire: Puppet Ops with a touch of BASH

So on today's agenda was removing our loadtest cluster. Pretty simple: term some EC2 instances, remove the auto scaling group, Code Deploy, Jenkins, etc. Then I hit Puppet and I saw...

Well I saw this:

$  sudo puppet cert list -a | grep api-loadtest
+ "api-loadtest-us-east-1e-i-a8fuib28afd.example.com" (69:B6:2A:E1:5B:BE:B8:8E:22:AD:42:CA:CF:6B:4E:72)

((( 900+ more lines )))

+ "api-loadtest-us-east-1e-i-q78uifasdfi.example.com" (95:69:93:BE:B0:53:49:89:D8:3B:23:53:83:8A:8E:AB)

Ah. So it seems as though whenever the loadtest cluster was initially configured (pre-me) it wasn't entirely cleaning up after itself. Alas.

Option 1: Manually remove each api-loadtest cert.
Option 2: Programmaticaly remove all the api-loadtest certs.

Yeah, we're going with option 2. The way I accomplished this was using the following:

sudo puppet cert list -a | grep api-loadtest | awk '{ gsub(/"/, "", $2); print $2 }' | while IFS= read -r NODE ; do sudo puppet cert clean ${NODE}; done

Let's break this down:

sudo puppet cert list -a | grep api-loadtest

So this is just getting all the Puppet certs again and searching for the ones that have api-loadtest in the resulting line of text (in this case, in the name).

awk '{ gsub(/"/, "", $2); print $2 }'

The results of the last part are piped through this awk function. awk is used for processing text on the command line, here we're taking this output:

+ "api-loadtest-us-east-1e-i-q78uifasdfi.example.com" (95:69:93:BE:B0:53:49:89:D8:3B:23:53:83:8A:8E:AB)

And making it just:

api-loadtest-us-east-1e-i-q78uifasdfi.example.com

The print $2 returns the "api-loadtest... portion and gsub strips the ".

Now for this part:

while IFS= read -r NODE

This part reads in each line of the results (api-loadtest...) and stores it in the environmental variable NODE, which is then used by:

sudo puppet cert clean ${NODE}

To remove the cert.

nixing the while loop

There is also another way to do this: with xargs. In a situation where you are going through one "thing" (e.g. "line") at a time that is separated on spaces, xargs is a good fit. The new alternative would be:

sudo puppet cert list -a | grep api-loadtest | awk '{ print $2 }' | xargs -n1 sudo puppet cert clean

sudo puppet cert list -a | grep api-loadtest | awk ... is covered above, so I'll just get right back to xargs. xargs takes an input, spilts on whitespace, and uses it as an argument to the command, in this case sudo puppet cert clean. -n1 tells xargs to use one result at a time. To better visualize -n#, try the following in your HOME directory:

ls | xargs -n1 echo "-n1 output: "

ls | xargs -n2 echo "-n2 output: "

Using a while loop would have been a great thing to do for non-whitespaced results, using xargs in this case makes it a bit easier for the brain to parse exactly what is happening. Note that with xargs I also no longer need to strip the "s for an added bonus.

Documented on my frequently used assets page.