diff --git a/config/confluence.cfg.cluster.xml.j2 b/config/confluence.cfg.cluster.xml.j2 new file mode 100644 index 0000000..c0b0132 --- /dev/null +++ b/config/confluence.cfg.cluster.xml.j2 @@ -0,0 +1,16 @@ + + + + true + {{ atl_product_home_shared }} + {{ atl_product_home_shared }} + {{ atl_hazelcast_network_aws_iam_role }} + {{ atl_hazelcast_network_aws_iam_region }} + {{ atl_hazelcast_network_aws_host_header }} + {{ atl_hazelcast_network_aws_tag_key }} + {{ atl_hazelcast_network_aws_tag_value }} + aws + {{ atl_aws_stack_name }} + 1 + + diff --git a/config/confluence.cfg.db.xml.j2 b/config/confluence.cfg.db.xml.j2 new file mode 100644 index 0000000..c72b39f --- /dev/null +++ b/config/confluence.cfg.db.xml.j2 @@ -0,0 +1,19 @@ + + + + {{ atl_db_choice }} + {{ atl_db_dialect }} + {{ atl_db_driver }} + {{ atl_jdbc_url }} + {{ atl_jdbc_user }} + {{ atl_jdbc_password }} + {{ atl_db_poolminsize }} + {{ atl_db_poolmaxsize }} + {{ atl_db_timeout }} + {{ atl_db_idletestperiod }} + {{ atl_db_maxstatements }} + {{ atl_db_validate }} + {{ atl_db_acquireincrement }} + {{ atl_db_validationquery }} + + diff --git a/config/confluence.cfg.head.xml.j2 b/config/confluence.cfg.head.xml.j2 new file mode 100644 index 0000000..521bfb8 --- /dev/null +++ b/config/confluence.cfg.head.xml.j2 @@ -0,0 +1,17 @@ + + + + + + + setupstart + custom + 0 + + + database-type-standard + ${localHome}/temp + ${confluenceHome}/attachments + + + diff --git a/config/confluence.cfg.tail.xml.j2 b/config/confluence.cfg.tail.xml.j2 new file mode 100644 index 0000000..225be14 --- /dev/null +++ b/config/confluence.cfg.tail.xml.j2 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/config/confluence.cfg.xml.j2 b/config/confluence.cfg.xml.j2 deleted file mode 100644 index 4b5368c..0000000 --- a/config/confluence.cfg.xml.j2 +++ /dev/null @@ -1,42 +0,0 @@ - - - - - setupstart - custom - 0 - - - postgresql - database-type-standard - com.atlassian.confluence.impl.hibernate.dialect.PostgreSQLDialect - ${localHome}/temp - ${confluenceHome}/attachments - - {{ atl_db_driver }} - {{ atl_jdbc_url }} - {{ atl_jdbc_user }} - {{ atl_jdbc_password }} - {{ atl_db_poolminsize }} - {{ atl_db_poolmaxsize }} - {{ atl_db_timeout }} - {{ atl_db_idletestperiod }} - {{ atl_db_maxstatements }} - {{ atl_db_validate }} - {{ atl_db_acquireincrement }} - select version(); - - {{ atl_product_home_shared }} - true - {{ atl_product_home_shared }} - {{ atl_hazelcast_network_aws_iam_role }} - {{ atl_hazelcast_network_aws_iam_region }} - {{ atl_hazelcast_network_aws_host_header }} - {{ atl_hazelcast_network_aws_tag_key }} - {{ atl_hazelcast_network_aws_tag_value }} - aws - {{ atl_aws_stack_name }} - 1 - - - diff --git a/entrypoint.sh b/entrypoint.sh index ef4bc16..464e836 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -43,7 +43,58 @@ log "Generating ${CONFLUENCE_INSTALL_DIR}/conf/server.xml" > ${CONFLUENCE_INSTALL_DIR}/conf/server.xml ###################################################################### -# Configure login properties +# Confluence config files + +log "Generating ${CONFLUENCE_HOME}/confluence.cfg.xml" + +/opt/atlassian/bin/templater.sh \ + /opt/atlassian/etc/confluence.cfg.head.xml.j2 \ + > ${CONFLUENCE_HOME}/confluence.cfg.xml + +: ${ATL_JDBC_URL:=} +if [[ ! -z "$ATL_JDBC_URL" ]]; then + declare -A databases=( + ["mysql-driver"]="com.mysql.jdbc.Driver" + ["mysql-dialect"]="com.atlassian.confluence.impl.hibernate.dialect.MySQLDialect" + ["postgresql-driver"]="org.postgresql.Driver" + ["postgresql-dialect"]="com.atlassian.confluence.impl.hibernate.dialect.PostgreSQLDialect" + ["mssql-driver"]="com.microsoft.sqlserver.jdbc.SQLServerDriver" + ["mssql-dialect"]="com.atlassian.confluence.impl.hibernate.dialect.SQLServerDialect" + ["oracle12c-driver"]="oracle.jdbc.driver.OracleDriver" + ["oracle12c-dialect"]="com.atlassian.confluence.impl.hibernate.dialect.OracleDialect" + ) + + # Must be supplied + export atl_jdbc_url=${ATL_JDBC_URL} + export atl_jdbc_user=${ATL_JDBC_USER} + export atl_jdbc_password=${ATL_JDBC_PASSWORD} + export atl_db_choice=${ATL_DB_TYPE} + + export atl_db_driver=${databases[${atl_db_choice}"-driver"]} + export atl_db_dialect=${databases[${atl_db_choice}"-dialect"]} + + # Defaults, can be overridden + export atl_db_poolmaxsize=${ATL_DB_POOLMAXSIZE:=100} + export atl_db_poolminsize=${ATL_DB_POOLMINSIZE:=20} + export atl_db_timeout=${ATL_DB_TIMEOUT:=30} + export atl_db_idletestperiod=${ATL_DB_IDLETESTPERIOD:=100} + export atl_db_maxstatements=${ATL_DB_MAXSTATEMENTS:=0} + export atl_db_validate=${ATL_DB_VALIDATE:=false} + export atl_db_acquireincrement=${ATL_DB_ACQUIREINCREMENT:=1} + export atl_db_validationquery=${ATL_DB_VALIDATIONQUERY:=select 1} + + /opt/atlassian/bin/templater.sh \ + /opt/atlassian/etc/confluence.cfg.db.xml.j2 \ + >> ${CONFLUENCE_HOME}/confluence.cfg.xml + +fi + +/opt/atlassian/bin/templater.sh \ + /opt/atlassian/etc/confluence.cfg.tail.xml.j2 \ + >> ${CONFLUENCE_HOME}/confluence.cfg.xml +chown ${RUN_USER}.${RUN_GROUP} ${CONFLUENCE_HOME}/confluence.cfg.xml +chmod 0640 ${CONFLUENCE_HOME}/confluence.cfg.xml + # The default is two weeks, in seconds, same as the seraph default. export atl_autologin_cookie_age=${ATL_AUTOLOGIN_COOKIE_AGE:=1209600} @@ -54,6 +105,14 @@ log "Generating ${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/classes/seraph-conf > ${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/classes/seraph-config.xml +export atl_product_home=${CONFLUENCE_HOME} + +log "Generating ${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/classes/confluence-init.properties" +/opt/atlassian/bin/templater.sh \ + /opt/atlassian/etc/confluence-init.properties.j2 \ + > ${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/classes/confluence-init.properties + + # Start Confluence as the correct user if [ "${UID}" -eq 0 ]; then echo "User is currently root. Will change directory ownership to ${RUN_USER}:${RUN_GROUP}, then downgrade permission to ${RUN_USER}" diff --git a/scripts/templater.sh b/scripts/templater.sh index 2062369..f0855cc 100755 --- a/scripts/templater.sh +++ b/scripts/templater.sh @@ -16,6 +16,8 @@ vars=$(grep -oE '\{\{\s*[A-Za-z0-9_]+\s*\}\}' "$template" | sort | uniq | sed -e if [[ -z "$vars" ]]; then echo "Warning: No variable was found in $template, syntax is {{VAR}}" >&2 + cat $template + exit fi var_value() { diff --git a/tests/test_image.py b/tests/test_image.py index 6283202..cfe3623 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -31,6 +31,16 @@ def wait_for_proc(container, proc_str, max_wait=10): raise TimeoutError("Failed to find target process") +def wait_for_file(container, path, max_wait=10): + waited = 0 + while waited < max_wait: + if container.file(path).exists: + return + time.sleep(0.1) + waited += 0.1 + + raise TimeoutError("Failed to find target process") + ###################################################################### # Tests @@ -140,7 +150,7 @@ def test_server_xml_params(docker_cli, image): def test_seraph_defaults(docker_cli, image): container = run_image(docker_cli, image) - _jvm = wait_for_proc(container, "org.apache.catalina.startup.Bootstrap") + wait_for_file(container, "/opt/atlassian/confluence/confluence/WEB-INF/classes/seraph-config.xml") xml = etree.fromstring(container.file('/opt/atlassian/confluence/confluence/WEB-INF/classes/seraph-config.xml').content) param = xml.xpath('//param-name[text()="autologin.cookie.age"]')[0].getnext() @@ -149,7 +159,7 @@ def test_seraph_defaults(docker_cli, image): def test_seraph_login_set(docker_cli, image): container = run_image(docker_cli, image, environment={"ATL_AUTOLOGIN_COOKIE_AGE": "TEST_VAL"}) - _jvm = wait_for_proc(container, "org.apache.catalina.startup.Bootstrap") + wait_for_file(container, "/opt/atlassian/confluence/confluence/WEB-INF/classes/seraph-config.xml") xml = etree.fromstring(container.file('/opt/atlassian/confluence/confluence/WEB-INF/classes/seraph-config.xml').content) param = xml.xpath('//param-name[text()="autologin.cookie.age"]')[0].getnext() @@ -158,26 +168,73 @@ def test_seraph_login_set(docker_cli, image): def test_conf_init_set(docker_cli, image): container = run_image(docker_cli, image, environment={"CONFLUENCE_HOME": "/tmp/"}) - _jvm = wait_for_proc(container, "org.apache.catalina.startup.Bootstrap") + wait_for_file(container, "/opt/atlassian/confluence/confluence/WEB-INF/classes/confluence-init.properties") init = container.file('/opt/atlassian/confluence/confluence/WEB-INF/classes/confluence-init.properties') assert init.contains("confluence.home = /tmp/") -# -# def test_confluence_cfg_xml_defaults(docker_cli, image): -# environment = { -# -# } -# container = docker_cli.containers.run(image, environment=environment, detach=True) -# confluence_cfg_xml = get_fileobj_from_container(container, '/var/atlassian/application-data/confluence/confluence.cfg.xml') -# xml = etree.parse(confluence_cfg_xml) -# -# -# def test_confluence_cfg_xml_params(docker_cli, image): -# environment = { -# -# } -# container = docker_cli.containers.run(image, environment=environment, detach=True) -# confluence_cfg_xml = get_fileobj_from_container(container, '/var/atlassian/application-data/confluence/confluence.cfg.xml') -# xml = etree.parse(confluence_cfg_xml) +def test_confluence_xml_default(docker_cli, image): + container = run_image(docker_cli, image) + wait_for_file(container, "/opt/atlassian/confluence/confluence/WEB-INF/classes/confluence-init.properties") + #_jvm = wait_for_proc(container, "org.apache.catalina.startup.Bootstrap") + + xml = etree.fromstring(container.file('/var/atlassian/application-data/confluence/confluence.cfg.xml').content) + assert xml.xpath('/confluence-configuration/buildNumber')[0].text == "0" + assert xml.xpath('/confluence-configuration/properties/property[@name="hibernate.connection.url"]') == [] + +def test_confluence_xml_postgres(docker_cli, image): + environment = { + 'ATL_DB_TYPE': 'postgresql', + 'ATL_JDBC_URL': 'atl_jdbc_url', + 'ATL_JDBC_USER': 'atl_jdbc_user', + 'ATL_JDBC_PASSWORD': 'atl_jdbc_password' + } + container = run_image(docker_cli, image, environment=environment) + wait_for_file(container, "/opt/atlassian/confluence/confluence/WEB-INF/classes/confluence-init.properties") + + xml = etree.fromstring(container.file('/var/atlassian/application-data/confluence/confluence.cfg.xml').content) + assert xml.xpath('//property[@name="hibernate.connection.url"]')[0].text == "atl_jdbc_url" + assert xml.xpath('//property[@name="hibernate.connection.username"]')[0].text == "atl_jdbc_user" + assert xml.xpath('//property[@name="hibernate.connection.password"]')[0].text == "atl_jdbc_password" + assert xml.xpath('//property[@name="confluence.database.choice"]')[0].text == "postgresql" + assert xml.xpath('//property[@name="hibernate.dialect"]')[0].text == "com.atlassian.confluence.impl.hibernate.dialect.PostgreSQLDialect" + assert xml.xpath('//property[@name="hibernate.connection.driver_class"]')[0].text == "org.postgresql.Driver" + + assert xml.xpath('//property[@name="hibernate.c3p0.min_size"]')[0].text == "20" + assert xml.xpath('//property[@name="hibernate.c3p0.max_size"]')[0].text == "100" + assert xml.xpath('//property[@name="hibernate.c3p0.timeout"]')[0].text == "30" + assert xml.xpath('//property[@name="hibernate.c3p0.idle_test_period"]')[0].text == "100" + assert xml.xpath('//property[@name="hibernate.c3p0.max_statements"]')[0].text == "0" + assert xml.xpath('//property[@name="hibernate.c3p0.validate"]')[0].text == "false" + assert xml.xpath('//property[@name="hibernate.c3p0.acquire_increment"]')[0].text == "1" + assert xml.xpath('//property[@name="hibernate.c3p0.preferredTestQuery"]')[0].text == "select 1" + +def test_confluence_xml_postgres_all_set(docker_cli, image): + environment = { + 'ATL_DB_TYPE': 'postgresql', + 'ATL_JDBC_URL': 'atl_jdbc_url', + 'ATL_JDBC_USER': 'atl_jdbc_user', + 'ATL_JDBC_PASSWORD': 'atl_jdbc_password', + 'ATL_DB_POOLMAXSIZE': 'x100', + 'ATL_DB_POOLMINSIZE': 'x20', + 'ATL_DB_TIMEOUT': 'x30', + 'ATL_DB_IDLETESTPERIOD': 'x100', + 'ATL_DB_MAXSTATEMENTS': 'x0', + 'ATL_DB_VALIDATE': 'xfalse', + 'ATL_DB_ACQUIREINCREMENT': 'x1', + 'ATL_DB_VALIDATIONQUERY': 'xselect 1' + } + container = run_image(docker_cli, image, environment=environment) + wait_for_file(container, "/opt/atlassian/confluence/confluence/WEB-INF/classes/confluence-init.properties") + + xml = etree.fromstring(container.file('/var/atlassian/application-data/confluence/confluence.cfg.xml').content) + + assert xml.xpath('//property[@name="hibernate.c3p0.min_size"]')[0].text == "x20" + assert xml.xpath('//property[@name="hibernate.c3p0.max_size"]')[0].text == "x100" + assert xml.xpath('//property[@name="hibernate.c3p0.timeout"]')[0].text == "x30" + assert xml.xpath('//property[@name="hibernate.c3p0.idle_test_period"]')[0].text == "x100" + assert xml.xpath('//property[@name="hibernate.c3p0.max_statements"]')[0].text == "x0" + assert xml.xpath('//property[@name="hibernate.c3p0.validate"]')[0].text == "xfalse" + assert xml.xpath('//property[@name="hibernate.c3p0.acquire_increment"]')[0].text == "x1" + assert xml.xpath('//property[@name="hibernate.c3p0.preferredTestQuery"]')[0].text == "xselect 1"