From 81d68ef3f7b04c0cf0ead26b8a5ccfa7c88b6b83 Mon Sep 17 00:00:00 2001 From: Stefan - Zipkid - Goethals Date: Thu, 10 Oct 2024 07:40:35 +0200 Subject: [PATCH 1/2] Update entrypoint Run custom scripts in filename order Add support for custom scripts in /docker-entrypoint.d for different stages of the entrypoint --- puppetserver/docker-entrypoint.sh | 118 +++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 10 deletions(-) diff --git a/puppetserver/docker-entrypoint.sh b/puppetserver/docker-entrypoint.sh index 1a16c6f19..170f09581 100755 --- a/puppetserver/docker-entrypoint.sh +++ b/puppetserver/docker-entrypoint.sh @@ -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 From 5b49d03b96cab09dadd354d755b8702dd320c152 Mon Sep 17 00:00:00 2001 From: Stefan - Zipkid - Goethals Date: Fri, 11 Oct 2024 15:19:26 +0200 Subject: [PATCH 2/2] Add docs about the deployment scripts Also fix linter errors about bold setting --- README.md | 73 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index b6c90a0a1..a7d82f4be 100644 --- a/README.md +++ b/README.md @@ -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) --- @@ -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

Defaults to unset. | -| **CERTNAME** | The DNS name used on the servers SSL certificate - sets the `certname` in puppet.conf

Defaults to unset. | -| **DNS_ALT_NAMES** | Additional DNS names to add to the servers SSL certificate
**Note** only effective on initial run when certificates are generated | -| **PUPPETSERVER_PORT** | The port of the puppetserver

`8140` | -| **AUTOSIGN** | Whether or not to enable autosigning on the puppetserver instance. Valid values are `true`, `false`, and `/path/to/autosign.conf`.

Defaults to `true`. | -| **CA_ENABLED** | Whether or not this puppetserver instance has a running CA (Certificate Authority)

`true` | -| **CA_HOSTNAME** | The DNS hostname for the puppetserver running the CA. Does nothing unless `CA_ENABLED=false`

`puppet` | -| **CA_PORT** | The listening port of the CA. Does nothing unless `CA_ENABLED=false`

`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`.

`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

`puppetdb` | -| **PUPPET_STORECONFIGS** | Sets `storeconfigs` in puppet.conf

`true` | -| **PUPPET_STORECONFIGS_BACKEND** | Sets `storeconfigs_backend` in puppet.conf

`puppetdb` | -| **PUPPETSERVER_MAX_ACTIVE_INSTANCES** | The maximum number of JRuby instances allowed

`1` | -| **PUPPETSERVER_MAX_REQUESTS_PER_INSTANCE** | The maximum HTTP requests a JRuby instance will handle in its lifetime (disable instance flushing)

`0` | -| **PUPPETSERVER_JAVA_ARGS** | Arguments passed directly to the JVM when starting the service

`-Xms1024m -Xmx1024m` | -| **USE_PUPPETDB** | Whether to connect to puppetdb
Sets `PUPPET_REPORTS` to `log` and `PUPPET_STORECONFIGS` to `false` if those unset

`true` | -| **PUPPETDB_SERVER_URLS** | The `server_urls` to set in `/etc/puppetlabs/puppet/puppetdb.conf`

`https://puppetdb:8081` | -| **PUPPETDB_HOSTNAME** | The DNS name of the puppetdb

Defaults to `puppetdb` | -| **PUPPETDB_SSL_PORT** | The TLS port of the puppetdb

Defaults to `8081` | -| **PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED** | Activate the graphite exporter. Also needs **PUPPETSERVER_GRAPHITE_HOST** and **PUPPETSERVER_GRAPHITE_PORT**

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.

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.

Default to `9109` | -| **PUPPETSERVER_ENVIRONMENT_TIMEOUT** | Configure the environment timeout

Defaults to `unlimited` | -| **PUPPETSERVER_ENABLE_ENV_CACHE_DEL_API** | Enable the puppet admin api endpoint via certificates to allow clearing environment caches

Defaults to `true` | -| **ENVIRONMENTPATH** | Set an environmentpath

Defaults to `/etc/puppetlabs/code/environments` | -| **HIERACONFIG** | Set a hiera_config entry in puppet.conf file

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" } }'`

Defaults to empty JSON object `{}`
Please note that within a compose file, you must provide all environment variables as Hash and not as Array!
environment:
`CSR_ATTRIBUTES: '{"extension_request": {...}}'` | +| __PUPPETSERVER_HOSTNAME__ | The DNS name used on the servers SSL certificate - sets the `server` in puppet.conf

Defaults to unset. | +| __CERTNAME__ | The DNS name used on the servers SSL certificate - sets the `certname` in puppet.conf

Defaults to unset. | +| __DNS_ALT_NAMES__ | Additional DNS names to add to the servers SSL certificate
__Note__ only effective on initial run when certificates are generated | +| __PUPPETSERVER_PORT__ | The port of the puppetserver

`8140` | +| __AUTOSIGN__ | Whether or not to enable autosigning on the puppetserver instance. Valid values are `true`, `false`, and `/path/to/autosign.conf`.

Defaults to `true`. | +| __CA_ENABLED__ | Whether or not this puppetserver instance has a running CA (Certificate Authority)

`true` | +| __CA_HOSTNAME__ | The DNS hostname for the puppetserver running the CA. Does nothing unless `CA_ENABLED=false`

`puppet` | +| __CA_PORT__ | The listening port of the CA. Does nothing unless `CA_ENABLED=false`

`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`.

`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

`puppetdb` | +| __PUPPET_STORECONFIGS__ | Sets `storeconfigs` in puppet.conf

`true` | +| __PUPPET_STORECONFIGS_BACKEND__ | Sets `storeconfigs_backend` in puppet.conf

`puppetdb` | +| __PUPPETSERVER_MAX_ACTIVE_INSTANCES__ | The maximum number of JRuby instances allowed

`1` | +| __PUPPETSERVER_MAX_REQUESTS_PER_INSTANCE__ | The maximum HTTP requests a JRuby instance will handle in its lifetime (disable instance flushing)

`0` | +| __PUPPETSERVER_JAVA_ARGS__ | Arguments passed directly to the JVM when starting the service

`-Xms1024m -Xmx1024m` | +| __USE_PUPPETDB__ | Whether to connect to puppetdb
Sets `PUPPET_REPORTS` to `log` and `PUPPET_STORECONFIGS` to `false` if those unset

`true` | +| __PUPPETDB_SERVER_URLS__ | The `server_urls` to set in `/etc/puppetlabs/puppet/puppetdb.conf`

`https://puppetdb:8081` | +| __PUPPETDB_HOSTNAME__ | The DNS name of the puppetdb

Defaults to `puppetdb` | +| __PUPPETDB_SSL_PORT__ | The TLS port of the puppetdb

Defaults to `8081` | +| __PUPPETSERVER_GRAPHITE_EXPORTER_ENABLED__ | Activate the graphite exporter. Also needs __PUPPETSERVER_GRAPHITE_HOST__ and __PUPPETSERVER_GRAPHITE_PORT__

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.

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.

Default to `9109` | +| __PUPPETSERVER_ENVIRONMENT_TIMEOUT__ | Configure the environment timeout

Defaults to `unlimited` | +| __PUPPETSERVER_ENABLE_ENV_CACHE_DEL_API__ | Enable the puppet admin api endpoint via certificates to allow clearing environment caches

Defaults to `true` | +| __ENVIRONMENTPATH__ | Set an environmentpath

Defaults to `/etc/puppetlabs/code/environments` | +| __HIERACONFIG__ | Set a hiera_config entry in puppet.conf file

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" } }'`

Defaults to empty JSON object `{}`
Please note that within a compose file, you must provide all environment variables as Hash and not as Array!
environment:
`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