J-Are
J-Are

Reputation: 35

Strange behaviour with envsubst command

I try to check the command return inside my bash script for all commands. I created a function for this named check_command_return_code. This function is called in some other function which run command and it seems to work as expected except for the envsubst command.

This is my check_command_return_code:

check_command_return_code(){
  "$@"
  if [ "$?" -ne 0 ]; then
    echo "[ERROR] Error with command $@"
    exit 1
  fi
  echo "[SUCCESS] Command $@ has successfully run"
}

I also write this function in order to substitute env variable inside yaml file:

substitute_env_variables_into_file(){
  echo "Create new file named $2 from $1 by substituting environment variables within it"
  check_command_return_code envsubst < $1 > $2

}

I call my function which proceeds the substitution like this:

substitute_env_variables_into_file "./ingress-values.yaml" "./ingress-values-subst.yaml"

This is my ingress-values.yaml file:

controller:
  replicaCount: 2
  service:
    loadBalancerIP: "$INTERNAL_LOAD_BALANCER_IP"
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-internal: "true" 

I expect my ingress-values-subst.yaml looks like this:

controller:
  replicaCount: 2
  service:
    loadBalancerIP: "my_private_ip"
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-internal:

Unfortunately the ingress-values-subst.yaml is expanded with the echo of my check_command_return_code function as you can see:

controller:
  replicaCount: 2
  service:
    loadBalancerIP: "my_private_ip"
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-internal: "true"
[SUCCESS] Command envsubst has successfully run

I enabled the "debug" mode thanks to the following command in order to have more verbosity:

set -x

These logs are those from the output of my script:

++ substitute_env_variables_into_file ./private-ingress-values.yaml ./private-ingress-values-subst.yaml
++ echo 'Create new file named ./ingress/private-ingress-values-subst.yaml from ./private-ingress-values.yaml by substituting environment variables within it'
Create new file named ./private-ingress-values-subst.yaml from ./private-ingress-values.yaml by substituting environment variables within it
++ check_command_return_code envsubst
++ envsubst
++ '[' 0 -ne 0 ']'
++ echo '[SUCCESS] Command envsubst has successfully run'

I don't understand why the parameter of my command envsubst are not passed into my check_command_return_code function as you can see in the previous logs.

Thanks in advance for your help

Upvotes: 1

Views: 1472

Answers (1)

KamilCuk
KamilCuk

Reputation: 140970

I don't understand why the parameter of my command envsubst are not passed into my check_command_return_code

Redirections are not parameters. Redirections are opened at the time the line is executed.

When you do your_function > file, then inside your_function standard output is redirected to file for the whole duration of the function, including all the commands inside your_function.

Wrap it in yet another function:

myenvsubst() {
    envsubst < "$1" > "$2"
}
check_command_return_code myenvsubst "$1" "$2"

Or better yet, write log information to standard error, or another file descriptor.

    echo "[ERROR] Error with command $*" >&2

Check your scripts with shellcheck to find such problems like:

< $1 > $2

are not quoted. They should be < "$1" > "$2"

if [ "$?" -ne 0 ]; then

is an antipattern. Prefer if ! "$@"; then.

echo "[ERROR] Error with command $@"

is an odd usage of quoted $@. Prefer $*, or move to a separate argument.

Upvotes: 3

Related Questions