Categories
SysOps

How to use templates inside shell scripts

Use templates inside shell scripts by substituting environment variables.

I will use envsubst utility, which is a part of the gettext-base package.

Create a template file

Create a template using environment variables.

$ cat configuration.yml
---
connection:
  database:
    name: ${DATABASE_NAME}
    type: ${DATABASE_TYPE}
  credentials:
    user: ${SATABASE_USER}
    pass: ${DATABASE_PASS}
  connection:
    host: ${DATABASE_HOST}
    port: ${DATABASE_PORT}

These environment variables will be substituted by the envsubst utility.

Simple environment variables substitution

Set environment variables.

$ export DATABASE_NAME="bookmarks"
$ export DATABASE_TYPE="postgres"

$ export DATABASE_USER="book"
$ export DATABASE_PASS="worm"

$ export DATABASE_HOST="172.16.0.21"
$ export DATABASE_PORT="5432"

Perform substitution of all environment variables.

$ cat configuration.yml | envsubst 
---
connection:
  database:
    name: bookmarks
    type: postgres
  credentials:
    user: book
    pass: worm
  connection:
    host: 172.16.0.21
    port: 5432

Simple environment variables substitution using shell redirection

Set environment variables.

$ export DATABASE_NAME="bookmarks"
$ export DATABASE_TYPE="postgres"

$ export DATABASE_USER="book"
$ export DATABASE_PASS="worm"

$ export DATABASE_HOST="172.16.0.22"
$ export DATABASE_PORT="5432"

Perform substitution of all environment variables using shell redirection.

$ envsubst < configuration.yml > bookmarks_connection.yml 

Inspect created file.

$ cat bookmarks_connection.yml 
---
connection:
  database:
    name: bookmarks
    type: postgres
  credentials:
    user: book
    pass: worm
  connection:
    host: 172.16.0.22

Simple environment variables substitution in multiple steps

Define and inspect variables that will be replaced.

$ envsubst --variables '$DATABASE_USER $DATABASE_PASS $DATABASE_NAME $DATABASE_TYPE'
DATABASE_USER
DATABASE_PASS
DATABASE_NAME
DATABASE_TYPE

Perform partial substitution of environment variables.

$ DATABASE_USER=book DATABASE_PASS=worm DATABASE_NAME=notes DATABASE_TYPE=postgres envsubst '$DATABASE_USER $DATABASE_PASS $DATABASE_NAME $DATABASE_TYPE' < configuration.yml > connection_temp.yml

Inspect created file, notice the last two settings are intact.

$ cat connection_temp.yml 
---
connection:
  database:
    name: notes
    type: postgres
  credentials:
    user: book
    pass: worm
  connection:
    host: ${DATABASE_HOST}
    port: ${DATABASE_PORT}

Define and inspect variables that will be replaced in the second run.

$ envsubst --variables '$DATABASE_HOST $DATABASE_PORT'
DATABASE_HOST
DATABASE_PORT

Perform partial substitution of environment variables.

$ DATABASE_HOST=localhost DATABASE_PORT=5432 envsubst '$DATABASE_HOST $DATABASE_PORT' < connection_temp.yml > connection_final.yml

Inspect created file.

$ cat connection_final.yml 
---
connection:
  database:
    name: notes
    type: postgres
  credentials:
    user: book
    pass: worm
  connection:
    host: localhost
    port: 5432

Simple environment variables substitution using the specified prefix

Set environment variables.

$ export DATABASE_NAME="files"
$ export DATABASE_TYPE="postgres"

$ export DATABASE_USER="book"
$ export DATABASE_PASS="worm"

$ export DATABASE_HOST="172.16.0.42"
$ export DATABASE_PORT="5432"

Display environment variables that are using the prefix DATABASE_.

$ echo "${!DATABASE_@}"
DATABASE_HOST DATABASE_NAME DATABASE_PASS DATABASE_PORT DATABASE_TYPE DATABASE_USER

Display each element as an environment variable with a dollar sign.

$ printf '${%s}\n' ${!DATABASE_@}
${DATABASE_HOST}
${DATABASE_NAME}
${DATABASE_PASS}
${DATABASE_PORT}
${DATABASE_TYPE}
${DATABASE_USER}

Use this list to perform the substitution of specified environment variables.

$ envsubst "$(printf '${%s}\n' ${!DATABASE_@})" < configuration.yml
---
connection:
  database:
    name: files
    type: postgres
  credentials:
    user: book
    pass: worm
  connection:
    host: 172.16.0.42
    port: 5432