diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb88f3334..a9821f13a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,10 +43,14 @@ jobs: fail-fast: false matrix: script: - - name: Basic - args: "database_engine=postgresql database_version=postgresql@14.1" - - name: Extended - args: "use_celery=y use_drf=y js_task_runner=Gulp database_engine=postgresql database_version=postgresql@14.1" + - name: Basic - Postgres + args: "database_engine=postgresql database_version='postgresql@14.1'" + - name: Extended - Postgres + args: "use_celery=y use_drf=y js_task_runner=Gulp database_engine=postgresql database_version='postgresql@14.1'" + - name: Basic - MySQL + args: "database_engine=mysql database_version='mysql@8.0.28'" + - name: Extended - MySQL + args: "use_celery=y use_drf=y js_task_runner=Gulp database_engine=mysql database_version='mysql@8.0.28'" name: "${{ matrix.script.name }} Docker" runs-on: ubuntu-latest diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index adb0f894d..70ff207a7 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -257,7 +257,7 @@ def set_database_user(file_path: str, value: str, database_engine: str): def set_database_password(file_path: str, database_engine: str, value: str = None): database_password = set_flag( file_path, - f"!!!SET {database_engine.upper()}_USER!!!", + f"!!!SET {database_engine.upper()}_PASSWORD!!!", value=value, length=64, using_digits=True, @@ -266,6 +266,18 @@ def set_database_password(file_path: str, database_engine: str, value: str = Non return database_password +def set_mysql_root_password(file_path: str, database_engine: str, value: str = None): + database_root_password = set_flag( + file_path, + f"!!!SET {database_engine.upper()}_ROOT_PASSWORD!!!", + value=value, + length=74, + using_digits=True, + using_ascii_letters=True, + ) + return database_root_password + + def get_database_env_path(env: str, database_engine: str): local_postgres_envs_path = os.path.join(".envs", ".local", ".postgres") production_postgres_envs_path = os.path.join(".envs", ".production", ".postgres") @@ -345,6 +357,19 @@ def set_flags_in_envs(database_user, celery_flower_user, debug=False): value=DEBUG_VALUE if debug else None, ) + if selected_database == "mysql": + set_mysql_root_password( + get_database_env_path(env="local", database_engine=selected_database), + database_engine=selected_database, + value=DEBUG_VALUE if debug else None, + ) + + set_mysql_root_password( + get_database_env_path(env="prod", database_engine=selected_database), + database_engine=selected_database, + value=DEBUG_VALUE if debug else None, + ) + set_celery_flower_user(local_django_envs_path, value=celery_flower_user) set_celery_flower_password( local_django_envs_path, value=DEBUG_VALUE if debug else None diff --git a/{{cookiecutter.project_slug}}/.envs/.local/.mysql b/{{cookiecutter.project_slug}}/.envs/.local/.mysql index 765b69183..221c8e264 100644 --- a/{{cookiecutter.project_slug}}/.envs/.local/.mysql +++ b/{{cookiecutter.project_slug}}/.envs/.local/.mysql @@ -6,4 +6,3 @@ MYSQL_DATABASE={{ cookiecutter.project_slug }} MYSQL_USER=!!!SET MYSQL_USER!!! MYSQL_PASSWORD=!!!SET MYSQL_PASSWORD!!! MYSQL_ROOT_PASSWORD=!!!SET MYSQL_ROOT_PASSWORD!!! - diff --git a/{{cookiecutter.project_slug}}/.envs/.local/.postgres b/{{cookiecutter.project_slug}}/.envs/.local/.postgres index f190db8e6..7a11cb3ad 100644 --- a/{{cookiecutter.project_slug}}/.envs/.local/.postgres +++ b/{{cookiecutter.project_slug}}/.envs/.local/.postgres @@ -3,5 +3,5 @@ POSTGRES_HOST=postgres POSTGRES_PORT=5432 POSTGRES_DB={{ cookiecutter.project_slug }} -POSTGRES_USER=!!!SET POSTGRES_USER!!! -POSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!! +POSTGRES_USER=!!!SET POSTGRESQL_USER!!! +POSTGRES_PASSWORD=!!!SET POSTGRESQL_PASSWORD!!! diff --git a/{{cookiecutter.project_slug}}/.envs/.production/.postgres b/{{cookiecutter.project_slug}}/.envs/.production/.postgres index f190db8e6..7a11cb3ad 100644 --- a/{{cookiecutter.project_slug}}/.envs/.production/.postgres +++ b/{{cookiecutter.project_slug}}/.envs/.production/.postgres @@ -3,5 +3,5 @@ POSTGRES_HOST=postgres POSTGRES_PORT=5432 POSTGRES_DB={{ cookiecutter.project_slug }} -POSTGRES_USER=!!!SET POSTGRES_USER!!! -POSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!! +POSTGRES_USER=!!!SET POSTGRESQL_USER!!! +POSTGRES_PASSWORD=!!!SET POSTGRESQL_PASSWORD!!! diff --git a/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile b/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile index 6f1bb8b5e..c9c4bfc4d 100644 --- a/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile @@ -12,8 +12,13 @@ ENV PYTHONDONTWRITEBYTECODE 1 RUN apt-get update && apt-get install --no-install-recommends -y \ # dependencies for building Python packages build-essential \ + {%- if cookiecutter.database_engine == "postgresql" %} # psycopg2 dependencies libpq-dev \ + {%- elif cookiecutter.database_engine == "mysql" %} + # mysql dependency + default-libmysqlclient-dev \ + {%- endif %} # cleaning up unused files && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && rm -rf /var/lib/apt/lists/* @@ -37,8 +42,13 @@ ENV PYTHONDONTWRITEBYTECODE 1 RUN apt-get update && apt-get install --no-install-recommends -y \ # To run the Makefile make \ + {%- if cookiecutter.database_engine == "postgresql" %} # psycopg2 dependencies libpq-dev \ + {%- elif cookiecutter.database_engine == "mysql" %} + # mysql dependency + default-libmysqlclient-dev \ + {%- endif %} # Translations dependencies gettext \ # Uncomment below lines to enable Sphinx output to latex and pdf diff --git a/{{cookiecutter.project_slug}}/compose/production/django/entrypoint b/{{cookiecutter.project_slug}}/compose/production/django/entrypoint index 109fcfdcc..52f535609 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/entrypoint +++ b/{{cookiecutter.project_slug}}/compose/production/django/entrypoint @@ -19,7 +19,7 @@ export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES {%- endif %} {%- if cookiecutter.database_engine == 'mysql' %} if [ -z "${MYSQL_USER}" ]; then - base_mysql_image_default_user='mysql' + base_mysql_image_default_user='root' export MYSQL_USER="${base_mysql_image_default_user}" fi export DATABASE_URL="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}" diff --git a/{{cookiecutter.project_slug}}/compose/production/mysql/Dockerfile b/{{cookiecutter.project_slug}}/compose/production/mysql/Dockerfile index 71eabc804..65aa79ab9 100644 --- a/{{cookiecutter.project_slug}}/compose/production/mysql/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/production/mysql/Dockerfile @@ -4,3 +4,7 @@ COPY ./compose/production/mysql/maintenance /usr/local/bin/maintenance RUN chmod +x /usr/local/bin/maintenance/* RUN mv /usr/local/bin/maintenance/* /usr/local/bin \ && rmdir /usr/local/bin/maintenance + +COPY ./compose/production/mysql/init.sh /docker-entrypoint-initdb.d +RUN sed -i 's/\r$//g' /docker-entrypoint-initdb.d/init.sh +RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/init.sh diff --git a/{{cookiecutter.project_slug}}/compose/production/mysql/init.sh b/{{cookiecutter.project_slug}}/compose/production/mysql/init.sh new file mode 100644 index 000000000..e6802e377 --- /dev/null +++ b/{{cookiecutter.project_slug}}/compose/production/mysql/init.sh @@ -0,0 +1,40 @@ +#!/bin/bash + + +initialize() { + { + mysql_note "Giving user ${MYSQL_USER} access to schema test_${MYSQL_DATABASE}" + docker_process_sql --database=mysql <<<"GRANT ALL ON \`test_${MYSQL_DATABASE//_/\\_}\`.* TO '$MYSQL_USER'@'%' ;" + + # exporting dummy MYSQL_ONETIME_PASSWORD to avoid -> MYSQL_ONETIME_PASSWORD: unbound variable + export DUMMY_ONETIME_PASSWORD="$MYSQL_ROOT_PASSWORD" + } || { + exit 1 + } +} + +docker_process_sql() { + if [ -n "$MYSQL_DATABASE" ]; then + set -- --database="$MYSQL_DATABASE" "$@" + fi + + mysql --protocol=socket -uroot --password="${MYSQL_ROOT_PASSWORD}" -hlocalhost --socket="${SOCKET}" --comments "$@" +} + +# logging functions +mysql_log() { + local type="$1"; shift + # accept argument string or stdin + local text="$*"; if [ "$#" -eq 0 ]; then text="$(cat)"; fi + local dt; dt="$(date --rfc-3339=seconds)" + printf '%s [%s] [Entrypoint]: %s\n' "$dt" "$type" "$text" +} + +mysql_note() { + mysql_log Note "$@" +} + +until (initialize); do + >&2 echo 'Waiting for MYSQL to execute init' + sleep 1 +done