2

I have a scenario where I am running the following code:

error_count=0
(cd tmp1 && terraform init -backend=false > /dev/null && terraform validate && echo "Terraform format check passed successfully in -------> xxx" && rm -rf .terraform*) || (echo "Terraform validation failed in xxx" && cd tmp && rm -rf .terraform* && let "error_count=error_count+1")

(cd tmp2 && terraform init -backend=false > /dev/null && terraform validate && echo "Terraform format check passed successfully in -------> yyy" && rm -rf .terraform*) || (echo "Terraform validation failed in yyy" && cd tmp && rm -rf .terraform* && let "error_count=error_count+1")
echo $error_count
if [ "$error_count" -gt 0 ]; then
  echo "terraform check failed"
  exit 1
else
  echo "terraform check passed"
fi

What I observe here is even if the condition fails, the error_count=0 value remains the same. How can I increment the counter on a failing condition?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
Jenifer
  • 85
  • 5
  • Does this answer your question? - [How to make a variable from a subshell available in the parent shell](https://unix.stackexchange.com/q/140043/100397) – roaima Mar 23 '22 at 14:41

1 Answers1

2

As roaima commented, the core of your question boils down to the subshell environment (in (cd ... )) exiting completely, leaving the let "error_count=error_count+1" behind, and not affecting the parent shell's value of error_count.

I would recommend refactoring the code a bit so that you have a reusable function to execute the common functionality and have it return a success or failure code:

#!/bin/bash
terraform_init_and_validate() (
  if    cd "$1" &&
        terraform init -backend=false > /dev/null &&
        terraform validate
  then
        echo "Terraform format check passed successfully in -------> xxx"
        rm -rf .terraform*
        return 0
  else
        echo "Terraform validation failed in xxx"
        cd tmp && rm -rf .terraform*
        return 1
  fi
)

error_count=0
if ! terraform_init_and_validate tmp1
then
  let "error_count=error_count+1"
fi

if ! terraform_init_and_validate tmp2
then
  let "error_count=error_count+1"
fi

echo $error_count
if [ "$error_count" -gt 0 ]; then
  echo "terraform check failed"
  exit 1
else
  echo "terraform check passed"
fi

The terraform_init_and_validate function runs the code in a subshell, maintaining that isolation for the cd commands, but returns a true or false value depending on the success or failure of the two terraform commands. The main script then calls that function with the two different parameters and increments error_count only if the function returned an error code.

I would also point out a minor discrepancy (to my eyes): that the "success" branch of your code does a rm -rf .terraform* from the initial directory but the "failure" branch does a cd tmp && rm -rf .terraform*, which removes files from a subdirectory of the initial directory.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
  • Thanks for the inputs, but if I refactor code like this then if I need to run some pre-steps for let say `tmp2` how do I do that ? something like this scenario `if executing directory is tmp2 then echo "something"` – Jenifer Mar 23 '22 at 15:45
  • Well, I just saw lots of duplicated code, and along with the idea of separating the `cd` to a subshell, a function sprang to mind. There's always more than one way to do it. Perhaps before calling `if ! terraform_init_and_validate tmp2` you insert the code there? – Jeff Schaller Mar 23 '22 at 17:09