cbtshare has asked for the wisdom of the Perl Monks concerning the following question:

Hello All, I have a script that is suppose to check aws api for cloudformation stacks that are out of sync and then send an email. The script works for the most part but it seems to work irrationally when doing a search for the word SYNC.Below is put output that shows all of the stacks are in sync pulled from the aws api, but at times the script reads some as IN_SYNC and other times goes to the else section of the script which will send an email if there is a script found to be out of sync. An example of the output is below (the top shows the the script is in sync and should output Setup ok, but some even though it shows insync says it is when it is not)
IN_SYNC Stack AviatrixGatewaySetup is OK!! IN_SYNC Stack ChildEC2 is out of sync!! SEND EMAIL NOW!! IN_SYNC IN_SYNC Stack ChildEFS is OK!! IN_SYNC IN_SYNC Stack ChildElasticache is OK!! IN_SYNC IN_SYNC Stack ChildFargate is OK!! IN_SYNC Stack ChildRDS is OK!! IN_SYNC IN_SYNC Stack ChildSQs is OK!! IN_SYNC Stack ChildSns is OK!! IN_SYNC Stack EFDEVProject is out of sync!! SEND EMAIL NOW!! IN_SYNC Stack S3 is out of sync!! SEND EMAIL NOW!! IN_SYNC Stack Users is OK!! IN_SYNC IN_SYNC Stack VPC2 is OK!! IN_SYNC IN_SYNC Stack parent is OK!! IN_SYNC Stack test-sample-function is OK!!
My code
#!/usr/bin/perl use strict; use warnings; my $ID; my @FINAL; my $SYNC; my $stack; my $DETECTION; #my $email=''; my @STACK_NAME=qx(aws cloudformation list-stacks --stack-status-filter + CREATE_COMPLETE UPDATE_COMPLETE --query 'sort_by(StackSummaries, &S +tackName)[*].[StackName]' --output text ); for $stack (@STACK_NAME) { chomp($stack); $ID=qx(aws cloudformation detect-stack-drift --stack-name "$stack" | j +q .[] | awk -F '\"' '{print \$2}'); chomp($ID); ##Get status based on ID do { $SYNC=qx(aws cloudformation describe-stack-drift-detection-status +--stack-drift-detection-id $ID | grep StackDriftStatus | awk -F '\"' +'{print \$4}'); $DETECTION=qx(aws cloudformation describe-stack-drift-detection-st +atus --stack-drift-detection-id $ID | grep DetectionStatus | awk -F ' +\"' '{print \$4}'); #system qq{aws cloudformation describe-stack-drift-detection-statu +s --stack-drift-detection-id $ID | grep DetectionStatus | awk -F '"' +'{print \$4}'}; system qq{aws cloudformation describe-stack-drift-detection-status + --stack-drift-detection-id $ID | grep StackDriftStatus | awk -F '\"' + '{print \$4}'}; chomp($DETECTION); chomp($SYNC); } until(("$DETECTION" eq 'DETECTION_COMPLETE') || ("$DETECTION" =~ + /DETECTION_FAILED/mi)) ; #if($SYNC eq 'IN_SYNC') if ( 'IN_SYNC' =~ /$SYNC/mi ) { print "Stack $stack is OK!!\n"; } else { print "Stack $stack is out of sync!! SEND EMAIL NOW!!\n\n"; #system qq{aws ses send-email --from "systems\@eemail.com" --d +estination "ToAddresses=$email" --message "Subject={Data=Cloudformati +on Drift Detected,Charset=utf8},Body={Text={Data=String,Charset=utf8} +,Html={Data=A Cloudformation stack has been detected to be out of SYN +C on Stack $stack,Charset=utf8}}" --region us-east-1}; } }
Any help would be appreciated thank you

Replies are listed 'Best First'.
Re: word search in perl script
by Corion (Patriarch) on Feb 08, 2020 at 07:26 UTC

    The first step is to look at the value of $SYNC in the error case.

    Maybe it contains whitespace, or it contains additional information or other stuff. Maybe it is empty because the command didn't output anything?

    You are doing a lot of awk-ing and grep-ping in your pipelines - Perl can do that too, and maybe you're throwing away important information, at least for debugging?

      I see no spaces in the $SYNC, and I made sure to chomp then do a search .
Re: word search in perl script
by poj (Abbot) on Feb 08, 2020 at 13:35 UTC
    If you are looking for a particular word in $SYNC then it should be on LHS of the regex and the word on the RHS.
    # if ( 'IN_SYNC' =~ /$SYNC/mi ) if ( $SYNC =~ /IN_SYNC/mi )
    poj
      Thank you
Re: word search in perl script
by jcb (Parson) on Feb 09, 2020 at 00:00 UTC

    You are making pairs of API requests. You could be working with inconsistent results. You should be opening a pipe and reading one consistent report. Try replacing lines 24 - 29 with something like: (untested)

    open my $awspipe, '-|', qw/aws cloudformation describe-stack-drift­- +detection-status --stack-drift-detect­ion-id/, $ID or die "open aws pipe: $!"; while (<$awspipe>) { chomp; my @f = split /"/; $DETECTION = $f[3] if /DetectionStatus/; $SYNC = $f[3] if /StackDriftStatus/; } close $awspipe or die "close aws pipe: $!";

    I translated your grep/awk pipeline because I do not know what your input data looks like, but Perl programmers would normally use regexes with a capture group instead of splitting on " and matching key names blindly. If the aws command outputs JSON, normal practice is to parse the objects using JSON instead of slicing up the text.