Assert Your Environment
Env::Assert
In the category of "scratching my itch".
I was doing some data pipelining and dockerising my creation. And - as always - when testing and devving I forgot to set the right environment variables. And when container image gets passed around, the information about the required env settings will certainly get lost.
Here is something of a solution to that:
How to ensure you have the environment variables and values you need?
Here is a common sight:
$ PLAEC='Stockholm'
$ if [[ "$PLACE" == '' ]]; then echo "Normal OK"; fi
OK
... And the program fails with no errors!
Not quite what we want!
Another example, from a docker container image I created lately:
perl -Ilib bin/repos-gh-yaml.pl --verbose \
| perl -Ilib bin/repos-yaml-csv.pl --verbose \
| az storage blob upload --data @- \
--content-type 'text/csv' \
--content-encoding 'UTF-8' \
--content-language 'en_US' \
--name "$blob_name" \
--container "$CONTAINER_NAME" \
--account-name "$AZURE_STORAGE_ACCOUNT" \
--sas-token "$AZURE_STORAGE_SAS_TOKEN"
If the environment variables are wrongly set, or entirely unset, it won't become known until after the run has started. And it could take hours before it reaches that point.
What we need is a way to find out if the environment variables are what we assume them to be. This needs to be done in an easy way and right at the beginning of the run.
Environment Description to the Rescue
Package Env::Assert
and the executable envassert
that comes with it
do just this.
envassert
is a CLI command to assert that your environment variables
match your environment description.
environment description is a way to describe which environment variables are required by your program.
environment description is written in a file.
Default file name is .envdesc
.
If you are in the habbit of using .env
files anyway,
.envdesc
complements it. Commit your .envdesc
file into
your repository and it will act as a template for user to create his/her .env
file
which should not be committed into Git anyway.
.envdesc
actually looks a lot like a .env
file, except instead of
defining variables and their content, it defines regular expressions
which control the variables' content. These regexps are Perl's
extended regular expressions (m/<regexp>/msx
).
Example:
CONTAINER_NAME=^[a-z0-9-]{1,}$
AZURE_STORAGE_ACCOUNT=^[a-z0-9]{1,}$
AZURE_STORAGE_SAS_TOKEN=^[?].*$
GITHUB_TOKEN=^[[:word:]]{1,}$
In normal circumstances, envassert
only verifies the variables that you specifically describe.
If you want more control over your environment,
there is the meta command envassert (opts: exact=1)
which will make envassert
also assert that
the environment doesn't contain any unknown variables.
## envassert (opts: exact=1)
USER=^username$
HOME=^/home/username$
PATH=^/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin$
You can create an airtight environment description
to verify environment variables in both test and production.
Just run envassert
as the first command during container execution.
This is what I do:
envassert --env-description /home/me/.envdesc \
|| ( echo 'Break execution ...' 1>&2 && exit 1 )
Installation
If I need to add envassert
to a container image during build,
there is a FatPacked executable
ready for those cases when using CPAN is overkill.
I do this in Dockerfile!
RUN curl -LSs -o /usr/local/bin/envassert \
https://raw.githubusercontent.com/mikkoi/env-assert/main/envassert.self-contained
RUN chmod +x /usr/local/bin/envassert
There is no extra dependencies outside Perl's standard distribution, so envassert
is as lean as it can be.
This is brilliant and I must now delay everything I was going to do today to integrate it into everything. Seriously. This would have solved some problems from last week.
Yeah, this is good stuff. Would you be ok with presenting it at the Perl conference in Helsinki in August? :-)
https://PerlKohaCon.fi