Skip to content

Commit

Permalink
Merge pull request #133 from vrtdev/feature/entrypoint
Browse files Browse the repository at this point in the history
feat: add support for custom scripts in /docker-entrypoint.d and run custom scripts in order
  • Loading branch information
rwaffen authored Oct 12, 2024
2 parents ddf7a2b + 5b49d03 commit fd50897
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 43 deletions.
73 changes: 40 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
---

- [Voxpupuli Puppet Server container](#voxpupuli-puppet-server-container)
- [Note about environment caching](#note-about-environment-caching)
- [New version schema](#new-version-schema)
- [Configuration](#configuration)
- [Initialization Scripts](#initialization-scripts)
- [Persistance](#persistance)
- [How to Release the container](#how-to-release-the-container)
- [How to contribute](#how-to-contribute)
- [Transfer notice](#transfer-notice)
- [Transfer Notice](#transfer-notice)

---

Expand Down Expand Up @@ -90,42 +91,48 @@ The following environment variables are supported:

| Name | Usage / Default |
|--------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **PUPPETSERVER_HOSTNAME** | The DNS name used on the servers SSL certificate - sets the `server` in puppet.conf<br><br>Defaults to unset. |
| **CERTNAME** | The DNS name used on the servers SSL certificate - sets the `certname` in puppet.conf<br><br>Defaults to unset. |
| **DNS_ALT_NAMES** | Additional DNS names to add to the servers SSL certificate<br>**Note** only effective on initial run when certificates are generated |
| **PUPPETSERVER_PORT** | The port of the puppetserver<br><br>`8140` |
| **AUTOSIGN** | Whether or not to enable autosigning on the puppetserver instance. Valid values are `true`, `false`, and `/path/to/autosign.conf`.<br><br>Defaults to `true`. |
| **CA_ENABLED** | Whether or not this puppetserver instance has a running CA (Certificate Authority)<br><br>`true` |
| **CA_HOSTNAME** | The DNS hostname for the puppetserver running the CA. Does nothing unless `CA_ENABLED=false`<br><br>`puppet` |
| **CA_PORT** | The listening port of the CA. Does nothing unless `CA_ENABLED=false`<br><br>`8140` |
| **CA_ALLOW_SUBJECT_ALT_NAMES** | Whether or not SSL certificates containing Subject Alternative Names should be signed by the CA. Does nothing unless `CA_ENABLED=true`.<br><br>`false` |
| **INTERMEDIATE_CA** | Allows to import an existing intermediate CA. Needs `INTERMEDIATE_CA_BUNDLE`, `INTERMEDIATE_CA_CHAIN` and `INTERMEDIATE_CA_KEY`. See [Puppet Intermediat CA](https://www.puppet.com/docs/puppet/latest/server/intermediate_ca.html) |
| **INTERMEDIATE_CA_BUNDLE** | File path and name to the complete CA bundle (signing CA + Intermediate CA) |
| **INTERMEDIATE_CRL_CHAIN** | File path and name to the complete CA CRL chain |
| **INTERMEDIATE_CA_KEY** | File path and name to the private CA key |
| **PUPPET_REPORTS** | Sets `reports` in puppet.conf<br><br>`puppetdb` |
| **PUPPET_STORECONFIGS** | Sets `storeconfigs` in puppet.conf<br><br>`true` |
| **PUPPET_STORECONFIGS_BACKEND** | Sets `storeconfigs_backend` in puppet.conf<br><br>`puppetdb` |
| **PUPPETSERVER_MAX_ACTIVE_INSTANCES** | The maximum number of JRuby instances allowed<br><br>`1` |
| **PUPPETSERVER_MAX_REQUESTS_PER_INSTANCE** | The maximum HTTP requests a JRuby instance will handle in its lifetime (disable instance flushing)<br><br>`0` |
| **PUPPETSERVER_JAVA_ARGS** | Arguments passed directly to the JVM when starting the service<br><br>`-Xms1024m -Xmx1024m` |
| **USE_PUPPETDB** | Whether to connect to puppetdb<br>Sets `PUPPET_REPORTS` to `log` and `PUPPET_STORECONFIGS` to `false` if those unset<br><br>`true` |
| **PUPPETDB_SERVER_URLS** | The `server_urls` to set in `/etc/puppetlabs/puppet/puppetdb.conf`<br><br>`https://puppetdb:8081` |
| **PUPPETDB_HOSTNAME** | The DNS name of the puppetdb <br><br> Defaults to `puppetdb` |
| **PUPPETDB_SSL_PORT** | The TLS port of the puppetdb <br><br> Defaults to `8081` |
| **PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED** | Activate the graphite exporter. Also needs **PUPPETSERVER_GRAPHITE_HOST** and **PUPPETSERVER_GRAPHITE_PORT**<br><br> Defaults to `false` |
| **PUPPETSERVER_GRAPHITE_HOST** | Only used if **PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED** is set to `true`. FQDN or Hostname of the graphite server where puppet should push metrics to. <br><br> Defaults to `exporter` |
| **PUPPETSERVER_GRAPHITE_PORT** | Only used if **PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED** is set to `true`. Port of the graphite server where puppet should push metrics to. <br><br> Default to `9109` |
| **PUPPETSERVER_ENVIRONMENT_TIMEOUT** | Configure the environment timeout<br><br> Defaults to `unlimited` |
| **PUPPETSERVER_ENABLE_ENV_CACHE_DEL_API** | Enable the puppet admin api endpoint via certificates to allow clearing environment caches<br><br> Defaults to `true` |
| **ENVIRONMENTPATH** | Set an environmentpath<br><br> Defaults to `/etc/puppetlabs/code/environments` |
| **HIERACONFIG** | Set a hiera_config entry in puppet.conf file<br><br> Defaults to `$confdir/hiera.yaml` |
| **CSR_ATTRIBUTES** | Provide a JSON string of the csr_attributes.yaml content. e.g. `CSR_ATTRIBUTES='{"custom_attributes": { "challengePassword": "foobar" }, "extension_requests": { "pp_project": "foo" } }'`<br><br> Defaults to empty JSON object `{}`<br> Please note that within a compose file, you must provide all environment variables as Hash and not as Array!<br> environment:<br> `CSR_ATTRIBUTES: '{"extension_request": {...}}'` |
| __PUPPETSERVER_HOSTNAME__ | The DNS name used on the servers SSL certificate - sets the `server` in puppet.conf<br><br>Defaults to unset. |
| __CERTNAME__ | The DNS name used on the servers SSL certificate - sets the `certname` in puppet.conf<br><br>Defaults to unset. |
| __DNS_ALT_NAMES__ | Additional DNS names to add to the servers SSL certificate<br>__Note__ only effective on initial run when certificates are generated |
| __PUPPETSERVER_PORT__ | The port of the puppetserver<br><br>`8140` |
| __AUTOSIGN__ | Whether or not to enable autosigning on the puppetserver instance. Valid values are `true`, `false`, and `/path/to/autosign.conf`.<br><br>Defaults to `true`. |
| __CA_ENABLED__ | Whether or not this puppetserver instance has a running CA (Certificate Authority)<br><br>`true` |
| __CA_HOSTNAME__ | The DNS hostname for the puppetserver running the CA. Does nothing unless `CA_ENABLED=false`<br><br>`puppet` |
| __CA_PORT__ | The listening port of the CA. Does nothing unless `CA_ENABLED=false`<br><br>`8140` |
| __CA_ALLOW_SUBJECT_ALT_NAMES__ | Whether or not SSL certificates containing Subject Alternative Names should be signed by the CA. Does nothing unless `CA_ENABLED=true`.<br><br>`false` |
| __INTERMEDIATE_CA__ | Allows to import an existing intermediate CA. Needs `INTERMEDIATE_CA_BUNDLE`, `INTERMEDIATE_CA_CHAIN` and `INTERMEDIATE_CA_KEY`. See [Puppet Intermediat CA](https://www.puppet.com/docs/puppet/latest/server/intermediate_ca.html) |
| __INTERMEDIATE_CA_BUNDLE__ | File path and name to the complete CA bundle (signing CA + Intermediate CA) |
| __INTERMEDIATE_CRL_CHAIN__ | File path and name to the complete CA CRL chain |
| __INTERMEDIATE_CA_KEY__ | File path and name to the private CA key |
| __PUPPET_REPORTS__ | Sets `reports` in puppet.conf<br><br>`puppetdb` |
| __PUPPET_STORECONFIGS__ | Sets `storeconfigs` in puppet.conf<br><br>`true` |
| __PUPPET_STORECONFIGS_BACKEND__ | Sets `storeconfigs_backend` in puppet.conf<br><br>`puppetdb` |
| __PUPPETSERVER_MAX_ACTIVE_INSTANCES__ | The maximum number of JRuby instances allowed<br><br>`1` |
| __PUPPETSERVER_MAX_REQUESTS_PER_INSTANCE__ | The maximum HTTP requests a JRuby instance will handle in its lifetime (disable instance flushing)<br><br>`0` |
| __PUPPETSERVER_JAVA_ARGS__ | Arguments passed directly to the JVM when starting the service<br><br>`-Xms1024m -Xmx1024m` |
| __USE_PUPPETDB__ | Whether to connect to puppetdb<br>Sets `PUPPET_REPORTS` to `log` and `PUPPET_STORECONFIGS` to `false` if those unset<br><br>`true` |
| __PUPPETDB_SERVER_URLS__ | The `server_urls` to set in `/etc/puppetlabs/puppet/puppetdb.conf`<br><br>`https://puppetdb:8081` |
| __PUPPETDB_HOSTNAME__ | The DNS name of the puppetdb <br><br> Defaults to `puppetdb` |
| __PUPPETDB_SSL_PORT__ | The TLS port of the puppetdb <br><br> Defaults to `8081` |
| __PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED__ | Activate the graphite exporter. Also needs __PUPPETSERVER_GRAPHITE_HOST__ and __PUPPETSERVER_GRAPHITE_PORT__<br><br> Defaults to `false` |
| __PUPPETSERVER_GRAPHITE_HOST__ | Only used if __PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED__ is set to `true`. FQDN or Hostname of the graphite server where puppet should push metrics to. <br><br> Defaults to `exporter` |
| __PUPPETSERVER_GRAPHITE_PORT__ | Only used if __PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED__ is set to `true`. Port of the graphite server where puppet should push metrics to. <br><br> Default to `9109` |
| __PUPPETSERVER_ENVIRONMENT_TIMEOUT__ | Configure the environment timeout<br><br> Defaults to `unlimited` |
| __PUPPETSERVER_ENABLE_ENV_CACHE_DEL_API__ | Enable the puppet admin api endpoint via certificates to allow clearing environment caches<br><br> Defaults to `true` |
| __ENVIRONMENTPATH__ | Set an environmentpath<br><br> Defaults to `/etc/puppetlabs/code/environments` |
| __HIERACONFIG__ | Set a hiera_config entry in puppet.conf file<br><br> Defaults to `$confdir/hiera.yaml` |
| __CSR_ATTRIBUTES__ | Provide a JSON string of the csr_attributes.yaml content. e.g. `CSR_ATTRIBUTES='{"custom_attributes": { "challengePassword": "foobar" }, "extension_requests": { "pp_project": "foo" } }'`<br><br> Defaults to empty JSON object `{}`<br> Please note that within a compose file, you must provide all environment variables as Hash and not as Array!<br> environment:<br> `CSR_ATTRIBUTES: '{"extension_request": {...}}'` |

## Initialization Scripts

If you would like to do additional initialization, add a directory called `/docker-custom-entrypoint.d/` and fill it with `.sh` scripts.
These scripts will be executed at the end of the entrypoint script, before the service is ran.

You can also create sub-directories in `/docker-custom-entrypoint.d/` for scripts that have to run at different stages.

- `/docker-custom-entrypoint.d/` - scripts that run after the default entrypoint scripts, but before the puppetserver service is started.
- `/docker-custom-entrypoint.d/post-startup/` - scripts that run after the puppetserver service is started.
- `/docker-custom-entrypoint.d/sigterm-handler/` - scripts that run when the container receives a SIGTERM signal.
- `/docker-custom-entrypoint.d/post-execution/` - scripts that run after the puppetserver service has stopped.

## Persistance

Expand Down
118 changes: 108 additions & 10 deletions puppetserver/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,117 @@
#!/bin/bash
# bash is required to pass ENV vars with dots as sh cannot

set -e
set -o errexit # exit on any command failure; use `whatever || true` to accept failures
# use `if something; then` instead of `something; if [ $? -eq 0 ]; then`
# use `rv=0; something || rv=$?` if you really need the exact exit code
set -o pipefail # pipes fail when any command fails, not just the last one. Use: ( whatever || true ) | somethingelse
set -o nounset # exit on use of undeclared var, use `${possibly_undefined-}` to substitute the empty string in that case
# You can assign default values like this:
# `: ${possibly_undefined=default}`
# `: ${possibly_undefined_or_empty:=default}` will also replace an empty (but declared) value
# set -o xtrace

for f in /docker-entrypoint.d/*.sh; do
pid=0

echoerr() { echo "$@" 1>&2; }

echoerr "Entrypoint PID $$"

## Pre execution handler
pre_execution_handler() {
for f in /docker-entrypoint.d/*.sh; do
echo "Running $f"
"$f"
done

if [ -d /docker-custom-entrypoint.d/ ]; then
done
if [ -d /docker-custom-entrypoint.d/ ]; then
find /docker-custom-entrypoint.d/ -type f -name "*.sh" \
-exec chmod +x {} \;
-exec chmod +x {} \;
sync
find /docker-custom-entrypoint.d/ -type f -name "*.sh" \
-exec echo Running {} \; -exec {} \;
fi
for f in /docker-custom-entrypoint.d/*.sh; do
echo "Running $f"
"$f"
done
fi
}

## Post startup handler
post_startup_handler() {
if [ -d /docker-custom-entrypoint.d/ ]; then
if [ -d /docker-custom-entrypoint.d/post-startup/ ]; then
find /docker-custom-entrypoint.d/post-startup/ -type f -name "*.sh" \
-exec chmod +x {} \;
sync
for f in /docker-custom-entrypoint.d/post-startup/*.sh; do
echo "Running $f"
"$f"
done
fi
fi
}

## Post execution handler
post_execution_handler() {
if [ -d /docker-custom-entrypoint.d/ ]; then
if [ -d /docker-custom-entrypoint.d/post-execution/ ]; then
find /docker-custom-entrypoint.d/post-execution/ -type f -name "*.sh" \
-exec chmod +x {} \;
sync
for f in /docker-custom-entrypoint.d/post-execution/*.sh; do
echo "Running $f"
"$f"
done
fi
fi
}

## Sigterm Handler
sigterm_handler() {
echoerr "Catching SIGTERM"
if [ $pid -ne 0 ]; then
echoerr "sigterm_handler for PID '${pid}' triggered"
# the above if statement is important because it ensures
# that the application has already started. without it you
# could attempt cleanup steps if the application failed to
# start, causing errors.
if [ -d /docker-custom-entrypoint.d/ ]; then
if [ -d /docker-custom-entrypoint.d/sigterm-handler/ ]; then
find /docker-custom-entrypoint.d/sigterm-handler/ -type f -name "*.sh" \
-exec chmod +x {} \;
sync
for f in /docker-custom-entrypoint.d/sigterm-handler/*.sh; do
echo "Running $f"
"$f"
done
fi
fi
kill -15 "$pid"
wait "$pid"
post_execution_handler
fi
exit 143; # 128 + 15 -- SIGTERM
}

## Setup signal trap
# on callback execute the specified handler
trap sigterm_handler SIGTERM

## Initialization
pre_execution_handler

## Start Process
echoerr "Starting Puppetserver"
# run process in background and record PID
/opt/puppetlabs/bin/puppetserver "$@" &
pid="$!"

## Post Startup
post_startup_handler

## Wait forever until app dies
wait "$pid"
return_code="$?"

exec /opt/puppetlabs/bin/puppetserver "$@"
## Cleanup
post_execution_handler
# echo the return code of the application
exit $return_code

0 comments on commit fd50897

Please sign in to comment.