@@ -37,7 +37,7 @@ set -eo pipefail
3737
3838
3939# Do our best to match the logging requested by the user running the container.
40- declare -rA LOG_LEVELS=([error]=0 [warn]=1 [info]=2 [debug]=3)
40+ declare -rA LOG_LEVELS=( [error]=0 [warn]=1 [info]=2 [debug]=3 )
4141declare LOG_LEVEL=error
4242
4343# Mimic the structured logging used by InfluxDB.
@@ -63,11 +63,13 @@ function log () {
6363# Set the global log-level for the entry-point to match the config passed to influxd.
6464function set_global_log_level () {
6565 local level
66- level=" $( influxd print-config --key-name log-level " ${@ } " ) "
66+ level=" $( influxd::config::get log-level " ${@ } " ) "
67+
6768 if [ -z " ${level} " ] || [ -z " ${LOG_LEVELS[${level}]} " ]; then
68- return 1
69+ LOG_LEVEL=info
70+ else
71+ LOG_LEVEL=${level}
6972 fi
70- LOG_LEVEL=${level}
7173}
7274
7375# Look for standard config names in the volume configured in our Dockerfile.
@@ -92,23 +94,97 @@ function set_config_path () {
9294 export INFLUXD_CONFIG_PATH=" ${config_path} "
9395}
9496
97+ function influxd::config::get()
98+ {
99+ # The configuration is a mixture of both configuration files, environment
100+ # variables, and command line options. Consequentially, this prevents the
101+ # configuration from being known *before* executing influxd. This
102+ # emulates what `influx server-config` would return.
103+ declare -r COLUMN_ENVIRONMENT=0
104+ declare -r COLUMN_DEFAULT=1
105+ declare -rA table=(
106+ # #################################################################################
107+ # PRIMARY_KEY # ENVIRONMENT VARIABLE # DEFAULT #
108+ # #################################################################################
109+ [bolt-path]=" INFLUXD_BOLT_PATH | /var/lib/influxdb/influxd.bolt"
110+ [engine-path]=" INFLUXD_ENGINE_PATH | /var/lib/influxdb/engine"
111+ [log-level]=" INFLUXD_LOG_LEVEL | info"
112+ [tls-key]=" INFLUXD_TLS_KEY | "
113+ [tls-cert]=" INFLUXD_TLS_CERT | "
114+ [http-bind-address]=" INFLUXD_HTTP_BIND_ADDRESS | :8086"
115+ )
116+
117+ function table::get()
118+ {
119+ ( # don't leak shopt options
120+ local row
121+ local value
122+
123+ shopt -s extglob
124+ # Unfortunately, bash doesn't support multidimensional arrays. This
125+ # retrieves the corresponding row from the array, splits the column
126+ # from row, and strips leading and trailing whitespace. `extglob`
127+ # is required for this to delete multiple spaces.
128+ IFS=' |' row=(${table[${1}]} )
129+ value=${row[${2}]}
130+ value=" ${value## +([[:space:]])} "
131+ value=" ${value%% +([[:space:]])} "
132+ echo " ${value} "
133+ )
134+ }
135+
136+ #
137+ # Parse Value from Arguments
138+ #
139+
140+ local primary_key=" ${1} " && shift
141+
142+ # Command line arguments take precedence over all other configuration
143+ # sources. This supports two argument formats and ignores unspecified
144+ # arguments even if they contain errors. These will be caught when
145+ # influxd is started.
146+ while [[ " ${# } " -gt 0 ]] ; do
147+ case ${1} in
148+ --${primary_key} =* ) echo " ${1/# " --${primary_key} =" } " && return ;;
149+ --${primary_key} * ) echo " ${2} " && return ;;
150+ * ) shift ;;
151+ esac
152+ done
153+
154+ #
155+ # Parse Value from Environment
156+ #
157+
158+ local value
159+
160+ # If no command line arguments match, retrieve the corresponding environment
161+ # variable. This differentiates between unset and empty variables. If empty,
162+ # it is possible that variable was intentionally emptied; therefore, this
163+ # returns nothing when empty.
164+ value=" $( table::get " ${primary_key} " ${COLUMN_ENVIRONMENT} ) "
165+ if [[ ${! value+x} ]] ; then
166+ echo " ${! value} " && return
167+ fi
168+
169+ #
170+ # Parse Value from Configuration
171+ #
172+ dasel -f " ${INFLUXD_CONFIG_PATH} " -s " ${primary_key} " -w - 2> /dev/null || \
173+ table::get " ${primary_key} " " ${COLUMN_DEFAULT} "
174+ }
175+
95176function set_data_paths () {
96- BOLT_PATH=" $( influxd print- config --key-name bolt-path " ${@ } " ) "
97- ENGINE_PATH=" $( influxd print- config --key-name engine-path " ${@ } " ) "
177+ BOLT_PATH=" $( influxd:: config::get bolt-path " ${@ } " ) "
178+ ENGINE_PATH=" $( influxd:: config::get engine-path " ${@ } " ) "
98179 export BOLT_PATH ENGINE_PATH
99180}
100181
101182# Ensure all the data directories needed by influxd exist with the right permissions.
102183function create_directories () {
103- log info " creating folders with the right permissions"
104184 local -r bolt_dir=" $( dirname " ${BOLT_PATH} " ) "
105185 local user
106186 user=$( id -u)
107187
108- if [ " $( id -u) " != 0 ]; then
109- log warn " cannot create folders as non-root"
110- return
111- fi
112188
113189 mkdir -p " ${bolt_dir} " " ${ENGINE_PATH} "
114190 chmod 700 " ${bolt_dir} " " ${ENGINE_PATH} " || :
@@ -126,9 +202,15 @@ function create_directories () {
126202# Read password and username from file to avoid unsecure env variables
127203if [ -n " ${DOCKER_INFLUXDB_INIT_PASSWORD_FILE} " ]; then [ -e " ${DOCKER_INFLUXDB_INIT_PASSWORD_FILE} " ] && DOCKER_INFLUXDB_INIT_PASSWORD=$( cat " ${DOCKER_INFLUXDB_INIT_PASSWORD_FILE} " ) || echo " DOCKER_INFLUXDB_INIT_PASSWORD_FILE defined, but file not existing, skipping." ; fi
128204if [ -n " ${DOCKER_INFLUXDB_INIT_USERNAME_FILE} " ]; then [ -e " ${DOCKER_INFLUXDB_INIT_USERNAME_FILE} " ] && DOCKER_INFLUXDB_INIT_USERNAME=$( cat " ${DOCKER_INFLUXDB_INIT_USERNAME_FILE} " ) || echo " DOCKER_INFLUXDB_INIT_USERNAME_FILE defined, but file not existing, skipping." ; fi
205+ if [ -n " ${DOCKER_INFLUXDB_INIT_ADMIN_TOKEN_FILE} " ]; then [ -e " ${DOCKER_INFLUXDB_INIT_ADMIN_TOKEN_FILE} " ] && DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=$( cat " ${DOCKER_INFLUXDB_INIT_ADMIN_TOKEN_FILE} " ) || echo " DOCKER_INFLUXDB_INIT_ADMIN_TOKEN_FILE defined, but file not existing, skipping." ; fi
129206
130207# List of env vars required to auto-run setup or upgrade processes.
131- declare -ra REQUIRED_INIT_VARS=(DOCKER_INFLUXDB_INIT_USERNAME DOCKER_INFLUXDB_INIT_PASSWORD DOCKER_INFLUXDB_INIT_ORG DOCKER_INFLUXDB_INIT_BUCKET)
208+ declare -ra REQUIRED_INIT_VARS=(
209+ DOCKER_INFLUXDB_INIT_USERNAME
210+ DOCKER_INFLUXDB_INIT_PASSWORD
211+ DOCKER_INFLUXDB_INIT_ORG
212+ DOCKER_INFLUXDB_INIT_BUCKET
213+ )
132214
133215# Ensure all env vars required to run influx setup or influxd upgrade are set in the env.
134216function ensure_init_vars_set () {
@@ -302,21 +384,36 @@ function init_influxd () {
302384 return
303385 fi
304386
305- local -r final_bind_addr=" $( influxd print- config --key-name http-bind-address " ${@ } " ) "
387+ local -r final_bind_addr=" $( influxd:: config::get http-bind-address " ${@ } " ) "
306388 local -r init_bind_addr=" :${INFLUXD_INIT_PORT} "
307389 if [ " ${init_bind_addr} " = " ${final_bind_addr} " ]; then
308390 log warn " influxd setup binding to same addr as final config, server will be exposed before ready" addr " ${init_bind_addr} "
309391 fi
310392 local final_host_scheme=" http"
311- if [ " $( influxd print-config --key-name tls-cert " ${@ } " ) " != ' ""' ] && [ " $( influxd print-config --key-name tls-key " ${@ } " ) " != ' ""' ]; then
312- final_host_scheme=" https"
393+ if [ -n " $( influxd::config::get tls-cert " ${@ } " ) " ] &&
394+ [ -n " $( influxd::config::get tls-key " ${@ } " ) " ]
395+ then
396+ final_host_scheme=" https"
313397 fi
314398
399+ case ${INFLUXD_CONFIG_PATH,,} in
400+ * .toml) local influxd_config_format=toml ;;
401+ * .json) local influxd_config_format=json ;;
402+ * .yaml|* .yml) local influxd_config_format=yaml ;;
403+ esac
404+
315405 # Generate a config file with a known HTTP port, and TLS disabled.
316- local -r init_config=/tmp/config.yml
317- influxd print-config " ${@ } " | \
318- sed -e " s#${final_bind_addr} #${init_bind_addr} #" -e ' /^tls/d' > \
319- " ${init_config} "
406+ local -r init_config=/tmp/config.json
407+ (
408+ dasel -r " ${influxd_config_format} " -w json \
409+ | dasel -r json put http-bind-address -v " ${init_bind_addr} " \
410+ ` # insert "tls-cert" and "tls-key" so delete succeeds` \
411+ | dasel -r json put tls-cert -v ' ' \
412+ | dasel -r json put tls-key -v ' ' \
413+ ` # delete "tls-cert" and "tls-key"` \
414+ | dasel -r json delete tls-cert \
415+ | dasel -r json delete tls-key
416+ ) < " ${INFLUXD_CONFIG_PATH} " | tee " ${init_config} "
320417
321418 # Start influxd in the background.
322419 log info " booting influxd server in the background"
@@ -341,7 +438,7 @@ function init_influxd () {
341438 wait " ${influxd_init_pid} " || true
342439 trap - EXIT INT TERM
343440
344- # Rewrite the ClI configs to point at the server's final HTTP address.
441+ # Rewrite the CLI configs to point at the server's final HTTP address.
345442 local -r final_port=" $( echo " ${final_bind_addr} " | sed -E ' s#[^:]*:(.*)#\1#' ) "
346443 sed -i " s#http://localhost:${INFLUXD_INIT_PORT} #${final_host_scheme} ://localhost:${final_port} #g" " ${INFLUX_CONFIGS_PATH} "
347444}
@@ -390,7 +487,7 @@ function main () {
390487 if [ -f " ${BOLT_PATH} " ]; then
391488 log info " found existing boltdb file, skipping setup wrapper" bolt_path " ${BOLT_PATH} "
392489 elif [ -z " ${DOCKER_INFLUXDB_INIT_MODE} " ]; then
393- log warn " boltdb not found at configured path, but DOCKER_INFLUXDB_INIT_MODE not specified, skipping setup wrapper" bolt_path " ${bolt_path } "
490+ log warn " boltdb not found at configured path, but DOCKER_INFLUXDB_INIT_MODE not specified, skipping setup wrapper" bolt_path " ${BOLT_PATH } "
394491 else
395492 init_influxd " ${@ } "
396493 # Set correct permission on volume directories again. This is necessary so that if the container was run as the
@@ -400,11 +497,11 @@ function main () {
400497 fi
401498
402499 if [ " $( id -u) " = 0 ]; then
403- exec setpriv --reuid=influxdb --regid=influxdb --init-groups --inh-caps=-all " $BASH_SOURCE " " $@ "
500+ exec setpriv --reuid=influxdb --regid=influxdb --init-groups --inh-caps=-all " $BASH_SOURCE " " ${ @ } "
404501 fi
405502
406503 # Run influxd.
407- exec influxd " $@ "
504+ exec influxd " ${ @ } "
408505}
409506
410- main " $@ "
507+ main " ${ @ } "
0 commit comments