Commits

Mikhail Korobov committed 145ef78

simple tests for django 1.4 project layout; typo in config_templates/django_wsgi.py is fixed.

Comments (0)

Files changed (20)

fab_deploy/config_templates/django_wsgi.py

 # django >= 1.4 wsgi setup: remove "<1.4 wsgi setup" above, uncomment the
 # following line and set proper your project's name:
 
-# from my_project.wsgi import appliation
+# from my_project.wsgi import application

fab_deploy_tests/runtests.py

                     PipSetupTest, NoPipSetupTest, CrontabTest
                 ])),
         'deploy': TestSuite(load([
-                    DeployTest, CustomLayoutDeployTest
+                    DeployTest, CustomLayoutDeployTest, Django14LayoutDeployTest
                 ])),
         'prepare': TestSuite(load(common + [PrepareServerTest])),
     }

fab_deploy_tests/test_project/config_templates/django_wsgi.py

 add_to_path([
      os.path.normpath('{{ ENV_DIR }}/lib/python2.5/site-packages'),
      os.path.normpath('{{ ENV_DIR }}/lib/python2.6/site-packages'),
-     os.path.normpath('{{ PROJECT_DIR }}' + '/..'),
+     os.path.normpath('{{ ENV_DIR }}/lib/python2.7/site-packages'),
+
+     os.path.normpath('{{ PROJECT_DIR }}' + '/..'), # <- remove this line if django >= 1.4
      '{{ PROJECT_DIR }}',
 ])
 
+# django < 1.4 wsgi setup
 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
-
-#print sys.path
-
 import django.core.handlers.wsgi
 application = django.core.handlers.wsgi.WSGIHandler()
+
+# django >= 1.4 wsgi setup: remove "<1.4 wsgi setup" above, uncomment the
+# following line and set proper your project's name:
+
+# from my_project.wsgi import application

fab_deploy_tests/test_project2/fabfile.py

     CONFIG_TEMPLATES_PATHS = ['hosting/staging', 'hosting'],
 )
 
+@define_host('foo2@127.0.0.1:2222', LAYOUT_OPTIONS)
 def foo_site():
-    env.hosts = ['foo2@127.0.0.1:2222']
-    env.conf = dict(
+    return dict(
         VCS = 'git',
         SERVER_NAME = 'foo.example.com',
 
         DB_ROOT_PASSWORD = '123',
         DB_USER = 'foouser',
         DB_PASSWORD = 'foo123',
-    )
-    env.conf.update(LAYOUT_OPTIONS)
-    update_env()
+    )

fab_deploy_tests/test_project3/README

+django 1.4 project layout example

fab_deploy_tests/test_project3/__init__.py

+# -*- coding: utf-8 -*-
+from __future__ import absolute_import

fab_deploy_tests/test_project3/fabfile.py

+from fab_deploy.utils import define_host
+
+@define_host('baz@127.0.0.1:2222')
+def baz_site():
+    return dict(
+        CONFIG_TEMPLATES_PATHS=['test_project3/config_templates'],
+        LOCAL_CONFIG = 'test_project3/config.py',
+        REMOTE_CONFIG_TEMPLATE = 'test_project3/config.server.py',
+        PIP_REQUIREMENTS_PATH = 'test_project3/reqs/',
+
+        DB_USER = 'baz',
+        DB_PASSWORD = '123',
+        VCS = 'none',
+        SERVER_NAME = 'baz.example.com'
+    )

fab_deploy_tests/test_project3/manage.py

+#!/usr/bin/env python
+import os, sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project3.settings")
+
+    from django.core.management import execute_from_command_line
+
+    execute_from_command_line(sys.argv)

fab_deploy_tests/test_project3/test_project3/__init__.py

Empty file added.

fab_deploy_tests/test_project3/test_project3/config.py

+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': 'testdb.sqlite',
+    }
+}
+INSTANCE_NAME = 'local'

fab_deploy_tests/test_project3/test_project3/config.server.py

+# my_project/config.server.py
+# config file for environment-specific settings
+
+DEBUG = True
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3', # TODO: postgres
+        'NAME': '{{ DB_NAME }}.sqlite',
+    }
+}
+INSTANCE_NAME = '{{ INSTANCE_NAME }}'
+{{ EXTRA }}

fab_deploy_tests/test_project3/test_project3/config_templates/apache.config

+NameVirtualHost 127.0.0.1:{{ APACHE_PORT }}
+<VirtualHost 127.0.0.1:{{ APACHE_PORT }}>
+    ServerName {{ SERVER_NAME }}
+    ServerAlias www.{{ SERVER_NAME }}
+    ServerAdmin {{ SERVER_ADMIN }}
+
+    WSGIDaemonProcess {{ INSTANCE_NAME }} user={{ USER }} group={{ USER }} processes={{ PROCESSES }} threads={{ THREADS }}
+    WSGIProcessGroup {{ INSTANCE_NAME }}
+
+    WSGIScriptAlias / {{ ENV_DIR }}/var/wsgi/{{ INSTANCE_NAME }}.py
+    <Directory {{ ENV_DIR }}/var/wsgi/>
+        Order deny,allow
+        allow from all
+    </Directory>
+
+    ErrorLog /var/log/apache2/{{ INSTANCE_NAME }}-error.log
+    ErrorDocument 500 {{ PROJECT_DIR }}/templates/500.html
+
+    # Possible values include: debug, info, notice, warn, error, crit, alert, emerg
+    LogLevel error
+</VirtualHost>

fab_deploy_tests/test_project3/test_project3/config_templates/django_wsgi.py

+import os
+import sys
+import site
+
+# prevent errors with 'print' commands
+sys.stdout = sys.stderr
+
+# adopted from http://code.google.com/p/modwsgi/wiki/VirtualEnvironments
+def add_to_path(dirs):
+    # Remember original sys.path.
+    prev_sys_path = list(sys.path)
+
+    # Add each new site-packages directory.
+    for directory in dirs:
+        site.addsitedir(directory)
+
+    # Reorder sys.path so new directories at the front.
+    new_sys_path = []
+    for item in list(sys.path):
+        if item not in prev_sys_path:
+            new_sys_path.append(item)
+            sys.path.remove(item)
+    sys.path[:0] = new_sys_path
+
+add_to_path([
+     os.path.normpath('{{ ENV_DIR }}/lib/python2.5/site-packages'),
+     os.path.normpath('{{ ENV_DIR }}/lib/python2.6/site-packages'),
+     os.path.normpath('{{ ENV_DIR }}/lib/python2.7/site-packages'),
+     '{{ PROJECT_DIR }}',
+])
+
+from test_project3.wsgi import application

fab_deploy_tests/test_project3/test_project3/config_templates/nginx.config

+server {
+    listen 80;
+    server_name {{ SERVER_NAME }};
+    access_log /var/log/nginx/{{ INSTANCE_NAME }}.access.log;
+    charset utf-8;
+    client_max_body_size 8m;
+
+    gzip_types text/plain text/xml text/css application/javascript application/x-javascript application/json;
+
+    location / {
+        proxy_pass http://localhost:{{ APACHE_PORT }};
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    }
+
+    # change /static to your static folder name
+    location /static {
+        root {{ PROJECT_DIR }};
+        autoindex off;
+        expires 1M;
+    }
+
+    #error_page  404  /404.html;
+
+    # redirect server error pages to the static page /50x.html
+    error_page   500 502 503 504  /50x.html;
+    location = /50x.html {
+        root   /var/www/nginx-default;
+    }
+}
+
+server {
+    listen 80;
+    server_name www.{{ SERVER_NAME }};
+    rewrite ^(.*)$ http://{{ SERVER_NAME }}$1 permanent;
+}
+
+# uncomment the following in order to deny all requests with unmatched server_name;
+# for nginx >= 0.8.21 replace 'default' with 'default_server'
+
+# server {
+#     listen       80  default;
+#     server_name  _;
+#     return       444;
+# }

fab_deploy_tests/test_project3/test_project3/reqs/active.txt

+-r all.txt

fab_deploy_tests/test_project3/test_project3/reqs/all.txt

+# django 1.4 svn
+-e svn+http://code.djangoproject.com/svn/django/trunk@17606#egg=django

fab_deploy_tests/test_project3/test_project3/settings.py

+# Django settings for test_project3 project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+    # ('Your Name', 'your_email@example.com'),
+)
+
+MANAGERS = ADMINS
+
+from config import *
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale.
+USE_L10N = True
+
+# If you set this to False, Django will not use timezone-aware datetimes.
+USE_TZ = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+MEDIA_URL = ''
+
+# Absolute path to the directory static files should be collected to.
+# Don't put anything in this directory yourself; store your static files
+# in apps' "static/" subdirectories and in STATICFILES_DIRS.
+# Example: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = ''
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+# Additional locations of static files
+STATICFILES_DIRS = (
+    # Put strings here, like "/home/html/static" or "C:/www/django/static".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+)
+
+# List of finder classes that know how to find static files in
+# various locations.
+STATICFILES_FINDERS = (
+    'django.contrib.staticfiles.finders.FileSystemFinder',
+    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
+)
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'ok3%3r+q*dls@(0lf01f7s#d4l%o!(@v(2u1&amp;np7#x0n&amp;@8&amp;+g'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.Loader',
+    'django.template.loaders.app_directories.Loader',
+#     'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+    'django.middleware.common.CommonMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    # Uncomment the next line for simple clickjacking protection:
+    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+)
+
+ROOT_URLCONF = 'test_project3.urls'
+
+# Python dotted path to the WSGI application used by Django's runserver.
+WSGI_APPLICATION = 'test_project3.wsgi.application'
+
+TEMPLATE_DIRS = (
+    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+)
+
+INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    # Uncomment the next line to enable the admin:
+    'django.contrib.admin',
+    # Uncomment the next line to enable admin documentation:
+    # 'django.contrib.admindocs',
+)
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error when DEBUG=False.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': False,
+    'filters': {
+        'require_debug_false': {
+            '()': 'django.utils.log.RequireDebugFalse'
+        }
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'filters': ['require_debug_false'],
+            'class': 'django.utils.log.AdminEmailHandler'
+        }
+    },
+    'loggers': {
+        'django.request': {
+            'handlers': ['mail_admins'],
+            'level': 'ERROR',
+            'propagate': True,
+        },
+    }
+}

fab_deploy_tests/test_project3/test_project3/urls.py

+from django.conf.urls import patterns, include, url
+from django.http import HttpResponse
+from django.conf import settings
+
+from django.contrib import admin
+admin.autodiscover()
+
+urlpatterns = patterns('',
+    (r'^admin/', include(admin.site.urls)),
+    (r'^instance/', lambda r: HttpResponse(settings.INSTANCE_NAME)),
+)

fab_deploy_tests/test_project3/test_project3/wsgi.py

+"""
+WSGI config for test_project3 project.
+
+This module contains the WSGI application used by Django's development server
+and any production WSGI deployments. It should expose a module-level variable
+named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
+this application via the ``WSGI_APPLICATION`` setting.
+
+Usually you will have the standard Django WSGI application here, but it also
+might make sense to replace the whole Django WSGI application with a custom one
+that later delegates to the Django one. For example, you could introduce WSGI
+middleware here, or combine a Django application with an application of another
+framework.
+
+"""
+import os
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project3.settings")
+
+# This application object is used by any WSGI server configured to use this
+# file. This includes Django's development server, if the WSGI_APPLICATION
+# setting points here.
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()
+
+# Apply WSGI middleware here.
+# from helloworld.wsgi import HelloWorldApplication
+# application = HelloWorldApplication(application)

fab_deploy_tests/tests/deploy.py

 from ..utils import setup_ssh, setup_sudo
 from ..test_project.fabfile import foo_site, bar_site, invalid_site
 from ..test_project2.fabfile import foo_site as foo_site2
+from ..test_project3.fabfile import baz_site
 
 def get_file_content(remote_file):
     @run_as('root')
         fab(deploy_project)
         fab(my_push)
         self.assertTrue(before_restart.called)
+
+
+class Django14LayoutDeployTest(FabDeployProjectTest):
+    project = 'test_project3'
+
+    def test_deploy(self):
+        url = 'http://baz.example.com/instance/'
+        fab(baz_site)
+
+        setup_sudo()
+        setup_ssh()
+        fab(deploy_project)
+        self.assertResponse(url, 'baz')