From fd703abd5a2ddd68382df94fcd6ffda7ef52f6e3 2020-05-12 18:35:39 From: Branko Majic Date: 2020-05-12 18:35:39 Subject: [PATCH] MAR-149: Updated usage documentation: - Add warning that Majic Ansible Roles support only Python 3. - Updated the Django Wiki deployment to use Python 3. - Upgraded the Django Wiki deployment for use with Python 3. - Removed one stale warning regarding compat links for MariDB devel files (leftover from Jessie). --- diff --git a/docs/usage.rst b/docs/usage.rst index b673f276806fff0669fd974642dc2ed12d1259a9..684230e7fd6074b5e0c07c449d77507142f79677 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -28,6 +28,19 @@ By the end of following the instructions, you will have the following: * Web server, providing the web services. * Backup server, used for storing all of the backups. +.. warning:: + Majic Ansible Roles support *only* Python 3 - both on the + controller side and on the managed servers side. + + It is important to make sure that both the controller Python + virtual environment used for Ansible *and* the interpreter for + remote servers are *both* set-up to use Python 3. + + Python 3 is specified explicitly during virtual environment + creation and in ``ansible.cfg`` configuration file + (``interpreter_python`` option under ``defaults`` section). + + Pre-requisites -------------- @@ -116,7 +129,7 @@ packages, and to prepare the environment a bit on the Ansible server: 1. Install the necessary system packages (using the ``root`` account):: - apt-get install -y virtualenv virtualenvwrapper git python-pip python-dev libffi-dev libssl-dev + apt-get install -y virtualenv virtualenvwrapper git python3-pip python3-dev libffi-dev libssl-dev 2. Set-up the virtual environment (using the ``ansible`` account): @@ -129,7 +142,7 @@ packages, and to prepare the environment a bit on the Ansible server: :: mkdir ~/mysite/ - mkvirtualenv -a ~/mysite/ mysite + mkvirtualenv -p /usr/bin/python3 -a ~/mysite/ mysite pip install -U pip setuptools pip install 'ansible~=2.9.0' dnspython @@ -184,6 +197,7 @@ First of all, let's set-up some basic directory structure and configuration: roles_path=/home/ansible/majic-ansible-roles/roles:/home/ansible/mysite/roles force_handlers = True inventory = /home/ansible/mysite/hosts + interpreter_python = /usr/bin/python3 [ssh_connection] pipelining = True @@ -318,7 +332,7 @@ If you need to, you can easily serve the preseed files from the Ansible server with Python's built-in HTTP server:: cd ~/mysite/preseed_files/ - python -m SimpleHTTPServer 8000 + python -m http.server 8000 Then you can point installer to the preseed file selecting the ``Advanced options -> Automated install`` (don't press ``ENTER`` yet), @@ -961,7 +975,7 @@ external addresses on those two servers goes through our anti-virus scanner. 5. After this you may want to test out sending mail via web or backup server's local SMTP to the root user (to see if the aliasing works), and to some - external mail address to check if forwarding works correctly too. Run some + external mail address to check if forwarding works correctly too. Run something similar to the following on your web server:: swaks --to root@localhost --server localhost @@ -1463,7 +1477,6 @@ Before we start, here is a couple of useful pointers regarding the state: link owner: "admin-tbg_example_com" group: "web-tbg_example_com" - mode: 02750 become: yes become_user: admin-tbg_example_com @@ -1669,16 +1682,15 @@ on the safe side: # in order to build Python packages installed via pip packages: - build-essential - - python-dev + - python3-dev + - libjpeg62-turbo - libjpeg-dev - - libzip-dev - - libtiff-dev - - libfreetype6-dev - - liblcms2-dev - - libwebp-dev - - libopenjp2-7-dev - - libmariadb-client-lgpl-dev - - libmariadb-client-lgpl-dev-compat + - libpng16-16 + - libpng-dev + - libmariadb-dev + - libmariadb-dev-compat + # Specify that Python 3 should be used for the application + python_version: 3 # Here we specify that anything accessing our website with "/static/" # URL should be treated as request to a static file, to be served # directly by Nginx instead of the WSGI server. @@ -1691,16 +1703,18 @@ on the safe side: # These are additional packages that should be installed in the # virtual environment. virtualenv_packages: - - pillow - - django==1.8.13 - - wiki - - MySQL-python + - django~=2.2.0 + - wiki~=0.5.0 + - mysqlclient # This is the name of the WSGI application to # serve. wiki_example_com.wsgi will be the Python "module" that is # accesed, while application is the object instantiated within it (the # application itself). The module is referenced relative to the code # directory (in our case /var/www/wiki.example.com/code/). wsgi_application: wiki_example_com.wsgi:application + # Specify explicitly requirements for installing Gunicorn. + wsgi_requirements: + - gunicorn==20.0.4 - role: database db_name: wiki db_password: wiki @@ -1771,7 +1785,6 @@ on the safe side: become: yes become_user: admin-wiki_example_com with_items: - - syncdb - migrate - collectstatic @@ -1812,69 +1825,91 @@ on the safe side: Django settings for wiki_example_com project. For more information on this file, see - https://docs.djangoproject.com/en/1.6/topics/settings/ + https://docs.djangoproject.com/en/2.2/topics/settings/ For the full list of settings and their values, see - https://docs.djangoproject.com/en/1.6/ref/settings/ + https://docs.djangoproject.com/en/2.2/ref/settings/ """ - # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os - BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + from django.urls import reverse_lazy + + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) + BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production - # See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ + # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! - SECRET_KEY = 'l^q+t$7h$ebls)v34+w9m9v4$n+^(9guxqntu&#cc4m&lfd-6_' + SECRET_KEY = '8rok13az%bqtb=ya&s9sia_x*@@rhd9a%g=!6nh4tb!g14rlt^' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False - TEMPLATE_DEBUG = False - ALLOWED_HOSTS = ["wiki.example.com", "localhost"] # Application definition - INSTALLED_APPS = ( + INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'django.contrib.sites', - 'django.contrib.humanize', - 'django_nyt', + 'django.contrib.sites.apps.SitesConfig', + 'django.contrib.humanize.apps.HumanizeConfig', + 'django_nyt.apps.DjangoNytConfig', 'mptt', 'sekizai', 'sorl.thumbnail', - 'wiki', - 'wiki.plugins.attachments', - 'wiki.plugins.notifications', - 'wiki.plugins.images', - 'wiki.plugins.macros', - ) - - MIDDLEWARE_CLASSES = ( + 'wiki.apps.WikiConfig', + 'wiki.plugins.attachments.apps.AttachmentsConfig', + 'wiki.plugins.notifications.apps.NotificationsConfig', + 'wiki.plugins.images.apps.ImagesConfig', + 'wiki.plugins.macros.apps.MacrosConfig', + ] + + MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - ) + ] ROOT_URLCONF = 'wiki_example_com.urls' + TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.request', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + "sekizai.context_processors.sekizai", + ], + }, + }, + ] + WSGI_APPLICATION = 'wiki_example_com.wsgi.application' # Database - # https://docs.djangoproject.com/en/1.6/ref/settings/#databases + # https://docs.djangoproject.com/en/2.2/ref/settings/#databases DATABASES = { 'default': { @@ -1887,8 +1922,27 @@ on the safe side: } } + # Password validation + # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + + AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, + ] + + # Internationalization - # https://docs.djangoproject.com/en/1.6/topics/i18n/ + # https://docs.djangoproject.com/en/2.2/topics/i18n/ LANGUAGE_CODE = 'en-us' @@ -1902,44 +1956,27 @@ on the safe side: # Static files (CSS, JavaScript, Images) - # https://docs.djangoproject.com/en/1.6/howto/static-files/ + # https://docs.djangoproject.com/en/2.2/howto/static-files/ STATIC_URL = '/static/' - STATIC_ROOT = '/var/www/wiki.example.com/htdocs/static' - from django.conf import settings - - TEMPLATE_CONTEXT_PROCESSORS = settings.TEMPLATE_CONTEXT_PROCESSORS + ( - "django.core.context_processors.debug", - "django.core.context_processors.request", - "sekizai.context_processors.sekizai", - ) + SITE_ID = 1 - SITE_ID=1 + LOGIN_REDIRECT_URL = reverse_lazy('wiki:get', kwargs={'path': ''}) :file:`~/mysite/roles/wiki/files/urls.py` :: - from django.conf.urls import patterns, include, url - from wiki.urls import get_pattern as get_wiki_pattern - from django_nyt.urls import get_pattern as get_nyt_pattern - from django.contrib import admin - admin.autodiscover() - - urlpatterns = patterns('', - # Examples: - # url(r'^$', 'wiki_example_com.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), + from django.urls import path, include - url(r'^admin/', include(admin.site.urls)), - ) + urlpatterns = [ + path('admin/', admin.site.urls), + path('notifications/', include('django_nyt.urls')), + path('', include('wiki.urls')) + ] - urlpatterns += patterns('', - (r'^notifications/', get_nyt_pattern()), - (r'', get_wiki_pattern()) - ) :file:`~/mysite/roles/wiki/files/create_superadmin.py` :: @@ -1979,15 +2016,6 @@ on the safe side: 7. Apply the changes: - .. warning:: - - Due to `Debian Bug 766996 - `_ Majic Ansible - Roles try to detect if you install ``libmariadb-client-lgpl-dev-compat`` - package, and create symbolic link from ``/usr/local/bin/mysql_config`` to - ``/usr/bin/mariadb_config`` automatically. Otherwise the MySQL-python - package will fail to build due to missing ``mysql_config`` binary. - :: workon mysite && ansible-playbook playbooks/site.yml @@ -2237,7 +2265,12 @@ Genie*. So let's fix that one. role dependency definitions. :file:`~/mysite/roles/tbg/meta/main.yml` - :: + + .. Small workaround for Sphinx not preserving leading spaces in + case all lines have the same amount of leading spaces. + + .. code-block:: none + :name: sphinx_workaround - role: backup when: enable_backup