From d52ad4fbc28985e61276450144e92b29bec8ff0b Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 10 Nov 2021 21:51:55 +0000 Subject: [PATCH] misc: import docker improvements from 7.39.1.dev2 - Legacy-Id: 19629 --- .devcontainer/devcontainer.json | 112 +++++++---- .devcontainer/docker-compose.extend.yml | 8 + .devcontainer/init.sh | 164 --------------- .devcontainer/settings_local.py | 65 ------ .vscode/settings.json | 45 +++++ .vscode/tasks.json | 190 ++++++++++++------ docker/Dockerfile | 137 ------------- docker/README.md | 165 ++++++++++++--- docker/_old/README.md | 56 ++++++ docker/_old/run | 110 ++++++++++ .../Dockerfile => docker/app.Dockerfile | 113 +++++------ docker/assets/vscode-debug-breakpoint.png | Bin 0 -> 6002 bytes docker/assets/vscode-debug-toolbar.png | Bin 0 -> 6185 bytes docker/assets/vscode-ports.png | Bin 0 -> 27172 bytes docker/assets/vscode-sqltools.png | Bin 0 -> 70699 bytes docker/assets/vscode-tasks.png | Bin 0 -> 26733 bytes docker/assets/vscode-terminal-new.png | Bin 0 -> 23253 bytes docker/cleandb | 8 + docker/{ => configs}/settings_local.py | 14 +- .../configs}/settings_local_debug.py | 0 docker/configs/settings_local_sqlitetest.py | 84 ++++++++ docker/db.Dockerfile | 56 ++++++ docker/docker-compose.extend.yml | 9 + {.devcontainer => docker}/docker-compose.yml | 32 ++- docker/docker-init.sh | 91 --------- docker/{ => misc}/build | 18 +- docker/{ => misc}/copydb | 0 docker/run | 111 +--------- docker/scripts/app-init.sh | 110 ++++++++++ .../app-rsync-extras.sh} | 0 docker/scripts/app-win32-timezone-fix.sh | 15 ++ docker/{ => scripts}/updatedb | 0 32 files changed, 931 insertions(+), 782 deletions(-) create mode 100644 .devcontainer/docker-compose.extend.yml delete mode 100755 .devcontainer/init.sh delete mode 100644 .devcontainer/settings_local.py create mode 100644 .vscode/settings.json delete mode 100644 docker/Dockerfile create mode 100644 docker/_old/README.md create mode 100644 docker/_old/run rename .devcontainer/Dockerfile => docker/app.Dockerfile (57%) create mode 100644 docker/assets/vscode-debug-breakpoint.png create mode 100644 docker/assets/vscode-debug-toolbar.png create mode 100644 docker/assets/vscode-ports.png create mode 100644 docker/assets/vscode-sqltools.png create mode 100644 docker/assets/vscode-tasks.png create mode 100644 docker/assets/vscode-terminal-new.png create mode 100644 docker/cleandb rename docker/{ => configs}/settings_local.py (86%) rename {.devcontainer => docker/configs}/settings_local_debug.py (100%) create mode 100644 docker/configs/settings_local_sqlitetest.py create mode 100644 docker/db.Dockerfile create mode 100644 docker/docker-compose.extend.yml rename {.devcontainer => docker}/docker-compose.yml (66%) delete mode 100644 docker/docker-init.sh rename docker/{ => misc}/build (77%) mode change 100755 => 100644 rename docker/{ => misc}/copydb (100%) mode change 100755 => 100644 create mode 100755 docker/scripts/app-init.sh rename docker/{rsync-extras => scripts/app-rsync-extras.sh} (100%) create mode 100755 docker/scripts/app-win32-timezone-fix.sh rename docker/{ => scripts}/updatedb (100%) mode change 100755 => 100644 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 88fa4bccc..5a97a990a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,29 +1,32 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.202.5/containers/python-3 { - "name": "IETF Datatracker", - "dockerComposeFile": "docker-compose.yml", + "name": "IETF Datatracker", + "dockerComposeFile": ["../docker/docker-compose.yml", "docker-compose.extend.yml"], "service": "app", - "workspaceFolder": "/usr/local/share/datatracker", + "workspaceFolder": "/root/src", "shutdownAction": "stopCompose", "postCreateCommand": "/docker-init.sh", - - // Set *default* container specific settings.json values on container create. - "settings": { + "containerEnv": { + "EDITOR_VSCODE": "true" + }, + + // Set *default* container specific settings.json values on container create. + "settings": { "terminal.integrated.defaultProfile.linux": "zsh", - "python.pythonPath": "/usr/local/bin/python", - "python.languageServer": "Pylance", - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", - "python.formatting.blackPath": "/usr/local/py-utils/bin/black", - "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", - "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", - "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", - "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", - "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", - "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", - "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint", + "python.pythonPath": "/usr/local/bin/python", + "python.languageServer": "Pylance", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", + "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", + "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", + "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", + "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", + "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", + "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint", "python.testing.pytestArgs": [ "ietf" ], @@ -35,27 +38,56 @@ "./ietf", "-p", "test*.py" + ], + "sqltools.connections": [ + // Default connection to dev DB container + { + "name": "Local Dev", + "server": "db", + "port": 3306, + "database": "ietf_utf8", + "username": "django", + "password": "RkTkDPFnKpko", + "driver": "MySQL", + "askForPassword": false, + "connectionTimeout": 60 + } ] // "python.envFile": "${workspaceFolder}/.devcontainer/dev.env" - }, - - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python", - "ms-python.vscode-pylance", - "ms-azuretools.vscode-docker", - "editorconfig.editorconfig", - "redhat.vscode-yaml", - "visualstudioexptteam.vscodeintellicode", - "batisteo.vscode-django", - ], - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - "forwardPorts": [8000, 3306] - - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "sh /docker-init.sh", - - // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - // "remoteUser": "django" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance", + "ms-azuretools.vscode-docker", + "editorconfig.editorconfig", + "redhat.vscode-yaml", + "visualstudioexptteam.vscodeintellicode", + "batisteo.vscode-django", + "mutantdino.resourcemonitor", + "spmeesseman.vscode-taskexplorer", + "mtxr.sqltools", + "mtxr.sqltools-driver-mysql" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [8000, 3306], + + "portsAttributes": { + "8000": { + "label": "Datatracker", + "onAutoForward": "notify" + }, + "3306": { + "label": "MariaDB", + "onAutoForward": "silent" + } + } + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "sh /docker-init.sh", + + // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "django" } diff --git a/.devcontainer/docker-compose.extend.yml b/.devcontainer/docker-compose.extend.yml new file mode 100644 index 000000000..148732db5 --- /dev/null +++ b/.devcontainer/docker-compose.extend.yml @@ -0,0 +1,8 @@ +version: '3.8' + +services: + app: + environment: + EDITOR_VSCODE: 1 + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db \ No newline at end of file diff --git a/.devcontainer/init.sh b/.devcontainer/init.sh deleted file mode 100755 index d29a017bc..000000000 --- a/.devcontainer/init.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/bash - -# A little bit of setup -export LANG=en_GB.UTF-8 - -WORKSPACEDIR="/usr/local/share/datatracker" - -echo "Gathering info ..." -if [ ! "$USER" ]; then - echo "Environment variable USER is not set -- will set USER='django'." - USER="django" -fi -if [ ! "$UID" ]; then - echo "Environment variable UID is not set -- will set UID='1000'." - UID="1000" -fi -if [ ! "$GID" ]; then - echo "Environment variable GID is not set -- will set GID='1000'." - GID="1000" -fi -if [ ! "$TAG" ]; then - echo "Environment variable TAG is not set -- will set TAG='datatracker'." - TAG="datatracker" -fi -echo "User $USER ($UID:$GID)" - -echo "Checking if syslogd is running ..." -if ! /etc/init.d/rsyslog status > /dev/null; then - echo "Starting syslogd ..." - /etc/init.d/rsyslog start -fi - -echo "Waiting for DB container to come online ..." -wget -qO- https://raw.githubusercontent.com/eficode/wait-for/v2.1.3/wait-for | sh -s -- localhost:3306 -- echo "DB ready" - -echo "Checking if the IETF database exists in DB container ..." -if ! mysql --protocol tcp -h localhost -u root --password=ietf --database="ietf_utf8" --execute="SHOW TABLES;" | grep -q 'django'; then - echo "Fetching database ..." - DUMPDIR=/home/$USER/$DATADIR - wget -N --progress=bar:force:noscroll -P $DUMPDIR http://www.ietf.org/lib/dt/sprint/ietf_utf8.sql.gz - - echo "Creating database ..." - mysql --protocol tcp -h localhost -u root --password=ietf --database="ietf_utf8" --execute="DROP DATABASE IF EXISTS ietf_utf8;" - mysqladmin --protocol tcp -h localhost -u root --password=ietf --default-character-set=utf8 create ietf_utf8 - - echo "Setting up permissions ..." - mysql --protocol tcp -h localhost -u root --password="ietf" ietf_utf8 <<< "GRANT ALL PRIVILEGES ON ietf_utf8.* TO 'django'@'%' IDENTIFIED BY 'RkTkDPFnKpko'; FLUSH PRIVILEGES;" - - echo "Loading database (this may take a while)..." - gunzip < $DUMPDIR/ietf_utf8.sql.gz \ - | pv --progress --bytes --rate --eta --cursor --force --size $(gzip --list --quiet $DUMPDIR/ietf_utf8.sql.gz | awk '{ print $2 }') \ - | sed -e 's/ENGINE=MyISAM/ENGINE=InnoDB/' \ - | mysql --protocol tcp -h localhost -u django --password=RkTkDPFnKpko -s -f ietf_utf8 \ - && rm $DUMPDIR/ietf_utf8.sql.gz -fi - -if ! grep -q ":$GID:$" /etc/group ; then - echo "Creating group entry for GID '$GID' ..." - groupadd -g "$GID" "$USER" -fi -if ! id -u "$USER" &> /dev/null; then - echo "Creating user '$USER' ..." - useradd -s /bin/bash --groups staff,sudo --uid $UID --gid $GID $USER - echo "$USER:$USER" | chpasswd -fi - -VIRTDIR="/opt/home/$USER/$TAG" -echo "Checking that there's a virtual environment for $TAG ..." -if [ ! -f $VIRTDIR/bin/activate ]; then - echo "Setting up python virtualenv at $VIRTDIR ..." - mkdir -p $VIRTDIR - python3.6 -m venv $VIRTDIR - echo -e " -# This is from $VIRTDIR/bin/activate, to activate the -# datatracker virtual python environment on docker container entry: -" >> /etc/bash.bashrc - cat $VIRTDIR/bin/activate >> /etc/bash.bashrc - cat /usr/local/share/datatracker/docker/setprompt >> /etc/bash.bashrc -else - echo "Using virtual environment at $VIRTDIR" -fi - -echo "Activating the virtual python environment ..." -. $VIRTDIR/bin/activate - -if [ ! -f "$WORKSPACEDIR/ietf/settings_local.py" ]; then - echo "Setting up a default settings_local.py ..." - cp $WORKSPACEDIR/.devcontainer/settings_local.py $WORKSPACEDIR/ietf/settings_local.py -fi - -if [ ! -f "$WORKSPACEDIR/ietf/settings_local_debug.py" ]; then - echo "Setting up a default settings_local_debug.py ..." - cp $WORKSPACEDIR/.devcontainer/settings_local_debug.py $WORKSPACEDIR/ietf/settings_local_debug.py -fi - -for sub in test/id/ test/staging/ test/archive/ test/rfc test/media test/wiki/ietf; do - dir="$WORKSPACEDIR/$sub" - if [ ! -d "$dir" ]; then - echo "Creating dir $dir" - mkdir -p "$dir"; - fi -done - -for sub in \ - nomcom_keys/public_keys \ - developers/ietf-ftp \ - developers/ietf-ftp/bofreq \ - developers/ietf-ftp/charter \ - developers/ietf-ftp/conflict-reviews \ - developers/ietf-ftp/internet-drafts \ - developers/ietf-ftp/rfc \ - developers/ietf-ftp/status-changes \ - developers/ietf-ftp/yang/catalogmod \ - developers/ietf-ftp/yang/draftmod \ - developers/ietf-ftp/yang/ianamod \ - developers/ietf-ftp/yang/invalmod \ - developers/ietf-ftp/yang/rfcmod \ - developers/www6s \ - developers/www6s/staging \ - developers/www6s/wg-descriptions \ - developers/www6s/proceedings \ - developers/www6/ \ - developers/www6/iesg \ - developers/www6/iesg/evaluation \ - ; do - dir="$WORKSPACEDIR/data/$sub" - if [ ! -d "$dir" ]; then - echo "Creating dir $dir" - mkdir -p "$dir"; - chown "$USER" "$dir" - fi -done - -if [ ! -f "$WORKSPACEDIR/test/data/draft-aliases" ]; then - echo "Generating draft aliases ..." - ietf/bin/generate-draft-aliases } -fi - -if [ ! -f "$WORKSPACEDIR/test/data/group-aliases" ]; then - echo "Generating group aliases ..." - ietf/bin/generate-wg-aliases } -fi - -chown -R $USER /opt/home/$USER -chmod -R g+w /usr/local/lib/ # so we can patch libs if needed - -cd "$WORKSPACEDIR" || cd "/home/$USER/" - -if ! echo "$LANG" | grep "UTF-8"; then - echo "" - echo "Make sure you export LANG=en_GB.UTF-8 (or another UTF-8 locale) in your .bashrc" -else - echo "LANG=$LANG" -fi - -HOME=/opt/home/$USER - -/usr/local/bin/python $WORKSPACEDIR/ietf/manage.py check --settings=settings_local - -echo "Done!" - -# su -p $USER - -exec "$@" \ No newline at end of file diff --git a/.devcontainer/settings_local.py b/.devcontainer/settings_local.py deleted file mode 100644 index ca1b0ce6d..000000000 --- a/.devcontainer/settings_local.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright The IETF Trust 2007-2019, All Rights Reserved -# -*- coding: utf-8 -*- - -import six -if six.PY3: - from typing import Collection, Dict, List, Tuple # pyflakes:ignore - -from ietf.settings import * # pyflakes:ignore - -ALLOWED_HOSTS = ['*'] - -SECRET_KEY = 'jzv$o93h_lzw4a0%0oz-5t5lk+ai=3f8x@uo*9ahu8w4i300o6' - -DATABASES = { - 'default': { - 'HOST': 'db', - 'PORT': 3306, - 'NAME': 'ietf_utf8', - 'ENGINE': 'django.db.backends.mysql', - 'USER': 'django', - 'PASSWORD': 'RkTkDPFnKpko', - 'OPTIONS': { - 'sql_mode': 'STRICT_TRANS_TABLES', - 'init_command': 'SET storage_engine=InnoDB; SET names "utf8"', - }, - }, -} # type: Dict[str, Dict[str, Collection[str]]] - -DATABASE_TEST_OPTIONS = { - 'init_command': 'SET storage_engine=InnoDB', - } - -IDSUBMIT_IDNITS_BINARY = "/usr/local/bin/idnits" -IDSUBMIT_REPOSITORY_PATH = "test/id/" -IDSUBMIT_STAGING_PATH = "test/staging/" -INTERNET_DRAFT_ARCHIVE_DIR = "test/archive/" -INTERNET_ALL_DRAFTS_ARCHIVE_DIR = "test/archive/" -RFC_PATH = "test/rfc/" - -AGENDA_PATH = 'data/developers/www6s/proceedings/' -MEETINGHOST_LOGO_PATH = AGENDA_PATH - -USING_DEBUG_EMAIL_SERVER=True -EMAIL_HOST='localhost' -EMAIL_PORT=2025 - -TRAC_WIKI_DIR_PATTERN = "test/wiki/%s" -TRAC_SVN_DIR_PATTERN = "test/svn/%s" -TRAC_CREATE_ADHOC_WIKIS = [ -] # type: List[Tuple[str, str, str]] - -MEDIA_BASE_DIR = 'test' -MEDIA_ROOT = MEDIA_BASE_DIR + '/media/' -MEDIA_URL = '/media/' - -PHOTOS_DIRNAME = 'photo' -PHOTOS_DIR = MEDIA_ROOT + PHOTOS_DIRNAME - -DOCUMENT_PATH_PATTERN = 'data/developers/ietf-ftp/{doc.type_id}/' - -SUBMIT_YANG_CATALOG_MODEL_DIR = 'data/developers/ietf-ftp/yang/catalogmod/' -SUBMIT_YANG_DRAFT_MODEL_DIR = 'data/developers/ietf-ftp/yang/draftmod/' -SUBMIT_YANG_INVAL_MODEL_DIR = 'data/developers/ietf-ftp/yang/invalmod/' -SUBMIT_YANG_IANA_MODEL_DIR = 'data/developers/ietf-ftp/yang/ianamod/' -SUBMIT_YANG_RFC_MODEL_DIR = 'data/developers/ietf-ftp/yang/rfcmod/' diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..7eefd1893 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,45 @@ +{ + "taskExplorer.exclude": [ + "**/.vscode-test/**", + "**/bin/**", + "**/build/**", + "**/CompiledOutput/**", + "**/dist/**", + "**/doc/**", + "**/ext/**", + "**/out/**", + "**/output/**", + "**/packages/**", + "**/release/**", + "**/releases/**", + "**/samples/**", + "**/sdks/**", + "**/static/**", + "**/target/**", + "**/test/**", + "**/third_party/**", + "**/vendor/**", + "**/work/**", + "/root/src/bootstrap/nuget/MyGet.ps1" + ], + "taskExplorer.enableAnt": false, + "taskExplorer.enableAppPublisher": false, + "taskExplorer.enablePipenv": false, + "taskExplorer.enableBash": false, + "taskExplorer.enableBatch": false, + "taskExplorer.enableGradle": false, + "taskExplorer.enableGrunt": false, + "taskExplorer.enableGulp": false, + "taskExplorer.enablePerl": false, + "taskExplorer.enableMake": false, + "taskExplorer.enableMaven": false, + "taskExplorer.enableNsis": false, + "taskExplorer.enableNpm": false, + "taskExplorer.enablePowershell": false, + "taskExplorer.enablePython": false, + "taskExplorer.enableRuby": false, + "taskExplorer.enableTsc": false, + "taskExplorer.enableWorkspace": true, + "taskExplorer.enableExplorerView": false, + "taskExplorer.enableSideBar": true +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1319ef547..9ab2bd71e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,63 +1,133 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "Run Checks", - "type": "shell", - "command": "/usr/local/bin/python", - "args": [ - "${workspaceFolder}/ietf/manage.py", - "check", - "--settings=settings_local" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "problemMatcher": [] - }, - { - "label": "Run Tests", - "type": "shell", - "command": "/usr/local/bin/python", - "args": [ - "${workspaceFolder}/ietf/manage.py", - "test", - "--settings=settings_sqlitetest" - ], - "group": "test", - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "new", - "showReuseMessage": true, - "clear": false - }, - "problemMatcher": [] - }, - { - "label": "Re-run Setup Project", - "type": "shell", - "command": "/bin/bash", - "args": [ - "/docker-init.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "new", - "showReuseMessage": false, - "clear": false + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Run Checks", + "type": "shell", + "command": "/usr/local/bin/python", + "args": [ + "${workspaceFolder}/ietf/manage.py", + "check", + "--settings=settings_local" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [] }, - "problemMatcher": [] - } - ] + { + "label": "Run All Tests", + "type": "shell", + "command": "/usr/local/bin/python", + "args": [ + "${workspaceFolder}/ietf/manage.py", + "test", + "--settings=settings_local_sqlitetest" + ], + "group": "test", + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "new", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [] + }, + { + "label": "Run JS Tests", + "type": "shell", + "command": "/usr/local/bin/python", + "args": [ + "${workspaceFolder}/ietf/manage.py", + "test", + "--settings=settings_local_sqlitetest", + "--pattern=tests_js.py", + ], + "group": "test", + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "new", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [] + }, + { + "label": "Re-run Setup Project", + "type": "shell", + "command": "/bin/bash", + "args": [ + "/docker-init.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "new", + "showReuseMessage": false, + "clear": false + }, + "problemMatcher": [] + }, + { + "label": "Run SMTP Debugging Server", + "type": "shell", + "command": "/usr/local/bin/python", + "args": ["-m", "smtpd", "-n", "-c", "DebuggingServer", "localhost:2025"], + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "new", + "showReuseMessage": false, + "clear": false + }, + "problemMatcher": [] + }, + { + "label": "Fetch assets via rsync", + "type": "shell", + "command": "/bin/bash", + "args": [ + "${workspaceFolder}/docker/scripts/app-rsync-extras.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "new", + "showReuseMessage": false, + "clear": false + }, + "problemMatcher": [] + }, + { + "label": "Fix Windows Timezone File Linking", + "type": "shell", + "command": "/bin/bash", + "args": [ + "${workspaceFolder}/docker/app-win32-timezone-fix.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "new", + "showReuseMessage": false, + "clear": false + }, + "problemMatcher": [] + } + ] } \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 701f20004..000000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,137 +0,0 @@ -# This is a Dockerfile with everything in it to run the IETF datatracker. -# -# If you make changes to the datatracker that add new dependencies (python -# packages or otherwise), you need to rebuild this image to make them -# available. Do this in the top-level directory of your datatracker source -# tree: -# -# docker/build -# -# You can then execute the datatracker like this (also from the top-level -# datatracker source directory): -# -# docker/run - -FROM python:3.6-bullseye -LABEL maintainer="IETF Tools Team " - -# Default django runserver port -EXPOSE 8000 - -# Default mysqld/mariadb port -EXPOSE 3306 - -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get -y update && \ - # apt-get upgrade is normally not a good idea, but this is a dev container - apt-get -y upgrade && \ - # Install all dependencies that are available as packages - apt-get -y install --no-install-recommends \ - apache2-utils \ - apt-file \ - apt-utils \ - curl \ - enscript \ - gcc \ - ghostscript \ - git \ - gnupg \ - graphviz \ - libmagic-dev \ - libmariadb-dev \ - locales \ - mariadb-server \ - npm \ - pigz \ - pv \ - python-is-python3 \ - rsyslog \ - unzip \ - yang-tools && \ - # Since snap doesn't work in Docker containers, install chromedriver per - # https://gist.github.com/varyonic/dea40abcf3dd891d204ef235c6e8dd79#gistcomment-3160722 - curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ - echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list && \ - apt-get update -y && \ - apt-get install -y --no-install-recommends google-chrome-stable && \ - CHROMEVER=$(google-chrome --product-version | grep -o "[^\.]*\.[^\.]*\.[^\.]*") && \ - DRIVERVER=$(curl "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$CHROMEVER") && \ - curl -L -O -C - "http://chromedriver.storage.googleapis.com/$DRIVERVER/chromedriver_linux64.zip" && \ - unzip chromedriver_linux64.zip -d /bin && \ - rm chromedriver_linux64.zip && \ - # Install some other packages that are not dependencies but make life easier - apt-get -y install --no-install-recommends \ - fish \ - less \ - nano \ - ripgrep \ - subversion \ - zsh && \ - # Reduce image footprint (not that it matters given the size of the above) - apt-get -y clean && \ - rm -rf /var/lib/apt/lists/* - -# Set locale to en_US.UTF-8 -RUN echo "LC_ALL=en_US.UTF-8" >> /etc/environment && \ - echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \ - echo "LANG=en_US.UTF-8" > /etc/locale.conf -RUN dpkg-reconfigure locales && \ - locale-gen en_US.UTF-8 && \ - update-locale LC_ALL en_US.UTF-8 -ENV LC_ALL en_US.UTF-8 - -# Install bower -RUN npm install -g bower - -# Install idnits -ADD https://raw.githubusercontent.com/ietf-tools/idnits-mirror/main/idnits /usr/local/bin/ -RUN chmod +rx /usr/local/bin/idnits - -# Install current datatracker python dependencies -COPY requirements.txt / -RUN pip install -r /requirements.txt - -# Turn off rsyslog kernel logging (doesn't work in Docker) -RUN sed -i '/imklog/s/^/#/' /etc/rsyslog.conf - -# Allow access to mariadb over the network -RUN sed -i 's/127.0.0.1/0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf - -# Turn on mariadb performance_schema -RUN sed -i 's/\[mysqld\]/\[mysqld\]\nperformance_schema=ON/' /etc/mysql/mariadb.conf.d/50-server.cnf - -# Make the mariadb sys schema available for possible installation -# We would normally use the next line, but that has a bug: -# ADD https://github.com/FromDual/mariadb-sys/archive/master.zip / -# This is the repo that has the PR: -ADD https://github.com/grooverdan/mariadb-sys/archive/refs/heads/master.zip / -RUN unzip /master.zip -RUN rm /master.zip - -# Colorize the bash shell -RUN sed -i 's/#force_color_prompt=/force_color_prompt=/' /root/.bashrc - -# Make a database dump available as part of the image, for if a user doesn't -# have one installed locally yet - this saves a bunch of time then -ADD https://www.ietf.org/lib/dt/sprint/ietf_utf8.sql.gz / -RUN pigz -v -d /ietf_utf8.sql.gz && \ - sed -i -e 's/ENGINE=MyISAM/ENGINE=InnoDB/' /ietf_utf8.sql -# see https://dba.stackexchange.com/a/83385 -RUN sed -i 's/\[mysqld\]/\[mysqld\]\ninnodb_buffer_pool_size = 1G\ninnodb_log_buffer_size = 128M\ninnodb_log_file_size = 256M\ninnodb_write_io_threads = 8\ninnodb_flush_log_at_trx_commit = 0/' /etc/mysql/mariadb.conf.d/50-server.cnf && \ - service mariadb start --innodb-doublewrite=0 && \ - echo "This sequence will take a long time, please be patient" && \ - mysqladmin -u root --default-character-set=utf8 create ietf_utf8 && \ - bash -c "cd /mariadb-sys-master && mysql --user root < sys_10.sql" && \ - bash -c "mysql --user root ietf_utf8 <<< \"GRANT ALL PRIVILEGES ON *.* TO django@localhost IDENTIFIED BY 'RkTkDPFnKpko'; FLUSH PRIVILEGES;\"" && \ - bash -c "mysql --user=django --password=RkTkDPFnKpko -f ietf_utf8 < /ietf_utf8.sql" && \ - service mariadb stop && \ - sed -i 's/^innodb_.*//g' /etc/mysql/mariadb.conf.d/50-server.cnf && \ - rm -rf /ietf_utf8.sql /mariadb-sys-master && \ - mv /var/lib/mysql / - -# Copy the startup file -COPY docker-init.sh /docker-init.sh -RUN chmod +x /docker-init.sh - -WORKDIR /root/src -ENTRYPOINT ["/docker-init.sh"] diff --git a/docker/README.md b/docker/README.md index e6c04da40..88e0f2546 100644 --- a/docker/README.md +++ b/docker/README.md @@ -2,8 +2,9 @@ ## Getting started -1. [Set up Docker](https://docs.docker.com/get-started/) on your preferred - platform. +1. [Set up Docker](https://docs.docker.com/get-started/) on your preferred platform. On Windows, it is highly recommended to use the [WSL 2 *(Windows Subsystem for Linux)*](https://docs.docker.com/desktop/windows/wsl/) backend. + +2. On Linux, you must also install [Docker Compose](https://docs.docker.com/compose/install/). Docker Desktop for Mac and Windows already include Docker Compose. 2. If you have a copy of the datatracker code checked out already, simply `cd` to the top-level directory. @@ -11,41 +12,149 @@ If not, check out a datatracker branch as usual. We'll check out `trunk` below, but you can use any branch: - svn co https://svn.ietf.org/svn/tools/ietfdb/trunk - cd trunk + ```sh + svn co https://svn.ietf.org/svn/tools/ietfdb/trunk + cd trunk + ``` -4. **TEMPORARY:** Until a pre-built docker image is available for download, you will need - to build it locally: +3. Follow the instructions for your preferred editor: + - [Visual Studio Code](#using-visual-studio-code) + - [Other Editors / Generic](#using-other-editors--generic) - docker/build +## Using Visual Studio Code - This will take a while (15 to 30m), but only needs to be done once. +This project includes a devcontainer configuration which automates the setup of the development environment with all the required dependencies. -5. Use the `docker/run` script to start the datatracker container. You will be - dropped into a shell from which you can start the datatracker and execute - related commands as usual, for example +### Initial Setup + +1. Launch [VS Code](https://code.visualstudio.com/) +2. Under the **Extensions** tab, install the **Remote - Containers** ([ms-vscode-remote.remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)) extension installed. On Windows, you also need the **Remote - WSL** ([ms-vscode-remote.remote-wsl](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl)) extension to take advantage of the WSL 2 *(Windows Subsystem for Linux)* native integration. +2. Open the top-level directory of the datatracker code you fetched above. +3. A prompt inviting you to reopen the project in containers will appear in the bottom-right corner. Click the **Reopen in Container** button. If you missed the prompt, you can press `F1`, start typing `reopen in container` task and launch it. +4. VS Code will relaunch in the dev environment and create the containers automatically. +5. You may get several warnings prompting you to reload the window as extensions get installed for the first time. Wait for the initialization script to complete before doing so. *(Wait for the message `Done!` to appear in the terminal panel.)* - ietf/manage.py check; ietf/manage.py runserver 0.0.0.0:8000 +### Subsequent Launch - to start the datatracker. +To return to your dev environment created above, simply open **VS Code** and select **File** > **Open Recent** and select the datatracker folder with the `[Dev Container]` suffix. - You can also pass additional arguments to `docker/run`, in which case they - will be executed in the container (instead of a shell being started.) +You can also open the datatracker project folder and click the **Reopen in container** button when prompted. f you missed the prompt, you can press `F1`, start typing `reopen in container` task and launch it. - If you do not already have a copy of the IETF database available in the - `data` directory, one will be downloaded and imported the first time you run - `docker/run`. This will take some time. +### Usage - Once the datatracker has started, you should be able to open - [http://localhost:8000](http://localhost:8000) in a browser and see the - landing page. +- Under the **Run and Debug** tab, you can run the server with the debugger attached using **Run Server** (F5). Once the server is ready to accept connections, you'll be prompted to open in a browser. You can also open [http://localhost:8000](http://localhost:8000) in a browser. + + > An alternate profile **Run Server with Debug Toolbar** is also available from the dropdown menu, which displays various tools + on top of the webpage. However, note that this configuration has a significant performance impact. -## Troubleshooting + To add a **Breakpoint**, simply click to the left of the line gutter you wish to stop at. You can also add **Conditional Breakpoints** and **Logpoint** by right-clicking at the same location. -- If the database fails to start, the cause is usually an incompatibility - between the database that last touched the files in `data/mysql` and the - database running inside the docker container. + ![](assets/vscode-debug-breakpoint.png) - The solution is to blow away your existing database (`rm -rf data/mysql`). A - fresh copy will be retrieved and imported next time you do `docker/run`, which - should resolve this issue. \ No newline at end of file + While running in debug mode (`F5`), the following toolbar is shown at the top of the editor: + + ![](assets/vscode-debug-toolbar.png) + + See this [tutorial](https://code.visualstudio.com/docs/python/tutorial-django#_explore-the-debugger) on how to use the debugging tools for Django in VS Code. + +- An integrated terminal is available with various shell options *(zsh, bash, fish, etc.)*. Use the **New Terminal** button located at the right side of the Terminal panel. You can have as many as needed running in parallel and you can use split to display multiple at once. + + ![](assets/vscode-terminal-new.png) + +- Under the **SQL Tools** tab, a connection **Local Dev** is preconfigured to connect to the DB container. Using this tool, you can list tables, view records and execute SQL queries directly from VS Code. + + > The port `3306` is also exposed to the host automatically, should you prefer to use your own SQL tool. + + ![](assets/vscode-sqltools.png) + +- Under the **Task Explorer** tab, a list of available preconfigured tasks is displayed. *(You may need to expand the tree to `src > vscode` to see it.)* These are common scritps you can run *(e.g. run tests, fetch assets, etc.)*. + + ![](assets/vscode-tasks.png) + +- From the command palette (`F1`), the command **Run Test Task** allows you to choose between running all tests or just the javascript tests. + +- The **Ports** panel, found in the Terminal area, shows the ports currently mapped to your host and if they are currently listening. + + ![](assets/vscode-ports.png) + +## Using Other Editors / Generic + +1. From the terminal, in the top-level directory of the datatracker project: + + On Linux / macOS: + + ```sh + cd docker + run + ``` + + On Windows: + ```sh + cd docker + docker-compose -f docker-compose.yml -f docker-compose.extend.yml up -d + docker-compose exec app /bin/sh /docker-init.sh + ``` + +2. Wait for the containers to initialize. Upon completion, you will be dropped into a shell from which you can start the datatracker and execute related commands as usual, for example + + ``` + ietf/manage.py runserver 0.0.0.0:8000 + ``` + + to start the datatracker. + + Once the datatracker has started, you should be able to open [http://localhost:8000](http://localhost:8000) in a browser and see the landing page. + + Note that unlike the VS Code setup, a debug SMTP server is launched automatically. Any email will be discarded and logged to the shell. + +### Exit Environment + +To exit the dev environment, simply enter command `exit` in the shell. + +The containers will automatically be shut down on Linux / macOS. + +On Windows, type the command (from the `docker/` directory) + +```sh +docker-compose down +``` + +to terminate the containers. + +### Clean / Rebuild / Fetch Latest DB Image + +To delete the active DB container, its volume and get the latest image / DB dump, simply run the following command: + +On Linux / macOS: + +```sh +cd docker +cleandb +``` + +On Windows: +```sh +cd docker +docker-compose down -v +docker-compose pull db +docker-compose build --no-cache db +``` + +### Accessing MariaDB Port + +The port is exposed but not mapped to `3306` to avoid potential conflicts with the host. To get the mapped port, run the command *(from the project `/docker` directory)*: +```sh +docker-compose port db 3306 +``` + +## Notes / Troubleshooting + +### Windows .ics files incorrectly linked + +When checking out the project on Windows, the `.ics` files are not correctly linked and will cause many tests to fail. To fix this issue, run the **Fix Windows Timezone File Linking** task in VS Code or run manually the script `docker/scripts/app-win32-timezone-fix.sh` + +The content of the source files will be copied into the target `.ics` files. Make sure not to add these modified files when committing code! + +### Missing assets in the data folder + +Because including all assets in the image would significantly increase the file size, they are not included by default. You can however fetch them by running the **Fetch assets via rsync** task in VS Code or run manually the script `docker/scripts/app-rsync-extras.sh` diff --git a/docker/_old/README.md b/docker/_old/README.md new file mode 100644 index 000000000..fe5c9fff4 --- /dev/null +++ b/docker/_old/README.md @@ -0,0 +1,56 @@ +# Datatracker Development in Docker + +## Getting started + +1. [Set up Docker](https://docs.docker.com/get-started/) on your preferred + platform. + +2. If you have a copy of the datatracker code checked out already, simply `cd` + to the top-level directory. + + If not, check out a datatracker branch as usual. We'll check out `trunk` + below, but you can use any branch: + + svn co https://svn.ietf.org/svn/tools/ietfdb/trunk + cd trunk + +3. **TEMPORARY:** Replace the contents of the `docker` directory with [Lars' + files](https://svn.ietf.org/svn/tools/ietfdb/personal/lars/7.39.1.dev0/docker/). + +4. **TEMPORARY:** Until [Lars' + changes](https://svn.ietf.org/svn/tools/ietfdb/personal/lars/7.39.1.dev0/docker/) + have been merged and a docker image is available for download, you will need + to build it locally: + + docker/build + + This will take a while, but only needs to be done once. + +5. Use the `docker/run` script to start the datatracker container. You will be + dropped into a shell from which you can start the datatracker and execute + related commands as usual, for example + + ietf/manage.py runserver 0.0.0.0:8000 + + to start the datatracker. + + You can also pass additional arguments to `docker/run`, in which case they + will be executed in the container (instead of a shell being started.) + + If you do not already have a copy of the IETF database available in the + `data` directory, one will be downloaded and imported the first time you run + `docker/run`. This will take some time. + + Once the datatracker has started, you should be able to open + [http://localhost:8000](http://localhost:8000) in a browser and see the + landing page. + +## Troubleshooting + +- If the database fails to start, the cause is usually an incompatibility + between the database that last touched the files in `data/mysql` and the + database running inside the docker container. + + The solution is to blow away your existing database (`rm -rf data/mysql`). A + fresh copy will be retrieved and imported next time you do `docker/run`, which + should resolve this issue. \ No newline at end of file diff --git a/docker/_old/run b/docker/_old/run new file mode 100644 index 000000000..79e7510cd --- /dev/null +++ b/docker/_old/run @@ -0,0 +1,110 @@ +#!/bin/bash + +version=0.20 +program=${0##*/} +progdir=${0%/*} +if [ "$progdir" = "$program" ]; then progdir="."; fi +if [ "$progdir" = "." ]; then progdir="$PWD"; fi +parent=$(dirname "$progdir") +if [ "$parent" = "." ]; then parent="$PWD"; fi +if [[ $(uname) =~ CYGWIN.* ]]; then parent=$(echo "$parent" | sed -e 's/^\/cygdrive\/\(.\)/\1:/'); fi + + +function usage() { + cat < + Lars Eggert, + +COPYRIGHT + Copyright (c) 2016 IETF Trust and the persons identified as authors of + the code. All rights reserved. Redistribution and use in source and + binary forms, with or without modification, is permitted pursuant to, + and subject to the license terms contained in, the Revised BSD + License set forth in Section 4.c of the IETF Trust’s Legal Provisions + Relating to IETF Documents(https://trustee.ietf.org/license-info). +EOF +} + + +function die() { + echo -e "\n$program: error: $*" >&2 + exit 1 +} + + +function version() { + echo -e "$program $version" +} + + +trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR + +# Default values +MYSQLDIR=$parent/data/mysql +PORT=8000 +REPO="ietf/datatracker-environment" +CACHED=':cached' + +# Option parsing +shortopts=cChp:V +args=$(getopt -o$shortopts $*) +if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi +set -- $args + +while true ; do + case "$1" in + -c) CACHED=':cached';; # Use cached disk access to reduce system load + -C) CACHED=':consistent';; # Use fully synchronized disk access + -h) usage; exit;; # Show this help, then exit + -p) PORT=$2; shift;; # Bind the container's port 8000 to external port PORT + -V) version; exit;; # Show program version, then exit + --) shift; break;; + *) die "Internal error, inconsistent option specification: '$1'";; + esac + shift +done + +if [ -z "$TAG" ]; then + TAG=$(basename "$(svn info "$parent" | grep ^URL | awk '{print $2}' | tr -d '\r')") +fi + +if [[ $(uname) =~ CYGWIN.* ]]; then + echo "Running under Cygwin, replacing symlinks with file copies" + ICSFILES=$(/usr/bin/find "$parent/vzic/zoneinfo/" -name '*.ics' -print) + for ICSFILE in $ICSFILES; do + LINK=$(head -n1 "$ICSFILE" | sed -e '/link .*/!d' -e 's/link \(.*\)/\1/') + if [ "$LINK" ]; then + WDIR=$(dirname "$ICSFILE") + echo "Replacing $(basename "$ICSFILE") with $LINK" + cp -f "$WDIR/$LINK" "$ICSFILE" + fi + done +fi + +echo "Starting a docker container for '$REPO:$TAG'." +mkdir -p "$MYSQLDIR" +docker run -ti -p "$PORT":8000 -p 33306:3306 \ + -v "$parent:/root/src$CACHED" \ + -v "$MYSQLDIR:/var/lib/mysql:delegated" \ + "$REPO:$TAG" "$@" \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/docker/app.Dockerfile similarity index 57% rename from .devcontainer/Dockerfile rename to docker/app.Dockerfile index f761d9475..162fbf671 100644 --- a/.devcontainer/Dockerfile +++ b/docker/app.Dockerfile @@ -3,71 +3,58 @@ # [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.10, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.10-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster ARG VARIANT="3.10-bullseye" FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} +LABEL maintainer="IETF Tools Team " + +# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 +ARG NODE_VERSION="none" +RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi EXPOSE 8000 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update + +# apt-get upgrade is normally not a good idea, but this is a dev container RUN apt-get -qy upgrade # Install the packages we need RUN apt-get install -qy \ - bash \ + apache2-utils \ + apt-file \ + apt-utils \ + bash \ build-essential \ - bzip2 \ - ca-certificates \ - colordiff \ + curl \ + enscript \ + fish \ gawk \ gcc \ - python3-ipython \ + git \ + gnupg \ + graphviz \ jq \ less \ - libbz2-dev \ - libdb5.3-dev \ - libexpat1-dev \ - libffi-dev \ - libgdbm-dev \ - libjpeg62-turbo-dev \ - liblzma-dev \ - libmagic1 \ - libmariadb-dev-compat \ + libmagic-dev \ libmariadb-dev \ - libncurses5-dev \ - libncursesw5-dev \ - libreadline-dev \ - libsqlite3-dev \ - libssl-dev \ - libsvn1 \ - libxml2-dev \ - libxslt-dev \ - libyang1 \ - libz-dev \ - libffi-dev \ locales \ - make \ - man \ mariadb-client \ - netcat \ - openssh-client \ - patch \ - procps \ + netcat \ + nano \ + pigz \ pv \ + python3-ipython \ + ripgrep \ rsync \ rsyslog \ subversion \ - sudo \ - uuid-dev \ - vim \ + unzip \ wget \ - xz-utils\ - zile \ - zlib1g-dev + yang-tools && \ + zsh # Install chromedriver -RUN apt-get update && \ - apt-get install -y gnupg wget curl unzip --no-install-recommends && \ - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ +RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list && \ apt-get update -y && \ apt-get install -y google-chrome-stable && \ @@ -81,37 +68,37 @@ RUN apt-get update && \ # Get rid of installation files we don't need in the image, to reduce size RUN apt-get clean && rm -rf /var/lib/apt/lists/* -# Enable some common locales -RUN sed -i -e 's/^. en_US/en_US/' -e 's/^. en_GB/en_GB/' -e 's/^. en_IE/en_IE/' /etc/locale.gen && \ - locale-gen +# Set locale to en_US.UTF-8 +RUN echo "LC_ALL=en_US.UTF-8" >> /etc/environment && \ + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \ + echo "LANG=en_US.UTF-8" > /etc/locale.conf && \ + dpkg-reconfigure locales && \ + locale-gen en_US.UTF-8 && \ + update-locale LC_ALL en_US.UTF-8 +ENV LC_ALL en_US.UTF-8 -# Remove an rsyslog module that we don't need, which also requires extra permissions -RUN sed -i -e '/load="imklog"/d' /etc/rsyslog.conf +# Install bower +RUN npm install -g bower -# Set up root password -RUN echo "root:root" | chpasswd - -# idnits and dependencies -ADD https://tools.ietf.org/tools/idnits/idnits /usr/local/bin/ +# Install idnits +ADD https://raw.githubusercontent.com/ietf-tools/idnits-mirror/main/idnits /usr/local/bin/ RUN chmod +rx /usr/local/bin/idnits -# Directory for Mac certs -RUN mkdir /etc/certificates - -# Setup workspace -ENV HOSTNAME="datatracker" - -ENV DDIR="/usr/local/share/datatracker" -RUN mkdir -p $DDIR -WORKDIR $DDIR - +# Install current datatracker python dependencies COPY requirements.txt /tmp/pip-tmp/ RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ && rm -rf /tmp/pip-tmp -COPY .devcontainer/init.sh /docker-init.sh +# Turn off rsyslog kernel logging (doesn't work in Docker) +RUN sed -i '/imklog/s/^/#/' /etc/rsyslog.conf + +# Colorize the bash shell +RUN sed -i 's/#force_color_prompt=/force_color_prompt=/' /root/.bashrc + +# Copy the startup file +COPY docker/scripts/app-init.sh /docker-init.sh RUN sed -i 's/\r$//' /docker-init.sh && \ chmod +x /docker-init.sh -# ENTRYPOINT ["/usr/local/share/datatracker/.devcontainer/init.sh"] -CMD ["sleep", "infinity"] +WORKDIR /root/src +# ENTRYPOINT [ "/docker-init.sh" ] diff --git a/docker/assets/vscode-debug-breakpoint.png b/docker/assets/vscode-debug-breakpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..a2446650ed6a11832f8c69006e82d1f7fdf0ccdc GIT binary patch literal 6002 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 Z`=S{6ZU^Dj&;HUu`a1Wt%QYQe{12T=31$EQ literal 0 HcmV?d00001 diff --git a/docker/assets/vscode-debug-toolbar.png b/docker/assets/vscode-debug-toolbar.png new file mode 100644 index 0000000000000000000000000000000000000000..044570ccf78cacc4480e2d8abe8e648deb5af717 GIT binary patch literal 6185 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 Jl_BlI{s&e}$o2pL literal 0 HcmV?d00001 diff --git a/docker/assets/vscode-ports.png b/docker/assets/vscode-ports.png new file mode 100644 index 0000000000000000000000000000000000000000..9cd346c829a01cccf91974def57f036875c0acac GIT binary patch literal 27172 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 literal 0 HcmV?d00001 diff --git a/docker/assets/vscode-sqltools.png b/docker/assets/vscode-sqltools.png new file mode 100644 index 0000000000000000000000000000000000000000..7f4523864763eaccadf2e95d9b6484578045218e GIT binary patch literal 70699 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�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 literal 0 HcmV?d00001 diff --git a/docker/assets/vscode-tasks.png b/docker/assets/vscode-tasks.png new file mode 100644 index 0000000000000000000000000000000000000000..927bbda11736becc93ba9eb76aff9b1045a43523 GIT binary patch literal 26733 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�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 literal 0 HcmV?d00001 diff --git a/docker/assets/vscode-terminal-new.png b/docker/assets/vscode-terminal-new.png new file mode 100644 index 0000000000000000000000000000000000000000..91044109cb34f056659ec239217c1f3580e9a3e1 GIT binary patch literal 23253 zcmcG$1yogEyFR+4K}tZR1q4L8J0zuBK)SoTQ{YE!1O%j8M5Lu#z%30@A|bHpZlv$@ z_kHI(=iKj{d&eDj{27}ySZl_f`OfEk-e(c5rt$&@iwp~bARKu)X$=Uv_Xhm(VIYAg zo$oYlAPA+wR!i4IS6NBO+}V-M)WX@!lFi4_1*Aieh`5i7skyzS2ep}{wXKsV?S4xK zEw!zMD6I~!GKaE@l%(!-S6$I-#bUC2k2 z_V0Ryz~6r!v(r-loyEgmlvY<+jatgt&61jzjhBssRt$?;#LdD=NJCoopM}AlD6Nf$ zhl>z9ySKMDn>RO`vzs+Lr=Xx9I|mm#7Z)qY!Rqeog4|9PZj^DL)y~a+|Aa- z!`9h}`cIvvX3m}-qO`Oio%)}ZTl(1kXYEez|Li^(2=+fI?3`>I?Ef{phppBBlKoH0 zzh!r^arSU_w{dp)R|o#vSNtpa-wJ}^`=5*Wn7aH=nU$6QpR+qU{s$xkeaQJrGu`tt)r!rI~ZM2S{@FL z|6A&-|B}kh`Cn3{oE@CqG{Lg66s6_-yU?Gp6Owl{wYJo;weYa{&)WVoLCMm|`cKM# z)bw}CpVm2e{+ZsFPPU*wT>n{{?ti9<(hBl{h4p9B|1S0Fe@yz2cX z@Zr$n;1J^E5#r@#<=_?i=V<+%8|()QQxDVsxBP!rHMIyRp{y(0koadP~#fB!1vZDR>4{NKCB{?Ep-|Jiu|(K-?Ke`~+U z-x>bPP6g%u@eEi1U`p8kWlO-#zpRm^6EHz;z}6HVU|j=y7G?`(=HF%nf*2D$6FU?o z)rsKZw(2&fYEn|+uX&{-N#$5^6ke&}SdCW7_?f1q*-ssw%9-L+Tey2 zU=*<0u-QHH%`OQe@MT-i8M#^T$34%vpX#F5w-HbE&B9%eal@O9g-tNixZ1ohF{t%{ zjE?mh!|&`9DXPMJx!FUeoV$pt4@43|{sA4X&5-p8|X zlUVZCOh~;LTCqqER+{>f59$7l$nGP9O;sg*=lXKwW{`f;tkINkku>Gw6{KR8;KMIO z6ZYGct5@J&05&I6EgruSnx#y3faOf@so)XU5HZ1h-3!#D8|zET zcOn_!)WCF+d*u#6xIKS<@1-!~l0y(RBrh$Y<&(8D@9jf0ozK6>?dU)K(HryB=s5=F zSl7vdL1*Jr7@_bkLz8iq+c@Dm1OFt9obT&b4-ON*hZvao3;y%8j+M3J?c&7DubFzn zbX^ysqO5s^-PhuZZZ-$gx!vEaoCH7;_$zoW)w(8gr)!}PhjH1*;yRlR$V3kAH&|Mws*2EO9!04i5;;lQHK&ak|wP&gugBQS7I zji?Lr+UN;rLbS!Q$RdPBj3SDS;+nSi$kk?WqG0F4Y$fO}-}`Tf;|ud2TVsDW1?|L% z^@(S|T9Re$`2OeqY`>ZP#hhW<$F79ya@5~CXv}enUJ!pJjJ;@ZAfiReSMoVmMCT6& z{T&T|jv}LKRJRuW%r%L8;rZ*DqRnIe3dZK{i~U{DF6s^9-w#M51e1}z-Ug^nb^FpK z3fkuyh;xVX*AR96_1pG7|KJebivP~J5hFGWMwk-;=V_g@!_3iKt?EeM8WqmG1H}=P~xT1W7-X#Xu$Lo)d_n>~g(_XHI%{nO{J>{Xw6bL^V!>epD(8lLqwB{Pk}VSMvoqSx7Bux>Kvx5fF4*nqCW>nHOx z8>X5)bWc&{1o)V!Y2Q4*=<;n!b~ec7`t0HHGn=1f_1P1w<0nzu{r2c{Pwqd6!;l{s zc$=Zfthck$mf-XvIf)C_#enlWxN+ACvXNtuFF14yK%8_x)h$ za$|1m&B*oN3W>#+8?YN|VP*4vaj;ZR4rG*GRk7&=c1xmkUkD_%ds+6!m+6=NTJUl= zsm2XoNanTfGh13hPP?j@U-_iOnx0v{^>Kr4vsz1ujNkF5-^}$_u_|89HXkyy8rO*B%*UDP#1z=yq=S|#{{uQ2u|OVq%T!#Qjc>TJm&*Sju|hjzNCuP^7IFJ!q3=$ z4)QyUG!M-i3I(lASQOQ@jqkO4-fIXukY3W%>8PfeHS%`5g3U*f&to=S`1aA%cd^As zP;^tyaQxY*2Z1G5I)gu*(ij<@YR?5+E^hKovo=u5n9S%2H~;*|+&tJ2kXDC%J~=&A zmswsItc^pP^iu$n$Knw&31fgyBLDZ9-TpZP5hW+Q{b8>WqSqzwWv^LN#8 z54;8UO;;wK;Qno=h-CalCT<3ex?QuP3ifS>*{-_5<}{9IDS{X|qSpAOQ!cq8uK zB9H5W0!z4PD!?9Unh$|Lk@Yo`^J6TV9Ol4YY}8k6+H$4}?PfhS<--22WVIEF>+aQ1DosWgm#-sCgjV z^=NDY;&(?%yqP1B=z1X+I2&smd!k_`JKT=X1xkm~dGoKTT3MNJ>p$heDdEa*xZ|QJ zbQc=U1YwB1i%=4Lp2Vu1I`lV}{&vbMotGb7dzC*Vy5sYpQ4F~5=&DLRrXl3762LXM z&rG5-ihv;+gYTBk*716Ja99?H$`aG?PjoX$azjC#(>|Gc_$MSSUd>B)xvw!F>jvEs zhEYF$$Cw)qZtzi*DF_1=H%`Gwn|nXua=m>nk&w?RvbdCZN`jgSmvTFILolK!V+VvD z>@iJy-faVk@FxU>guS$fDgFH? zpC_uSIQHFO2ob6Tl@fbL`;reWs_>-T+y>KmGO7e)L(St`bp3tLqm=b}2VyML;5+!N z(0uS~2RAnjH4_uV!0?r>9?V$LUd0 z6Gt1c=@=SzwZC(WWS9vl*|sCC`doXq8O=8vo49KQP>{pr9b&eH$iQxGGTP z(MQlE8FaGYngDkf@0A?2>Fo3?8cOGmwR$(Oy1KwOR%Plld!~AIh0cMUEZ1{CSC_+o zN-09}HaPgIW!7`HX`KkGSg*WY?&9eUu%KU%uJ%&-i0{SQlO8yxuQjb-;3>C_G(#mYkJ=K0{^usN!g^=t|LmK9KBgJ zhKzc~`ys1=Ayy*K5Fx>5n-itnPjDDv2)QJWCIbj+nZI3{N{FBxdwbpb?BZg5*cgK3 ziZz_mSq6UYdbP~c5XW|Zk^CKyqehL5iCO>C0XIr2Uk&4T0E&!mYTe8ZZWJLwbezEh3RSU7PhA_1e*cl&_Evy2BYmi`0L;= zPkS91Sy^==di(=@eSPt(038E|xtLW&UlAicy{+xa4zJ(e(){K}lgXzCEVy6@Is*Au zz84jS{z?qvitKIF$$hs6Q;%`boll(Rvb`7TW_I<;*`BcOUSE7C-@=m+Lq{Iq|130*t}p(@l>$-|sLQKz*;-;x;A{AN z{rm3bFGQo`tXQ2ct3t8H-OG|Xz4DJ`Wx@M5WefXnz3pQiVqHM{nf;1oYTp0sJ5P2-Mve7;``%to ze!eM+%x67AZEdtj)APfd@I3X<&{cA$hL)BVbO@i6G(9=nP+uqb(2R7T1|^|W&BMm0 zv7`iD0v`%dC`N%uu-_w|s@m4+LC;^l^mKBnkfUqPSE>{0TyhaG92VY51JIKZ36fJ% z$|8Ck3}#?;RYw4}y|crVrH4;Wh>V{%X)6e;o!!mOHl$dDQ3&?CWt~f_QWLGLu6;m8 zl68;cQQr3OYnfNk{A{I$5H&)P;L&q*QsG-(CtQ#Sx`&p^jv4V~XhcL=JqH0-(Pbfq zI;+j$)1UNC$NBGCs!K0AL)nE|np^ENhEfx!QsnVI<&gwPij`}OMA zCGShxeqEfALoU2^p50R2w23Zb1rbm7mq{W`r-SIFC6{c-lo?}=E&_hEhEd@HqY-Lm z{ao^3O)x=fFd>0cJmyv~=v;pRzlkhtQdHKCYHnlxqCOP;R^jIEb4z6YX zN>QNWwtB0?o};Z}tfMpi<{d|LflZ>EPwCDPWu$a393Fv!zCYU$yj~#+h0w=7S~5Nr zRi{c&V#3iXJM|L{qu$)yL{XWm!O!Z%q#C)(p#H0~^Lf&1yce&j&_J^u5R)}q97;yM zcSSO;c6bJb6l}&mVi)bOjGZ@~-t-8yt5aj7pqLQI_TEZvHd1uAm-X{gGf@k^3-OMY zW=R*de?PE_g@=cSiK&f_GBGvfcw>_}WL4&D^Qp9)IZKZ^MWLm+nG-uUChp^>k3vD$ zJ*So#L&V>uR9G3o%yOmk2tKnd%Gc5P^(H&}bmi-5yz)?2S7`Dw!gh_AfBD^zRjG8d z$!%-vTo&O|)!E&%s!{xGqminE9(=z=6O#)lrT|s*{Rb^3if*f6#zQtbc~x)khDj?$ zRmGwHL6??3sTVMci=z)}j8(I{xbP11SUUN#A=xqh1ylD^yUFEV)t;|kCnl#giGT_J z9bn`-#sfjh<9g+L#{TDNItGWhe$?_u^XCiR0y`HMzK4g0JTj-}=jR^h5JVDL4Qx$X zEV6;2;mxq2f6hB`=e0P3>>!)FQ1(L9Z&WGin6~~Rf&xq=9T6@$woBYqp#yDQ6;*G?>?lU6B~GMp zyvJi>hGa}JT{ORUi_d6KB!Z9uI{c3-f)k4+c-QJR^#*f-dWoGlth{AbqoB8_Lk7sq$EQ~X9j_z~T}O^)7Q7r*H0w~VFwxu>=wAxg8$x#ba+2cJ4j zwjQ$D_L=^I{s+SLc;9}Z-*0=3FigBc{o|{%%Z$HgGp<)F)q-%b$>V0dcRrTcqd={{ z=eRjJ)zjEg9zA-5_7QoIczeC&EKNttjp7kGVcX`W=aOkYW6aqpUh7RIUR^WjODao- zxV3h)G?OW5eXxnk>=`hM^ZYxwGGjv{4)3zkx)Bd#3onl6uPU{)|H*TAZd-xZo_M=@nW^J+>S7G7Sm&c+?%t4vH;%Ps-~{me47V*~7BnK>B-uU=~E{Q98wO);iq z>!drJZ1)E)N6POyB?P5fj^woX zoL$RAnr5l27d&12_*NlLOQC1Ezl=93f#RvW1~tAKQA&DFMoPL@)AH6-g81<;jaty^ z*0j+=QgVuG#mV2pCjkce)*JXlEn9QYTu~J-aLrfEC)3!7+)hyg%kKt{wV# zG}E-qn>GkLc=`LvSOx|n-sS$r&GwA zAf?g<0(W{g?-yIzYqMsG+WVO<- z)DN!y^yO(31ojL=d)AIp=Fq}4|LD|$pru<*(6`a?*(h^eFRw@gHevsY3A@@~PP2a< z9Q=64cr(f&qt4T~Jv2woe{Ygi0bQC#HYvyW%v1sj{NHQL9V4Gz&n?Iu%oI zjhL)&c0*4_3(Yr|QD5?UzJTS-1ut?yb6-&188c+nU(<;iQ;2B?75C3BHq%E)*87YF z5J}i%ph1GZmj=p?ZIgDh)$YHxQWSM64Yu+bv1Q8nX7}3A$;mS52@b#2XB&#P#)4WG+}XRByiC&WS!{&V$*DJfEq>G*e@Xc-!ibmRTf172Zcg_>ewLQGB7@ zeLW|99IGS%k+LpA^|7HrTttLNt^8;8Ri}0CzF}R!*d;GB8n0e*FBuh?hNk}Axwn|l z*(T2M`fw469`}c1HLWj20wv=YTJS898@uq_*$Lo_g^Cs$=pM? ziS!aOTrl#g)_raIu6yYuC>qhI%R(!k^q#a@?k_VED8y1XZFcqIW3D12(b0tniUb5# z=h^jW)=iaB*P?w;i*4^M0BHD_7->l)_`NWnt0n`s2Jc7akiKp^9RMp8IakNVzwSYF zJ@A{3$E}>!+VU@zMOP2AgxqftyTbC{lQXjq=lP9>hK3t`N=3Luhc?}ARvvZmrw(aGOjj<77jbsblGz7PgAP%)zjX!%$))d$#1NOq)s%}PBwmF$jKFHH{-;dwJe2mAj z+Mp#9ZdNy6qnkDW&S@vzZ#ADzn@?Y**3D9$YhG*vSB5@wK4@h_et)|jHvBbpDr+z< z@A+wOO-!hSqm|!BIXd7$p;0`27%M|-`m6J~ox<{QX0C{_-qg%Iw*!aIK53nvW65w9 zI@qc?3+?y5BN7!Y5xyq)CpICWtBQ2;ULIZv0h?}3oY;s%UzrF^Z5Bfkq9O+Q@2d=` zNTKIU`(52|2fnLMq%uu{>5jYESGW`v<<2O7s!QB%$L^+vn%a$_Fe-hp;^jNnpE7*q z=dJVWz{bRNYckY`F8bi2V3K!PE`DRKR)~Xxb30YW?x!!h( z(J6($imHiJlV)QKLWf-@Nz)n$IM*vNq$toIuMNs6%kS)xbEFTtrB7JZdY_*qQmHCw z6)BXWKo}8WujO6cng*4V933gc!^zSOgce=^mYnCumm~U;0m{dZj%SUp-@V_=d+r&0 zx43WJoPNPVlgz9chPuD{l$8axqWc|29#LKQV0rbq) zMK|2}0E70KZIaM)UXBm(vC&^K=cN3Enp=d0n(sjX)!9CiH%t8My=}a9rB?r|RC^l- zTpS!+y!-SnS*9d6Rr&4t(R8AH(aDmMVN7LqpR|P`Y5_(LZc)!~CLbzFgY%*wWfQcv zul_0c5^5;WK}ZhzeaoKWop-PHA_WDX7@XiM7-zB8ZlzwIV@-I@b@sk82F)boi|NDE<7l=u6l& z>akTvhv!uz6&8x<_dn1a?g}F1aMc?syq2sNpv0U`+uc|{~42&aWjw-6g_S;bK@pZSRd#Wttx%MSm zbKQWAA9yMsBHt62jH5y>O>?*z?(i;G7Pu?LKs8GjLeZj123fQn+Ycwklre@DBL;%- zEn4k)WUKJ*hf#Oj11ItS$!ln7IKz&CPu96OteYbX{wU7d^Xt7ZY5+V-9;$S4IQaZH zIADIm@yrQyN~L7nu2%fI?do;N2>4M^ROTZaa%#9T;!l(7k%>SJ-Ga(hMqKB@KP=fa zQh1@rJYZjht5QUac$^oHzF7n|i;Ry1k3z_fD?RY#PSNiluef8v!;xGmkfC?1Q)oQsOXX~D1^$hoPH+i;>qdDK9#l_BbKJjRmMV*ejdM>SNqh;}Xa!ZI`{yUL!Z5-aY8CQDn z@ztG_`h@5H5c9Y7Km2G9t-9+HQJv7DYH;AyN~!yKvmo5H2rlKfm!u6~Y3^h4hqg7k zP7PsjDazZU-=*A-fZ~VB8BCU{v%&H8TD)xG=J!?Rb3M-7-z(#W3y&&W8wEvJJnllD z=zO#bXnzDlWU-}<#72BYLz_Y-`hW{gjkj`i7-0h0!(cxpomf~F)v$QCe;#a62~kK- zOSa@l*VCJQ(%lX4t}Bu?sdm}8ad}0rs{vEWDADB9l&kv%iUb|~*B7s&9taHAd{PlN zFw{@W&D`BBReSbOsvE7gm+T?w!o=LiaXfkkB`jR622U^g9ymZ3k*0u7$@q!p8S=4; z+L$SM8KvE0ETFK@z_;$Ja#DjZ8=!U93`*tb{8l5B>3bt4>rUCygrCufF)$=i`|v2^ zVcTtOWy(&iA7Av2W39N6E(#>iX#5&=sGBLE?dJZjq5t#etZ;K{*+W%kYI)T_^W=fm z)PW+~(msU<3JLYtUIq2H?)HmJYKc*+Aq!SYp#4R<#5t|!3dmB4w5PqishMQKwOL$) zh28Du&Lv9JJE~-3gCA3%UDj4#(dAH0i$Op}ko69qJ@K!5i!8+Yj)vjAcI2n*1K|;Q z8+Fgz)rjsvp@F)iLwurbZ0t|RE$SBqsETkI+q7JPt!=8cmVO~~a*F41esT{2o@49v z^?T$f7%fK4MX9G-`k)10nU+GN>B5!ERq=pMMuz^ed#zF6MbrEh?n~`Sj={QP%FqyT zaBRgC$4b-Y8;P^vA4NrC<0ua?r?O(*$CGbMjVj`x05l{3|f{x+}Z%KePau zGY;A6B6U^N9SyZJynI{>@eYKUcTXREZ#xmC)<*N}zT zxGq55LrdC4?Tuc!pVPQ(x{@8oJ0dL7ZjQ%6t%$h@#RcB`_n$^ZMK&6+6-(0KADmN) z)SP!FPP{GBG4^%ZuBUtwTIY4j6+82DeD=lo;J9isIsYD0V|@Qt@f(p_G%q_032$UfM?NbGwZv% zUEOue-Mih}Hm=qEB!08{m?V;NXqBUOhKq-Xg5(1%AvT@gI#P}CI@kEl)kTf`5&6xK zj7&);#2B-A{j>t%JRNj`OQhI4(KjTg`0uHtn$ZS<4NdhG=8ybu&hSa%wqyD#=! zed2RzGG>@d)3=UWglJ*k=grMick8qhJnZ%h@eYK5)9y!0?wI?>ZZ&px+m-B(WfGy3 zqwWNtw5aEy6**ab#6OfJw!5-N>x2E}!R>b;}D)Ynzir zflufgk2)@X^?%e04M{*Ws)*AOVbKw|N}1QrnDq_I5yr}FmI8pf4Azj{HW_=0;RRe+ z-xZq>GXl3{V95g&4Gn^_RHosx-tD(-k9DRetgVV}mrKO6#I4_JG4&1g(P3PNCwSX< z`en{L)&2ZroE@?eg+o?;n>t+tsFlRRr$fYLLspd^K2?<4V`HeHqJNxs;)lCogNP7r z+5m6H{R5K7=pI_ws-#pH?UOISFgx-Ahm(qoifUpbEF4KH4Cx-k(rr}nVP|8ferCt- z=HTM{fLS6VBgY~x{kny^oO6@bOYV0HLD zGMsO-9ya_uvm1yUZfF>YlAy+95qJ}R7vOCle3z%j_#D5-hA;MY*hf-*0s519wB_`LVIYUEH{++Z{ftDc&?uK@a zHMbV>%-i|q>RCz@i33z~(jsEYhxuyXJcZiES7}{Dn7MbS`|g}q3=8{u5DzF888fIT zCSWWL@5&h?ABZeaBFV9({B-aNA6vOeLO$mRk!K{J#^AEn?i)-hu+MaVUN&hCF!6y} z&h}LbNygsx;}fG>ZZc);tNr)%=mH_s0aSO9N3T-B=wS~)(2iGBpTjaBze_8B7E1fETMMX$?Iy2lx9Q%?jt=zbFIr57r)s~x#rCQ$Q zg>|k%7SRX?OYX>hT-;V)7kqR9m&^o#P()Xk#M!XZei~N9oK%uZ$+1y_79)`od&Wnt zZ>l*${5(8^RZ5=9-Ajc}WwrBctxVJiA3hAt|Ipxxct}FhS@UUD`N#*QkqwR+1}G_F z69CF7;OoZ`U+kS}Fv1WdP@w`8X{DPg>Rxf;);nn*E3oL%6d4)SR{6MRLm3CF=00g;PshqbD_bY+u!4w|(B^p|rViAG7oZP74{Rgo! z18Hmq0>LUeIwM_DFL2P3hpZB!VH2B?0D`pMfrGZKr zJny){*|+4ay%7Iuap=>NBy(KyNErtg7YiGM+Q-LSb36C;vcAuudS>_Oh{2C4tKQt( zgIL%w8*WI|o6*Sk@9%Cp8ty?nLv(aKH+wqHxHzQCW(Ag9ee3?XJawP@EsyH!hx>d5 zJ1%GNc5z>LcoYrz?t1KuCYl4@LDkVf*m27u>7?hYtUCofz5;I>;EoI5nQ^Qm^PsEo z(0e!%i=m;R=y-v?2cy;gm+1?H8Ky!)El<}i?+*Nbk&W7X36nxXdW-ORGK_+@Pk(X` zMdFL36bH7wqw}wJ^U8+gKMPbSn`da0Xa2{W->O}F_tK|Q`_b*Fdk}8aeR%a&M)Sv? zXfXv8DkZXI)}+MLolf3wQ&a3eUxrEy0jTD2NmDko=OH9YH8NVYWcI2T{c*66hy%bl zyOf4rE#X!qFa$P(`|4!IaD`EdM(N~crru8xDlCYaIF^H`%-)7e|I@2;w_x-CY#SjN>)bYmQcyoS!XlPezJq)mK_WDl;xG3O)^LsHdOxWE;1buzn>y$A4 ztTrYhx1YD5CK`Jz9cy^zM%6AtI z>ABM5@;5(jH8)2xI2)6|-2l|(^^9joZfdURGWGsu@x8r06o7ZvIF5#a=pavanuB#y z962|?Tc7Eru0?@VgaB++H+2zI)a#>TlO^A?tgKp|ot1lh#NWP7+WX`DMU)c5O1QyCJwG!ayY!>*?oIN-ZD`Fv%00V> zFhqBEWb@_w+I9B&I&YYFTizi$(45*VhX(>(kpv$3A6@1(+W*h1pEL~y!9!9iG6Io> zhrX{nU(h9#6utg!e0}nQ)VA*tTk1%*;nDcrt&xk%VoDh=!jQdl{W$2ZESJTAqol0G z8XNCINk!rJE_?8&Hv{%tWK`0pRD>v@cLyz%j~=R2I6KtO?4E1B?Y3I#tcyx>Vd<`6 z8Q{A8jVFdTV6COl8?zb<{Oj(}890206=T1FhJc))+UK;N-rY)> zz4F7>-ew`GEL(C0>(p49OZ(@Y0NeC)PhH(__LU;4V-tA6*8}9*EiToqB@K@y-T=Op zyF^vk_0mAco4uPuwC#pR=4#6YTNZJ5eVNeCghNISLx7&u2R0v<;*plN?{U2?%R#NM6_oYoo zUrVcdT%<5%yf+TmOMlcLazc_& zaGddp$&Ln-?YX$WyI_yw;RLsDcV5I=DioUyaFZiVZb_8ao46VIzpw^8a$Hiuxb;X$ z2}4vwgl_qns@Kj}HHV>o`YkAB%;I*Xc77ppVI=4}5Jh4k==@1&$lVRU(eB=E?av*} zk`@3V9GY~sO?fgdFVPcnMKoQDw7x_RT(zK}xbR>~x0t{&bZZ%xX=H_gvFDEAX-TdJb$& z1Fa8Q^UD|KRY8Vo?0c) zE>fR&CPYUUkTzEahajjqMG}Ax z4@6YoKU4u&h6pnPP~JsRepz?7;?zJEG{0q8YekeR5_sF0UxA|7yP-d?Az zM_<++D&~Cnqf2n1Sf{L9T+NoI0vfIWPG3wU7Yg@eI+^i+dyk>TGoK3WXvo3P{5e+20tqAuRe=*zQ$8NH4iP(IEn$mEVf8fTuQN^&7+j< zUs!6-_Sf_F>=v>}1z>l;JuCb0=?llsy7TQLiqu_wfaH6>%YbN=h{wure?XM%Z^Z#& zJP;xgU+!>kw>10D{uDNJ@|O0|wUYe^Y@dxM&}%S;0V-}dL%nDm59pmzh*T%-JmZJT ze>l=c=aa^~mkbN5;U1Sy+S%JBx1FCGlu`$gUqA_Jv*`D5#C31dVMwwNczSqgnv4c(j%s%YpD8Ibgxf zs@eR^*b=A>ocJS6+uD$Yy>@pWkM{IPk719G&)!W$PBO+|p@sqMJ>@9;Q@A;aVA=Uq zMvzbA$7ZLC?-9QOZ?=cZ9ruF{`Y4fN5skopg-5~I3|kjloCD^UJZK=@PxamlH@aox zqE%1OppYkU6-QsI?qqUp;cT|dp^C>`a>YsL&2TtY7&S=@rD)I=0AKJHwgfDJ<67rD zMkeCu9uF_vz3Y<`jWQ_Yn7%IoafNgaB2-qdW~i z#(onHz`+6l?=8^UW@wfum;dGo#xldaRdPgo1!2D;9Z~-(S8VT=M-v1EP^q$|9r}o% z++!K=6`@L=`Qn--$p&{-DtUb5M4uvO;a1w~P$x_QL8V%>$qMD#ndjQPKp>W^Fk}@w zzKVsVg$yY%aEH+X!#|*$p=9Mu!&DqLvQ8c+o4Tr{fSLeDh8pDwTqs}&*d4)KxiOEgW z!fn@K1rmxx1M2_RTL1lf{_*5sZT$sV7&Tz96yB>Q4-}Q}Qer%x*a~5XQA}?-Wt}ek zdVq4ca`}>OQ_$-uZp@~6dZ>`L`_XW&p=;fm-OJtZ4-0>FK0j?0q!$TmIPWx#?Y(?{ zjyjKxmYNU|5&6luRz&cb1oa|v2#9+h7pI-=h&wb0e^t{{%kw+t-bR?43%B?!n{7ZT zOk7;o0k$*U*q?NaXSnFa_ah^m8vM`O*;TTH;5DCA&j|4IGK_d8?dkx3{8-AQRI4Aj z?l*6i);h7Y&>ajqm{{r6sqrDOsE)7n8>XlDB;|8@R_-=QPhnDGSIEWbKA z92A0vHOaN{aLC2x&Sp~j$s$enI)1#{kVBCfw2IwNTFRjmc3lG@Dkvmn;E~Mhh#Y~y zistu0b9U|tKydh!OT=M%fgRvixug{vz6Th;nTnC_m?k)gQoyN}i2r+gXO9pId=oh2 z#$&P6h%T;#A5YA$d6@s4cxGD~jT8#GWOZ4vwP^wG1Rc`l@J`jE$9lL-ge`XJ!q42&rR_vW4D4<|mqU6C@*;m8~U=b>UT!OiGF(Qn;&?epFxgju4? z@TW~0nl8pLGUfO8jVHG%ChmPqrymas4_8Cs%wz=|kN5cr)5;OR8=TmlLi1x|iEV*5 zDka>e8UgzLFD#@Rm6)n$C?5?l(V4kAsYJ@raitHgD-JaKUqX<*4!e8Pob`y|TLpU6 z!A#x{lcprZgp|?LasZ+>edj71dtG2-C2Oam9Vtz_CQwo7y!fTqExgO8MIq)j5`-T$ zF0Vd;q&KJS~$L4O83gU~B`P2+T1TyOJvgfOZnz&Jf5IzNkKw%>Xhgv-K zU)m)g$i|kIE##hG(!l;i)Y8oerc1Xhpj|k*yWnlZ^UDPT#4jH<8GtST?{IwdN5H_t z9D@$OizL({__%mpqFj$VZTGll@-N?g#9qzh#xab%E2$}7aF%B%cFr@&n-9^OmI!XBwLEq(|X=9Xy$UQn29FYpHzS5zm;i z%<6Szk(gO|eV48UAL@LR!+XU+&+e*WVC_A!#IDL$_ZgtcpVP*2s>-CJHa0OiueewR zpDksdiveD=@%Ru8^q>N@Q6p7-ywvqc%FYIsO`{D+f8smBN3s$y%CrDMYqR``ja*z6pF)6)KFmDEFcmzd5@`D zjxI$G0$dd1ODrOphi<-0Zv(=jb{G8BO4SBg(j%!cV5Z1qjxK78bFb(Xim&JK#4vHO z0+wb*-Vx}3ppTnqH4rx8 zgi)g)h%Lm62~yExvi5crr*53_#j&MZCdgwD+m2E*R_)`TR$Vk?{+Dp zx=DfRvRubFE;gQ2`6VjSEl}8wWHF;cB6X&oD%xu$!e0A=F7Hg=fz?s2*Ures*Boqe zfcqFoWNWy_kKAg{f?ZEQ)CCn{F>XG%7*ZW(O!vARM1?}0Q~wS)4+SDspd~f+L0Onu zI34kB__+)Fb$bL)-z>ErG4{KfPf)TtRt-AI29C2rM1ao^mm4+?Z2H|C5c8RTpIZOs zO`h@fN>o$RE8`pi<>tPO=13s!KF71M;Of)wxP7JVw-udi?W8lAT7TAYd)&636KFT^ z9_Rj}!3z&~j(f2sRRVf<6_6wp*shg}-xZcNrBEN_c3gzpMra0IO&K@)`*oaOP6JP` z*80vA3Q=P6-Mml+5V+%ZK9>^L8n}jp$Lj_mZI{^wAT=Yi$ z;)f9RAF)4yVWaMvGBecKH@Qdo)83AQpH%amLgW3rpYk+S%JW0t#DB(Ns5seNi<#2_2%A=Z`6f#&iYy z!_et`SK*BUJ*n+8jOU-U?bVlvpb#xuD_sUIk%^YDE}M@PrR1-ENvSKdIxcJ%fr!pw zHD`)WnX(l(l-J-)&G{^p`Y&=X32p}|O~t!TYN*rHd*ejPEgf4*J#F^pVh=gLOX8xb z3+Z026$y|ZBD^no**Y{PXC}G**G@KNP%GPO=;`TQLBOrBkoL)wC(SMX-I7uO|HTwg zC1K;;e{gV7ctHhQ6sTygF0F5W0F8?0jcrAm6&3=nH7S{3#|vH|I-L=e@{*U5(vWjZ z9fHb@_Ptt4h*xYqn)hP&N zgH!W6LWt2mn&SE1~M>9WI;7O{l&8x88kSVV|Q3j`5S z{rSHD(#zZ8CtRfyS4eQqXx)IDdcdpiye%MYnLh;KC)RSx=>^oRfz|e7R9+YYh*Fyk z_5&LOP1Lw+vgqWUhusz>vJsyQ+8Kqo%mD2SxLTHhb`Zq?a;mqpXW&(d_N(Wzes&f< zAI40IY@3^k9YL-IZ6+XJeU&`(N#ogmM-Ih6bZvsQFFV_{- z)Yh$0KqH_Or6Wo&(u+a5Ab9AC7 z0MQ-#=5vy z7LMY9=oDbmn?1D%e8f{$FJZ-oL17%M8$#Uq9nTw$rzTzePSSn}{%fPipwTQGwZEG_ zC^J+o68+5N!Gk8l(hjdIaxza<5vJg<62YLO#JKt8t?gR?0S+J)?*oFEuGW!BfbW~N zLgWY?%EGCx1B%Jydl;GJ(IS2%8Xhn*gm<)U^GA#t!3o;FMqkCl4!Z#nB6wqAS-OF=gdBZL4+J(5u?*+h8H$S+Hux8b ze-Q8WE6r_98_G(=01R4~V@09TH49C7for+7y`9)O5_Xt>dX|tY2dwNVAF>4L zV;=*LPZDQYVeP;g{Fa=ruWDiZyO`BoNR&f#G!5wHmkO_tc^;m9%V@qt9I0;P0GXnm z;gFlz^JK38)rW=exHvnl$qnlT4I`}plYST=m>7*~c6(?UV)shB&uea^noC-#zNjf_ z)XQWnY-}Y?{BnYxHjnHY6%w-LLPCB|S9cy`{Z)YKnR3ToFg!re z*+x}bA`kU#`NGKb^xnO0XBm02j-@>KW{*Ny`6eS3Fs0tm*!-)$ooxwG1$hnzjnVh~ zW?-9|aR0r9-wh1}+SjQ4&ac)(ho^qo6VBrs(PU)6bFbN~)zaO$fdaO_M4*2^0)A^` zUlBao2ORrOPEHs}?QIIQ310@U%bjz0j2RE>|Kz=VWmR+7leeD_$wI|N1yLhoG}bg0 zb(~}M*Kx6M{5V-Z_ifaY@upFd&Z>m%D;9>{XQ~Nw-u`MkEiL04JjO?-Xzcl@md!;q z$mk!;Vl;OO_rc-mNcQ<*@Wg3AQ!F>I8m!6Tx3*lR%(vj@o83YVYm5QZCQFT*YX(=UFa^?}D&;A-U_4@()ILY$*T3z#*nF&5fSEcyTLrvYHWSCX? z&UU@S^EEROSUs*AH}e!$B5N*^K+4nqsB+@woT(43ZXT>f6+1BM4T)B`H5;6xgYm0c zKpLhyjw)GCNfe`|VvA;J36N}W{Aiq?B#qI1uJi2iyL_T!6%TpD(kCsiLZv9{OLp9L zaqo0*WM?^uxpNjOqvNom#(#1#LT|Xg`xOO{PNSRvGAI?kqujG=nYju%DZp%n?)61vd3?R13;k z2LEL*#!g7U)nESCC3o6zKCQ{&%I}Dc^H60V1zvlToa%Hlx~+ql*HF3K@?EC>?hek!xcqQ;@@x%TW!+|WHiHZfc2__} z8RmO>J$@EPuSO&Jni&LK-P?ObQJ;*o${CDBtjiwtVu`*&@=~pNpN_-M4|jh=|5T|L zbLxp!5MQ%yo9&@El7>w7cCcKgy!2Vi?4GoH#!ASiq=6Wneygzks`jsV8MdmCq`a~W z`G{wKwmZnrh}Iz+gpm;&MBm_JVMN~p{>e#M4g3$`z$RbMo!rK z$B#Gr{da`-sj1xB4&jA0m6gk>2#<)G3*oX-bMqF)DyedIxK*&wz<2cklT4-INZQKh z0d92L@hI8cofG`J&Aqz1I^v>0t`Emk;S{v;LhP-a#*o=mp2bj-r8BNW<|Q;1Li?mN zxyR7ZpvZy7qwDJhD%4q@Y(ciHwFC67s)qCDDmd!m^K+dMb=J6vU;PlQsE>1w|PCDyA!p2e+6nI2)W9=$Bi zPEIX`k0R;tza+k49(;SC5mc&lRULTq!WjQ4e#9N8$G@+X!1NC#g^T_4_De@cq}ldH z>7hh}|J<~Qw$t2Sp-gBc^)$iJhOS0?Pc{p<`6VLF%yDQO zX=o-(F)}H-#eA&n>%&wrL*dnM!PI2uz?@uVKdGKkC~2Ek_Xh1PCA7=Y`D~mX9YtHd z(jBO{lY=b?|LM7fEH%AaRBGgt7tZp|vZ`7PUit@P?hqvI~^$XiFj4i$D4&0qc*>wSM%MutQ{uofw)}LpgpBh>Rz7Z-#N2 z*mZ5Ci@SzlG>YxxwoiYoL}4)P=+j1A?qbhY{S43_z2SRDM71gIjWwukIXbR(bBe!> zv=dg8qpjk9Zs-;gG4z}#QaA86++{DwYUyZ;6ve=x61=YB5w;%RxX5b4WXGW_=?Z>C zS)c)l`S`}lbKQ`j{iqX+W?N@ktC!{3R?|MS*wd#I@&j2yT=jle<+GKa4G(6u=Hl_} zb&OBdS(l3kDDR|-?;cDZ6Hd;~*M2$-f8kjyG5ef-rFLbqN)M1v0{RYVx~a!AUNb5= zKmsZAaMcbHscC8X*)jDn(8}b?i-nA$6vmXNK9P-A4)Eo@``2EAHNPEK-R6>-!2;HqB!N(9iX9kiYBedF?N3yWB2 zD0~jAE1I-Cto{(4d9;)T+B!nT9(;rwzKuEEvhF9z6@8l^%w|yH2UDD4RzC*w& zFOJU!ha|j6AH3&|`A*HeA1y^+LvAt0@Yb>zWvQ&*(Q=Z0x&te~8`5Ydij$}1^A7(8z&D@t8B}OMguv7u+Qg(JRToErE;)gtx%hfE z&Uhqqv4y{Zfv#^+X69zIY&lG^`3BcluPltt&86QxUZg(*w;^gSnV}m6gyrkq-*a-< z;=vpc6biMlB2j4aoyUTcg#lwKFJnQv=mkRhlaY;#Fvy+8Ier;gtTN30WE5fF*MBe;^btkzj&F zSAk*n!k@82N9I92LD6xBa6kDFr@-RdRw^GXVOIC5C125ZQLx9~T*LKq&K^iiOvpBu z85IcP+?z#~-09Uy41&qHV1{LYEUh;C%vX%7%t4R8d85I{I8{anQ#4-MEF>I3NvoTi z^J8OXi_@;#__#E>yMLah!3VdzAdh1L8}1{))ljr@kb28ETMdXGi=KQNm%Omr z5+$NfQLKYxqK(fR_W{R~1dj*&Z1Mb&k8vBd5z2?xZ<&f9?)B*98dg?t_|6D)0-2sJ z{CB|2``B1#*xcXfAC8PE$y3m~tTdWT!=U454G*G+W;z0C`2qr(exG=U;ro0sU-j50 zt!SClt(@yE#H7tdw2QkIvB)HI8EQLSq3z!|iTaJd*99W=Y1pkTEeEJC7R&I;y|tD4 zdu35HRbN}HfAVFyJia}}MJD_Jx3ochmE=Fv!2PR>FsvWn(+8dwQw zTHP3Z3-p7v0x1?;TbnHK{{YHew8>2I>%-puzF^yfn4+ieKyv~Ub;@I7=iU8VnYvkM zSuDZpdM0IF`E)`gi?lQsc~22LyLH%AFg71d+fdh#KFDOujO;P4m~Qan5r@EA+APe| zQ$wHIn7*$G@A?t3__AeZHwEh&sJ%p~fVD0!)4~qk%@qAtQ?GVEzzJ|(Pw(AVd+cQj zw%?45ldd0QO{`B!6zPIx_zu=>D34FkO+?o4D_lkM(_V_QqN2n&eGi+slw@a>MIRet z#zf|16@B`P#+f^n6BZ~lnP2o@e1`R6-UUg7!p^ef5PcTrvrEg%>&K&=>ODEZcLNXX z-nDj2O~}F~z6Un7Tr~sHCjsd@{sS04fIPr74q>73YvLx~_|_DZ=TLs*h|Q_b&)>e| zZZR`?`O7m#--G2x&aaI@S15D}tTyQ3Vlis|{ss%E*csH%Xh{|cyv@2J8Adsc!1^D6 zQs_)4P;MLmb>* zcK1wJc)rr9_quP&;#*j+YrH?eHecLH7@W~6HA)+TUC7|O$^!1fr2QqLdNx#dXzifj zj`d^vPKcc@gn^zbjw^~a+^wQTL$ElRC%Nmo041^UKAd7;_cW~gt81Y`Q?MjF;td@> z*a^b@_ANIL1s6r8akskA!+Qya@|WOuLhpE57gVpnb`oC2ALi|hnp|Vje0%S1oy2_# z9)9_A`unvzoW;p2a%zH#fgfJqoHY$$H#PCv*N$o%H3(mtO&8{@Si)|EWxBzeWu?>m z7d7M7;2e2RdTh-fRwBDhlvUm0gX)vGeB}02^l9ffM3dfift-w&Je-m&i3Y+%rYdzC l4Abj-Wdjo1|BZ{sVFa%(xawEU!+)nyYiZ~|s8q8F{~rWFJ39aX literal 0 HcmV?d00001 diff --git a/docker/cleandb b/docker/cleandb new file mode 100644 index 000000000..ae2ece3bc --- /dev/null +++ b/docker/cleandb @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "Shutting down any instance still running..." +docker-compose down -v +echo "Rebuilding the DB image..." +docker-compose pull db +docker-compose build --no-cache db +echo "Done!" \ No newline at end of file diff --git a/docker/settings_local.py b/docker/configs/settings_local.py similarity index 86% rename from docker/settings_local.py rename to docker/configs/settings_local.py index 6318f1b19..bb9210090 100644 --- a/docker/settings_local.py +++ b/docker/configs/settings_local.py @@ -1,14 +1,14 @@ # Copyright The IETF Trust 2007-2019, All Rights Reserved # -*- coding: utf-8 -*- -import six -if six.PY3: - from typing import Collection, Dict, List, Tuple # pyflakes:ignore +from ietf.settings import * # pyflakes:ignore -SECRET_KEY = 'jzv$o93h_lzw4a0%0oz-5t5lk+ai=3f8x@uo*9ahu8w4i300o6' +ALLOWED_HOSTS = ['*'] DATABASES = { 'default': { + 'HOST': 'db', + 'PORT': 3306, 'NAME': 'ietf_utf8', 'ENGINE': 'django.db.backends.mysql', 'USER': 'django', @@ -18,11 +18,11 @@ DATABASES = { 'init_command': 'SET storage_engine=InnoDB; SET names "utf8"', }, }, -} # type: Dict[str, Dict[str, Collection[str]]] +} DATABASE_TEST_OPTIONS = { 'init_command': 'SET storage_engine=InnoDB', - } +} IDSUBMIT_IDNITS_BINARY = "/usr/local/bin/idnits" IDSUBMIT_REPOSITORY_PATH = "test/id/" @@ -57,5 +57,3 @@ SUBMIT_YANG_DRAFT_MODEL_DIR = 'data/developers/ietf-ftp/yang/draftmod/' SUBMIT_YANG_INVAL_MODEL_DIR = 'data/developers/ietf-ftp/yang/invalmod/' SUBMIT_YANG_IANA_MODEL_DIR = 'data/developers/ietf-ftp/yang/ianamod/' SUBMIT_YANG_RFC_MODEL_DIR = 'data/developers/ietf-ftp/yang/rfcmod/' - - diff --git a/.devcontainer/settings_local_debug.py b/docker/configs/settings_local_debug.py similarity index 100% rename from .devcontainer/settings_local_debug.py rename to docker/configs/settings_local_debug.py diff --git a/docker/configs/settings_local_sqlitetest.py b/docker/configs/settings_local_sqlitetest.py new file mode 100644 index 000000000..a93f3f181 --- /dev/null +++ b/docker/configs/settings_local_sqlitetest.py @@ -0,0 +1,84 @@ +# Copyright The IETF Trust 2010-2020, All Rights Reserved +# -*- coding: utf-8 -*- + + +# Standard settings except we use SQLite and skip migrations, this is +# useful for speeding up tests that depend on the test database, try +# for instance: +# +# ./manage.py test --settings=settings_sqlitetest doc.ChangeStateTestCase +# + +import os +from ietf.settings import * # pyflakes:ignore +from ietf.settings import TEST_CODE_COVERAGE_CHECKER, BASE_DIR, PHOTOS_DIRNAME +import debug # pyflakes:ignore +debug.debug = True + +# Workaround to avoid spending minutes stepping through the migrations in +# every test run. The result of this is to use the 'syncdb' way of creating +# the test database instead of doing it through the migrations. Taken from +# https://gist.github.com/NotSqrt/5f3c76cd15e40ef62d09 + +class DisableMigrations(object): + + def __contains__(self, item): + return True + + def __getitem__(self, item): + return None + +MIGRATION_MODULES = DisableMigrations() + +DATABASES = { + 'default': { + 'NAME': 'test.db', + 'ENGINE': 'django.db.backends.sqlite3', + }, + } + +if TEST_CODE_COVERAGE_CHECKER and not TEST_CODE_COVERAGE_CHECKER._started: # pyflakes:ignore + TEST_CODE_COVERAGE_CHECKER.start() # pyflakes:ignore + +NOMCOM_PUBLIC_KEYS_DIR=os.path.abspath("tmp-nomcom-public-keys-dir") + +# Undo any developer-dependent middleware when running the tests +MIDDLEWARE = [ c for c in MIDDLEWARE if not c in DEV_MIDDLEWARE ] # pyflakes:ignore + +TEMPLATES[0]['OPTIONS']['context_processors'] = [ p for p in TEMPLATES[0]['OPTIONS']['context_processors'] if not p in DEV_TEMPLATE_CONTEXT_PROCESSORS ] # pyflakes:ignore + +REQUEST_PROFILE_STORE_ANONYMOUS_SESSIONS = False + +IDSUBMIT_IDNITS_BINARY = "/usr/local/bin/idnits" +IDSUBMIT_REPOSITORY_PATH = "test/id/" +IDSUBMIT_STAGING_PATH = "test/staging/" +INTERNET_DRAFT_ARCHIVE_DIR = "test/archive/" +INTERNET_ALL_DRAFTS_ARCHIVE_DIR = "test/archive/" +RFC_PATH = "test/rfc/" + +AGENDA_PATH = 'data/developers/www6s/proceedings/' +MEETINGHOST_LOGO_PATH = AGENDA_PATH + +USING_DEBUG_EMAIL_SERVER=True +EMAIL_HOST='localhost' +EMAIL_PORT=2025 + +TRAC_WIKI_DIR_PATTERN = "test/wiki/%s" +TRAC_SVN_DIR_PATTERN = "test/svn/%s" +TRAC_CREATE_ADHOC_WIKIS = [ +] # type: List[Tuple[str, str, str]] + +MEDIA_BASE_DIR = 'test' +MEDIA_ROOT = MEDIA_BASE_DIR + '/media/' +MEDIA_URL = '/media/' + +PHOTOS_DIRNAME = 'photo' +PHOTOS_DIR = MEDIA_ROOT + PHOTOS_DIRNAME + +DOCUMENT_PATH_PATTERN = 'data/developers/ietf-ftp/{doc.type_id}/' + +SUBMIT_YANG_CATALOG_MODEL_DIR = 'data/developers/ietf-ftp/yang/catalogmod/' +SUBMIT_YANG_DRAFT_MODEL_DIR = 'data/developers/ietf-ftp/yang/draftmod/' +SUBMIT_YANG_INVAL_MODEL_DIR = 'data/developers/ietf-ftp/yang/invalmod/' +SUBMIT_YANG_IANA_MODEL_DIR = 'data/developers/ietf-ftp/yang/ianamod/' +SUBMIT_YANG_RFC_MODEL_DIR = 'data/developers/ietf-ftp/yang/rfcmod/' diff --git a/docker/db.Dockerfile b/docker/db.Dockerfile new file mode 100644 index 000000000..00a08c8d0 --- /dev/null +++ b/docker/db.Dockerfile @@ -0,0 +1,56 @@ +# ==================== +# --- Import Stage --- +# ==================== +FROM ubuntu:hirsute AS importStage + +# Install dependencies for import +RUN DEBIAN_FRONTEND=noninteractive apt-get -y update && \ + apt-get -y install --no-install-recommends \ + locales \ + mariadb-server \ + pigz \ + unzip && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# Set locale to en_US.UTF-8 +RUN echo "LC_ALL=en_US.UTF-8" >> /etc/environment && \ + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \ + echo "LANG=en_US.UTF-8" > /etc/locale.conf && \ + dpkg-reconfigure locales && \ + locale-gen en_US.UTF-8 && \ + update-locale LC_ALL en_US.UTF-8 +ENV LC_ALL en_US.UTF-8 + +# Turn on mariadb performance_schema +RUN sed -i 's/\[mysqld\]/\[mysqld\]\nperformance_schema=ON/' /etc/mysql/mariadb.conf.d/50-server.cnf + +# Make the mariadb sys schema available for possible installation +# We would normally use the next line, but that has a bug: +# ADD https://github.com/FromDual/mariadb-sys/archive/master.zip / +# This is the repo that has the PR: +ADD https://github.com/grooverdan/mariadb-sys/archive/refs/heads/master.zip / +RUN unzip /master.zip +RUN rm /master.zip + +# Import the latest database dump +ADD https://www.ietf.org/lib/dt/sprint/ietf_utf8.sql.gz / +RUN pigz -v -d /ietf_utf8.sql.gz && \ + sed -i -e 's/ENGINE=MyISAM/ENGINE=InnoDB/' /ietf_utf8.sql +# see https://dba.stackexchange.com/a/83385 +RUN sed -i 's/\[mysqld\]/\[mysqld\]\ninnodb_buffer_pool_size = 1G\ninnodb_log_buffer_size = 128M\ninnodb_log_file_size = 256M\ninnodb_write_io_threads = 8\ninnodb_flush_log_at_trx_commit = 0/' /etc/mysql/mariadb.conf.d/50-server.cnf && \ + service mariadb start --innodb-doublewrite=0 && \ + echo "This sequence will take a long time, please be patient" && \ + mysqladmin -u root --default-character-set=utf8 create ietf_utf8 && \ + bash -c "cd /mariadb-sys-master && mysql --user root < sys_10.sql" && \ + bash -c "mysql --user root ietf_utf8 <<< \"GRANT ALL PRIVILEGES ON *.* TO 'django'@'%' IDENTIFIED BY 'RkTkDPFnKpko'; FLUSH PRIVILEGES;\"" && \ + bash -c "mysql --user=django --password=RkTkDPFnKpko -f ietf_utf8 < /ietf_utf8.sql" && \ + service mariadb stop + +# =================== +# --- Final Image --- +# =================== +FROM mariadb:10 +LABEL maintainer="IETF Tools Team " + +# Copy the mysql data folder from the import stage +COPY --from=importStage /var/lib/mysql /var/lib/mysql diff --git a/docker/docker-compose.extend.yml b/docker/docker-compose.extend.yml new file mode 100644 index 000000000..974dec69c --- /dev/null +++ b/docker/docker-compose.extend.yml @@ -0,0 +1,9 @@ +version: '3.8' + +services: + app: + ports: + - '8000:8000' + db: + ports: + - '3306' \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/docker/docker-compose.yml similarity index 66% rename from .devcontainer/docker-compose.yml rename to docker/docker-compose.yml index 9661ec999..1f5c01814 100644 --- a/.devcontainer/docker-compose.yml +++ b/docker/docker-compose.yml @@ -4,31 +4,32 @@ services: app: build: context: .. - dockerfile: .devcontainer/Dockerfile + dockerfile: docker/app.Dockerfile args: # Update 'VARIANT' to pick a version of Python: 3, 3.10, 3.9, 3.8, 3.7, 3.6 # Append -bullseye or -buster to pin to an OS version. # Use -bullseye variants on local arm64/Apple Silicon. VARIANT: 3.6-bullseye + NODE_VERSION: '16' volumes: - - ..:/usr/local/share/datatracker:cached + - ..:/root/src:cached init: true # Overrides default command so things don't shut down after the process ends. command: sleep infinity # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. - network_mode: service:db + # network_mode: service:db depends_on: - db - environment: - USER: django - UID: 1001 - GID: 1001 - DATADIR: data + # environment: + # USER: django + # UID: 1001 + # GID: 1001 + # DATADIR: data # DJANGO_SETTINGS_MODULE: settings_sqlitetest # Uncomment the next line to use a non-root user for all processes. @@ -38,7 +39,9 @@ services: # (Adding the "ports" property to this file will not forward from a Codespace.) db: - image: mariadb:10 + build: + context: .. + dockerfile: docker/db.Dockerfile restart: unless-stopped volumes: - mariadb-data:/var/lib/mysql @@ -47,8 +50,15 @@ services: MYSQL_DATABASE: ietf_utf8 MYSQL_USER: django MYSQL_PASSWORD: RkTkDPFnKpko - command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci'] - + command: + - '--character-set-server=utf8' + - '--collation-server=utf8_unicode_ci' + - '--innodb-buffer-pool-size=1G' + - '--innodb-log-buffer-size=128M' + - '--innodb-log-file-size=256M' + - '--innodb-write-io-threads=8' + - '--innodb-flush-log-at-trx-commit=0' + - '--performance-schema=1' # Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally. # (Adding the "ports" property to this file will not forward from a Codespace.) diff --git a/docker/docker-init.sh b/docker/docker-init.sh deleted file mode 100644 index c5b29f9cf..000000000 --- a/docker/docker-init.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash - -MYSQLDIR=/var/lib/mysql - -if [ ! -d "$MYSQLDIR" ]; then - echo "WARNING: Expected the directory $MYSQLDIR to exist." - exit 1 -fi - -service rsyslog start - -if [ -z "$(ls -A $MYSQLDIR/mysql 2>/dev/null)" ]; then - can=$(date -r /mysql +%s) - now=$(date +%s) - age=$((($now - $can)/86400)) - echo "NOTE: Database empty; populating it from canned snapshot ($age days old)" - echo " This will take a little while..." - cp -r /mysql/* $MYSQLDIR -fi - -service mariadb start - -if ! service mariadb status; then - echo "ERROR: MySQL didn't start. Here are some possible causes:" - echo "-------------------------------------------------------------------" - grep mysqld /var/log/syslog - echo "-------------------------------------------------------------------" - echo "Such errors are usually due to a corrupt or outdated database." - echo "Remove your local database and let the image install a clean copy." - exit 1 -fi - -if [ ! -f /root/src/ietf/settings_local.py ]; then - echo "Setting up a default settings_local.py ..." - cp /root/src/docker/settings_local.py /root/src/ietf/settings_local.py -fi - -for sub in \ - test/id \ - test/staging \ - test/archive \ - test/rfc \ - test/media \ - test/wiki/ietf \ - data/nomcom_keys/public_keys \ - data/developers/ietf-ftp \ - data/developers/ietf-ftp/bofreq \ - data/developers/ietf-ftp/charter \ - data/developers/ietf-ftp/conflict-reviews \ - data/developers/ietf-ftp/internet-drafts \ - data/developers/ietf-ftp/rfc \ - data/developers/ietf-ftp/status-changes \ - data/developers/ietf-ftp/yang/catalogmod \ - data/developers/ietf-ftp/yang/draftmod \ - data/developers/ietf-ftp/yang/ianamod \ - data/developers/ietf-ftp/yang/invalmod \ - data/developers/ietf-ftp/yang/rfcmod \ - data/developers/www6s \ - data/developers/www6s/staging \ - data/developers/www6s/wg-descriptions \ - data/developers/www6s/proceedings \ - data/developers/www6/ \ - data/developers/www6/iesg \ - data/developers/www6/iesg/evaluation \ - ; do - dir="/root/src/$sub" - if [ ! -d "$dir" ]; then - echo "Creating dir $dir" - mkdir -p "$dir"; - fi -done - -python -m smtpd -n -c DebuggingServer localhost:2025 & -echo - -if [ -z "$*" ]; then - echo "You can execute arbitrary commands now, e.g.," - echo - echo " ietf/manage.py check && ietf/manage.py runserver 0.0.0.0:8000" - echo - echo "to start a development instance of the Datatracker." - echo - bash -else - echo "Executing \"$*\" and stopping container." - echo - bash -c "$*" -fi - -service mariadb stop -service rsyslog stop \ No newline at end of file diff --git a/docker/build b/docker/misc/build old mode 100755 new mode 100644 similarity index 77% rename from docker/build rename to docker/misc/build index c84371092..b3cc97e52 --- a/docker/build +++ b/docker/misc/build @@ -13,7 +13,7 @@ if [[ $(uname) =~ CYGWIN.* ]]; then parent=$(echo "$parent" | sed -e 's/^\/cygdr function usage() { cat </dev/null || true -docker build --progress plain -t "$IMAGE:$TAG" docker/ -docker tag "$(docker images -q $IMAGE | head -n 1)" $IMAGE:latest +docker build --progress plain -t "$IMAGE-app:$TAG" -f docker/app.Dockerfile . +docker build --progress plain -t "$IMAGE-db:$TAG" -f docker/db.Dockerfile . +docker tag "$(docker images -q $IMAGE-app | head -n 1)" $IMAGE-app:latest +docker tag "$(docker images -q $IMAGE-db | head -n 1)" $IMAGE-db:latest if [ -z "$LOCAL" ]; then - docker push $IMAGE:latest - docker push "$IMAGE:$TAG" + docker push $IMAGE-app:latest + docker push "$IMAGE-app:$TAG" + docker push $IMAGE-db:latest + docker push "$IMAGE-db:$TAG" fi \ No newline at end of file diff --git a/docker/copydb b/docker/misc/copydb old mode 100755 new mode 100644 similarity index 100% rename from docker/copydb rename to docker/misc/copydb diff --git a/docker/run b/docker/run index 79e7510cd..f22ad235e 100755 --- a/docker/run +++ b/docker/run @@ -1,110 +1,5 @@ #!/bin/bash -version=0.20 -program=${0##*/} -progdir=${0%/*} -if [ "$progdir" = "$program" ]; then progdir="."; fi -if [ "$progdir" = "." ]; then progdir="$PWD"; fi -parent=$(dirname "$progdir") -if [ "$parent" = "." ]; then parent="$PWD"; fi -if [[ $(uname) =~ CYGWIN.* ]]; then parent=$(echo "$parent" | sed -e 's/^\/cygdrive\/\(.\)/\1:/'); fi - - -function usage() { - cat < - Lars Eggert, - -COPYRIGHT - Copyright (c) 2016 IETF Trust and the persons identified as authors of - the code. All rights reserved. Redistribution and use in source and - binary forms, with or without modification, is permitted pursuant to, - and subject to the license terms contained in, the Revised BSD - License set forth in Section 4.c of the IETF Trust’s Legal Provisions - Relating to IETF Documents(https://trustee.ietf.org/license-info). -EOF -} - - -function die() { - echo -e "\n$program: error: $*" >&2 - exit 1 -} - - -function version() { - echo -e "$program $version" -} - - -trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR - -# Default values -MYSQLDIR=$parent/data/mysql -PORT=8000 -REPO="ietf/datatracker-environment" -CACHED=':cached' - -# Option parsing -shortopts=cChp:V -args=$(getopt -o$shortopts $*) -if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi -set -- $args - -while true ; do - case "$1" in - -c) CACHED=':cached';; # Use cached disk access to reduce system load - -C) CACHED=':consistent';; # Use fully synchronized disk access - -h) usage; exit;; # Show this help, then exit - -p) PORT=$2; shift;; # Bind the container's port 8000 to external port PORT - -V) version; exit;; # Show program version, then exit - --) shift; break;; - *) die "Internal error, inconsistent option specification: '$1'";; - esac - shift -done - -if [ -z "$TAG" ]; then - TAG=$(basename "$(svn info "$parent" | grep ^URL | awk '{print $2}' | tr -d '\r')") -fi - -if [[ $(uname) =~ CYGWIN.* ]]; then - echo "Running under Cygwin, replacing symlinks with file copies" - ICSFILES=$(/usr/bin/find "$parent/vzic/zoneinfo/" -name '*.ics' -print) - for ICSFILE in $ICSFILES; do - LINK=$(head -n1 "$ICSFILE" | sed -e '/link .*/!d' -e 's/link \(.*\)/\1/') - if [ "$LINK" ]; then - WDIR=$(dirname "$ICSFILE") - echo "Replacing $(basename "$ICSFILE") with $LINK" - cp -f "$WDIR/$LINK" "$ICSFILE" - fi - done -fi - -echo "Starting a docker container for '$REPO:$TAG'." -mkdir -p "$MYSQLDIR" -docker run -ti -p "$PORT":8000 -p 33306:3306 \ - -v "$parent:/root/src$CACHED" \ - -v "$MYSQLDIR:/var/lib/mysql:delegated" \ - "$REPO:$TAG" "$@" \ No newline at end of file +docker-compose -f docker-compose.yml -f docker-compose.extend.yml up -d +docker-compose exec app /bin/sh /docker-init.sh +docker-compose down \ No newline at end of file diff --git a/docker/scripts/app-init.sh b/docker/scripts/app-init.sh new file mode 100755 index 000000000..9e11854f5 --- /dev/null +++ b/docker/scripts/app-init.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +WORKSPACEDIR="/root/src" + +service rsyslog start + +# Copy config files if needed + +if [ ! -f "$WORKSPACEDIR/ietf/settings_local.py" ]; then + echo "Setting up a default settings_local.py ..." + cp $WORKSPACEDIR/docker/configs/settings_local.py $WORKSPACEDIR/ietf/settings_local.py +else + echo "Using existing ietf/settings_local.py file" + if ! cmp -s $WORKSPACEDIR/docker/configs/settings_local.py $WORKSPACEDIR/ietf/settings_local.py; then + echo "NOTE: Differences detected compared to docker/configs/settings_local.py!" + echo "We'll assume you made these deliberately." + fi +fi + +if [ ! -f "$WORKSPACEDIR/ietf/settings_local_debug.py" ]; then + echo "Setting up a default settings_local_debug.py ..." + cp $WORKSPACEDIR/docker/configs/settings_local_debug.py $WORKSPACEDIR/ietf/settings_local_debug.py +else + echo "Using existing ietf/settings_local_debug.py file" + if ! cmp -s $WORKSPACEDIR/docker/configs/settings_local_debug.py $WORKSPACEDIR/ietf/settings_local_debug.py; then + echo "NOTE: Differences detected compared to docker/configs/settings_local_debug.py!" + echo "We'll assume you made these deliberately." + fi +fi + +if [ ! -f "$WORKSPACEDIR/ietf/settings_local_sqlitetest.py" ]; then + echo "Setting up a default settings_local_sqlitetest.py ..." + cp $WORKSPACEDIR/docker/configs/settings_local_sqlitetest.py $WORKSPACEDIR/ietf/settings_local_sqlitetest.py +else + echo "Using existing ietf/settings_local_sqlitetest.py file" + if ! cmp -s $WORKSPACEDIR/docker/configs/settings_local_sqlitetest.py $WORKSPACEDIR/ietf/settings_local_sqlitetest.py; then + echo "NOTE: Differences detected compared to docker/configs/settings_local_sqlitetest.py!" + echo "We'll assume you made these deliberately." + fi +fi + +# Create assets directories + +for sub in \ + test/id \ + test/staging \ + test/archive \ + test/rfc \ + test/media \ + test/wiki/ietf \ + data/nomcom_keys/public_keys \ + data/developers/ietf-ftp \ + data/developers/ietf-ftp/bofreq \ + data/developers/ietf-ftp/charter \ + data/developers/ietf-ftp/conflict-reviews \ + data/developers/ietf-ftp/internet-drafts \ + data/developers/ietf-ftp/rfc \ + data/developers/ietf-ftp/status-changes \ + data/developers/ietf-ftp/yang/catalogmod \ + data/developers/ietf-ftp/yang/draftmod \ + data/developers/ietf-ftp/yang/ianamod \ + data/developers/ietf-ftp/yang/invalmod \ + data/developers/ietf-ftp/yang/rfcmod \ + data/developers/www6s \ + data/developers/www6s/staging \ + data/developers/www6s/wg-descriptions \ + data/developers/www6s/proceedings \ + data/developers/www6/ \ + data/developers/www6/iesg \ + data/developers/www6/iesg/evaluation \ + ; do + dir="/root/src/$sub" + if [ ! -d "$dir" ]; then + echo "Creating dir $dir" + mkdir -p "$dir"; + fi +done + +# Wait for DB container +if [ -n "$EDITOR_VSCODE" ]; then + echo "Waiting for DB container to come online ..." + wget -qO- https://raw.githubusercontent.com/eficode/wait-for/v2.1.3/wait-for | sh -s -- localhost:3306 -- echo "DB ready" +fi + +# Initial checks + +echo "Running initial checks..." +/usr/local/bin/python $WORKSPACEDIR/ietf/manage.py check --settings=settings_local +# /usr/local/bin/python $WORKSPACEDIR/ietf/manage.py migrate --settings=settings_local + +echo "Done!" + +if [ -z "$EDITOR_VSCODE" ]; then + python -m smtpd -n -c DebuggingServer localhost:2025 & + if [ -z "$*" ]; then + echo + echo "You can execute arbitrary commands now, e.g.," + echo + echo " ietf/manage.py check && ietf/manage.py runserver 0.0.0.0:8000" + echo + echo "to start a development instance of the Datatracker." + echo + bash + else + echo "Executing \"$*\" and stopping container." + echo + bash -c "$*" + fi + service rsyslog stop +fi \ No newline at end of file diff --git a/docker/rsync-extras b/docker/scripts/app-rsync-extras.sh similarity index 100% rename from docker/rsync-extras rename to docker/scripts/app-rsync-extras.sh diff --git a/docker/scripts/app-win32-timezone-fix.sh b/docker/scripts/app-win32-timezone-fix.sh new file mode 100755 index 000000000..031f54fa4 --- /dev/null +++ b/docker/scripts/app-win32-timezone-fix.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +WORKSPACEDIR="/root/src" + +ICSFILES=$(/usr/bin/find $WORKSPACEDIR/vzic/zoneinfo/ -name '*.ics' -print) +for ICSFILE in $ICSFILES +do + LINK=$(head -n1 $ICSFILE | sed -e '/link .*/!d' -e 's/link \(.*\)/\1/') + if [ "$LINK" ]; then + WDIR=$(dirname $ICSFILE) + echo "Replacing $(basename $ICSFILE) with $LINK" + cp -f $WDIR/$LINK $ICSFILE + fi +done +echo "Done!" \ No newline at end of file diff --git a/docker/updatedb b/docker/scripts/updatedb old mode 100755 new mode 100644 similarity index 100% rename from docker/updatedb rename to docker/scripts/updatedb