Files
cacti/tests/e2e/entrypoint.sh
Thomas Vincent 41780277d3 fix(docker): restrict development permissions and start the poller (#8453)
* fix(docker): restrict the dev stack to localhost and make the poller run

The web port bound to every interface, named volumes hid the shipped .htaccess denies, and the cron job could neither find php nor write to PID 1's output, so the poller never ran.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(docker): keep harnesses polling and restore the developer's config.php

check_docker.sh deleted an existing include/config.php on exit, health polling aborted under pipefail before the container reported, the MariaDB wait had no bound, and the BSD mktemp template left its Xs literal.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): add fragment for #8453

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(e2e): move the pointer off the Deepness multiselect button

Deepness sets a zero body margin, so the unhovered #ms-button sits at the viewport origin and headless Chromium on Linux intermittently applies :hover to it.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: pull pinned integration database from authenticated mirror

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-23 08:17:48 -04:00

103 lines
6.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# +-------------------------------------------------------------------------+
# | Copyright (C) 2004-2026 The Cacti Group |
# | |
# | This program is free software; you can redistribute it and/or |
# | modify it under the terms of the GNU General Public License |
# | as published by the Free Software Foundation; either version 2 |
# | of the License, or (at your option) any later version. |
# +-------------------------------------------------------------------------+
# | Cacti: The Complete RRDtool-based Graphing Solution |
# +-------------------------------------------------------------------------+
# | http://www.cacti.net/ |
# +-------------------------------------------------------------------------+
set -euo pipefail
DB_HOST="${CACTI_DB_HOST:-mariadb}"
DB_NAME="${CACTI_DB_NAME:-cacti}"
DB_USER="${CACTI_DB_USER:-cactiuser}"
DB_PASS="${CACTI_DB_PASS:-cactiuser}"
DB_ROOT_PASS="${CACTI_DB_ROOT_PASS:-cactiroot}"
# Wait for MariaDB to accept connections before we seed the schema. Some
# MariaDB/MySQL clients default to TLS certificate verification, so a plain
# ping against the private test container can fail indefinitely. --skip-ssl
# disables that handshake for this container-to-container link.
# A bad host or password would otherwise loop forever and look like a hang.
DB_WAIT_TRIES="${CACTI_DB_WAIT_TRIES:-90}"
until mysqladmin ping -h "$DB_HOST" -uroot -p"$DB_ROOT_PASS" --skip-ssl --silent; do
DB_WAIT_TRIES=$((DB_WAIT_TRIES - 1))
if [ "$DB_WAIT_TRIES" -le 0 ]; then
echo "mariadb at ${DB_HOST} did not accept connections; giving up" >&2
exit 1
fi
echo "waiting for mariadb at ${DB_HOST}..."
sleep 2
done
# Point Cacti at the linked database. sed in place keeps the file simple.
# url_path is forced to '/' because the container serves Cacti from the Apache
# document root, not a /cacti/ subdirectory. The dist default of '/cacti/'
# makes CACTI_PATH_URL emit asset and redirect paths the e2e stack 404s on,
# including the htmx script src the specs assert against.
sed -i \
-e "s|\$database_type.*=.*|\$database_type = 'mysql';|" \
-e "s|\$database_default.*=.*|\$database_default = '${DB_NAME}';|" \
-e "s|\$database_hostname.*=.*|\$database_hostname = '${DB_HOST}';|" \
-e "s|\$database_username.*=.*|\$database_username = '${DB_USER}';|" \
-e "s|\$database_password.*=.*|\$database_password = '${DB_PASS}';|" \
-e "s|\$database_port.*=.*|\$database_port = '3306';|" \
-e "s|\$url_path.*=.*|\$url_path = '/';|" \
/var/www/html/include/config.php
# Seed the schema on first boot. The second boot will skip because tables
# already exist.
if ! mysql -h "$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --skip-ssl "$DB_NAME" \
-e "SELECT 1 FROM settings LIMIT 1" >/dev/null 2>&1; then
echo "seeding cacti schema..."
mysql -h "$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --skip-ssl "$DB_NAME" < /var/www/html/cacti.sql
# Mark the install complete so the UI does not redirect to the installer.
mysql -h "$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --skip-ssl "$DB_NAME" -e \
"REPLACE INTO settings (name, value) VALUES ('install_complete', '1')"
# cacti.sql ships version.cacti as the 'new_install' sentinel, which
# is_install_needed() reads as older than the develop target and so forces
# the installer redirect. Stamp the version row with CACTI_DEV_VERSION (the
# constant the comparison runs against) so the login page renders instead.
dev_version="$(php -r "require '/var/www/html/include/global_constants.php'; if (!defined('CACTI_DEV_VERSION')) { fwrite(STDERR, 'CACTI_DEV_VERSION is not defined' . PHP_EOL); exit(1); } echo CACTI_DEV_VERSION;")"
if [ -z "$dev_version" ]; then
echo "CACTI_DEV_VERSION resolved to an empty value" >&2
exit 1
fi
mysql -h "$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --skip-ssl "$DB_NAME" -e \
"UPDATE version SET cacti = '${dev_version}'"
# Seed the htmx_enabled toggle so the helper returns the enabled path.
mysql -h "$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --skip-ssl "$DB_NAME" -e \
"REPLACE INTO settings (name, value) VALUES ('htmx_enabled', 'on')"
fi
# Domain auth against the sibling OpenLDAP service. Re-applied on every
# start so a leftover settings row cannot leave the stack on local-only auth.
ldap_hash="$(php -r 'echo password_hash("unused-local-hash", PASSWORD_DEFAULT);')"
printf '%s\n' \
"REPLACE INTO settings (name, value) VALUES ('auth_method', '4');" \
"REPLACE INTO settings (name, value) VALUES ('guest_user', '0');" \
"REPLACE INTO settings (name, value) VALUES ('user_template', '1');" \
"INSERT INTO login_providers (id, name, type, enabled, debug, is_default, allow_auth_cookies, user_id, parameters) VALUES (1, 'E2E LDAP', 1, 'on', '', 1, 'on', 0, '{\"server\":\"openldap\",\"port\":389,\"port_ssl\":636,\"proto_version\":3,\"network_timeout\":2,\"bind_timeout\":2,\"encryption\":0,\"tls_certificate\":2,\"referrals\":0,\"mode\":0,\"dn\":\"cn=<username>,ou=users,dc=example,dc=org\",\"group_dn\":\"\",\"group_attrib\":\"\",\"group_member_type\":0,\"search_base\":\"ou=users,dc=example,dc=org\",\"search_filter\":\"(cn=<username>)\",\"specific_dn\":\"\",\"specific_password\":\"\",\"claim_full_name\":\"\",\"claim_email\":\"\"}') ON DUPLICATE KEY UPDATE name=VALUES(name), enabled='on', is_default=1, user_id=0, parameters=VALUES(parameters);" \
"INSERT INTO user_auth (id, username, password, realm, full_name, enabled) VALUES (1001, 'ldapuser', '${ldap_hash}', 1001, 'LDAP E2E User', 'on') ON DUPLICATE KEY UPDATE password=VALUES(password), realm=1001, enabled='on';" \
"INSERT INTO user_auth_realm (user_id, realm_id) SELECT 1001, realm_id FROM user_auth_realm WHERE user_id=1 ON DUPLICATE KEY UPDATE user_id=VALUES(user_id);" \
| mysql -h "$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --skip-ssl "$DB_NAME"
# Cacti writes to log/, rra/, resource/, cache/. The image build drops log/
# and cache/ via .dockerignore, so recreate any missing directory before the
# chown. global.php aborts with a FATAL when log/cacti.log is not writable,
# which suppresses the login page the htmx specs assert against.
mkdir -p /var/www/html/log /var/www/html/rra /var/www/html/resource /var/www/html/cache
chown -R www-data:www-data /var/www/html/log /var/www/html/rra /var/www/html/resource /var/www/html/cache \
2>/dev/null || true
exec "$@"