Skip to content

Commit

Permalink
[#71] Add support for "run once" custom script
Browse files Browse the repository at this point in the history
This commit introduces a new configuration parameter
`PGENV_SCRIPT_FIRSTSTART` that can be pointed to an executable that is
run once and only once at the very first start of the selected
instance.
Therefore, the usage of this script enables for customization of the
instance, like for example adding new users and databases.

The changes are made directly into the `pgenv_start_instance`
function, that is the entry point to a start action: the function in
turns calls `pgenv_initdb` that performs the initialization of the
instace. If the initialization is done, a new magic variable
`PGENV_INITDB_DONE` is set to `1`, so that `pgenv_start_instance` can
then decide to execute the script mentioned above.

Therefore, the trick here is to mark a "first start" time as the one
that immediatly follows the initdb phase.

Documentation updated.
Version number bumped.

Close #71
  • Loading branch information
fluca1978 committed Apr 15, 2024
1 parent 719039a commit 8d2c963
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 6 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,17 @@ The script gets the version of PostgreSQL being installed as first argument.
command ends the `initdb` phase, that happens only the `PGDATA` has not been
initialized (i.e., on *very first `use`*). The return value of the script
does not affect the `pgenv` workflow. The script gets the current `PGDATA`
path as first argument.
path as first argument. Please note that this script runs with the cluster
turned off.
- `PGENV_SCRIPT_POSTSTART` is an executable script run at the very first of
a freshly installed cluster. Typically, this happens immediatly after the
`initdb` phase, after the cluster has been succesfully started. Please
note that this script is run only once in the whole cluster's life, that
means it will not run at every cluster start action, but only on the very first
start of the cluster. Therefore, this script can be used to initialize
the cluster with custmo data (e.g., creating users, databases, populating
tables and so on).

- `PGENV_SCRIPT_POSTSTART` is an executable script executed each time an
instances is started, that is `start` is executed. The return value of the
Expand Down
32 changes: 27 additions & 5 deletions bin/pgenv
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# VERSION
#
PGENV_VERSION="1.3.5"
PGENV_VERSION="1.3.6"

# https://stackoverflow.com/a/19622569/79202
trap 'exit' ERR
Expand Down Expand Up @@ -781,7 +781,8 @@ pgenv_configuration_write() {
pgenv_configuration_write_variable "$CONF" "PGENV_RESTART_OPTIONS" "" 'Restart configuration flags'

pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_POSTINSTALL" "" 'Script to execute when the build process finishes'
pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_POSTINITDB" "" 'Script to execute when initdb finishes'
pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_POSTINITDB" "" 'Script to execute when initdb finishes (and the server has not started yet)'
pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_FIRSTSTART" "" 'Script to execute at the very first start of the instance'
pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_PRESTOP" "" 'Script to execute before the cluster stops'
pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_POSTSTOP" "" 'Script to execute when the cluster has been stopped'
pgenv_configuration_write_variable "$CONF" "PGENV_SCRIPT_POSTSTART" "" 'Script to execute when the cluster has been started'
Expand Down Expand Up @@ -927,6 +928,7 @@ pgenv_start_instance(){
fi

# Init the database if needed.
# the special variable PGENV_INITDB_DONE will be valued accordingly
pgenv_initdb

pgenv_debug "pg_ctl starting instance with flags [${PGENV_START_OPTIONS[@]}] log [$PGENV_LOG]"
Expand All @@ -935,6 +937,22 @@ pgenv_start_instance(){
echo "PostgreSQL $v started"
echo "Logging to $PGENV_LOG"

# if this is the first start, i.e., the start run
# just after the initialization, execute
# the appropriate custom script
if [ $PGENV_INITDB_DONE -eq 1 ]; then
if [ ! -z "$PGENV_SCRIPT_FIRSTSTART" -a -x "$PGENV_SCRIPT_FIRSTSTART" ]; then
cat <<EOF
This is the first time PostgreSQL $v is started,
executing the \`PGENV_SCRIPT_FIRSTSTART\` script
"$PGENV_SCRIPT_FIRSTSTART"
EOF
$PGENV_SCRIPT_FIRSTSTART "$PG_DATA"
fi
fi


# if there is a post-start script to run, run it
if [ -x "$PGENV_SCRIPT_POSTSTART" ]; then
echo "Running post-start script [$PGENV_SCRIPT_POSTSTART]"
Expand All @@ -955,6 +973,10 @@ pgenv_start_instance(){
# Initializes an instance if no data directory is found.
# Requires PG_DATA to be set.
# It is safe to call multiple times.
#
# The function cannot return a value, because it alredy outputs
# values on the stdout, so it sets a variable to indicate that this is
# a first initialization of the database.
pgenv_initdb(){
if [ ! -d $PG_DATA ]; then
pgenv_debug "initdb running with flags [${PGENV_INITDB_OPTIONS[@]}]"
Expand All @@ -966,8 +988,10 @@ pgenv_initdb(){
$PGENV_SCRIPT_POSTINITDB "$PG_DATA"
fi

export PGENV_INITDB_DONE=1
else
pgenv_debug "Directory $PG_DATA exists, not initdb-ing!"
export PGENV_INITDB_DONE=0
fi
}

Expand Down Expand Up @@ -1162,10 +1186,8 @@ case $1 in

# only start the database if the user specified the need to use the database
if [ "$command" == 'use' ]; then
# Init if needed.
pgenv_initdb

# start the instance
# (it will automatically initdb if needed)
pgenv_start_instance
fi

Expand Down

0 comments on commit 8d2c963

Please sign in to comment.