From af8b9e974cb56cf61822d777a8a98d17aef71955 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Fri, 29 Jan 2016 16:57:48 +0100 Subject: [PATCH 01/29] Start next development iteration This commit moves the version number to gvaldap's __init__.py, bumps the copyright year and starts a new development iteration. The docs/conf.py is synchronized with the gva project's version of that file. --- docs/conf.py | 19 ++++++++++--------- gvaldap/gvaldap/__init__.py | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index b2d2cf9..1553fb0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,13 +35,13 @@ django.setup() # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['releases', 'sphinx.ext.autodoc', 'celery.contrib.sphinx'] +# configuration for releases extension +releases_issue_uri = 'https://dev.gnuviech-server.de/gvaldap/ticket/%s' +releases_release_uri = 'https://dev.gnuviech-server.de/gvaldap/browser/?rev=%s' + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] -releases_issue_uri = 'https://dev.gnuviech-server.de/gvaldap/ticket/%s' - -releases_release_uri = 'https://dev.gnuviech-server.de/gvaldap/milestone/%s' - # The suffix of source filenames. source_suffix = '.rst' @@ -53,16 +53,17 @@ master_doc = 'index' # General information about the project. project = u'gvaldap' -copyright = u'2014, 2015 Jan Dittberner' +copyright = u'2014, 2015, 2016 Jan Dittberner' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. -version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.2' +from gvaldap import __version__ as release + +# The short X.Y version. +version = ".".join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -103,7 +104,7 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the diff --git a/gvaldap/gvaldap/__init__.py b/gvaldap/gvaldap/__init__.py index 62a61ef..613629e 100644 --- a/gvaldap/gvaldap/__init__.py +++ b/gvaldap/gvaldap/__init__.py @@ -1,3 +1,4 @@ """ This is the gvaldap project module. """ +__version__ = "0.6.0.dev1" From 6a8997e95067fc9d2a1a97b53d6653b879fe2bb7 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Fri, 29 Jan 2016 23:26:57 +0100 Subject: [PATCH 02/29] Add initial Vagrant/Saltstack setup This commit adds an initial Vagrant and Saltstack setup that reuses the same configuration as that of the gva repository. The LDAP server itself is not configured yet. --- .gitignore | 1 + Vagrantfile | 68 ++++++++++ salt/bootstrap.sh | 31 +++++ salt/grains | 0 salt/minion | 11 ++ salt/pillar/gnuviechadmin/database.sls | 8 ++ salt/pillar/gnuviechadmin/database/common.sls | 5 + salt/pillar/gnuviechadmin/gvaldap.sls | 8 ++ salt/pillar/gnuviechadmin/init.sls | 16 +++ salt/pillar/gnuviechadmin/queues.sls | 77 ++++++++++++ salt/pillar/gnuviechadmin/queues/cli.sls | 7 ++ salt/pillar/gnuviechadmin/queues/common.sls | 3 + salt/pillar/gnuviechadmin/queues/gva.sls | 5 + salt/pillar/gnuviechadmin/queues/gvafile.sls | 5 + salt/pillar/gnuviechadmin/queues/gvaldap.sls | 5 + salt/pillar/gnuviechadmin/queues/gvamysql.sls | 5 + salt/pillar/gnuviechadmin/queues/gvapgsql.sls | 5 + salt/pillar/gnuviechadmin/queues/gvaweb.sls | 5 + salt/pillar/gnuviechadmin/webinterface.sls | 9 ++ salt/pillar/top.sls | 8 ++ salt/roots/_states/rsa_key.py | 117 ++++++++++++++++++ salt/roots/_states/x509_certificate.py | 61 +++++++++ salt/roots/base/bash_functions | 25 ++++ salt/roots/base/bashrc | 117 ++++++++++++++++++ salt/roots/base/init.sls | 30 +++++ salt/roots/base/screenrc | 14 +++ salt/roots/gnuviechadmin/base.sls | 98 +++++++++++++++ salt/roots/gnuviechadmin/bash_functions | 25 ++++ salt/roots/gnuviechadmin/celery.sls | 13 ++ salt/roots/gnuviechadmin/database.sls | 33 +++++ .../gnuviechadmin/gva/gnuviechadmin.nginx | 27 ++++ salt/roots/gnuviechadmin/gva/settings.sh | 24 ++++ salt/roots/gnuviechadmin/gvaldap.sls | 11 ++ .../roots/gnuviechadmin/gvaldap/run_celery.sh | 7 ++ salt/roots/gnuviechadmin/gvaldap/settings.sh | 14 +++ salt/roots/gnuviechadmin/queues.sls | 30 +++++ salt/roots/gnuviechadmin/vars.sls | 7 ++ salt/roots/gnuviechadmin/webinterface.sls | 39 ++++++ salt/roots/nginx/init.sls | 38 ++++++ salt/roots/nginx/nginx.conf | 49 ++++++++ salt/roots/postgresql-server/init.sls | 9 ++ salt/roots/rabbitmq-server/init.sls | 17 +++ salt/roots/top.sls | 11 ++ salt/roots/vim/init.sls | 15 +++ salt/roots/vim/vimrc | 34 +++++ salt/roots/webserver/init.sls | 50 ++++++++ salt/roots/webserver/nginx-logformat.conf | 4 + salt/roots/webserver/nginx-security.conf | 19 +++ salt/roots/webserver/nginx-ssl.conf | 15 +++ salt/roots/webserver/sslcert.macros.sls | 30 +++++ 50 files changed, 1265 insertions(+) create mode 100644 Vagrantfile create mode 100755 salt/bootstrap.sh create mode 100644 salt/grains create mode 100644 salt/minion create mode 100644 salt/pillar/gnuviechadmin/database.sls create mode 100644 salt/pillar/gnuviechadmin/database/common.sls create mode 100644 salt/pillar/gnuviechadmin/gvaldap.sls create mode 100644 salt/pillar/gnuviechadmin/init.sls create mode 100644 salt/pillar/gnuviechadmin/queues.sls create mode 100644 salt/pillar/gnuviechadmin/queues/cli.sls create mode 100644 salt/pillar/gnuviechadmin/queues/common.sls create mode 100644 salt/pillar/gnuviechadmin/queues/gva.sls create mode 100644 salt/pillar/gnuviechadmin/queues/gvafile.sls create mode 100644 salt/pillar/gnuviechadmin/queues/gvaldap.sls create mode 100644 salt/pillar/gnuviechadmin/queues/gvamysql.sls create mode 100644 salt/pillar/gnuviechadmin/queues/gvapgsql.sls create mode 100644 salt/pillar/gnuviechadmin/queues/gvaweb.sls create mode 100644 salt/pillar/gnuviechadmin/webinterface.sls create mode 100644 salt/pillar/top.sls create mode 100644 salt/roots/_states/rsa_key.py create mode 100644 salt/roots/_states/x509_certificate.py create mode 100644 salt/roots/base/bash_functions create mode 100644 salt/roots/base/bashrc create mode 100644 salt/roots/base/init.sls create mode 100644 salt/roots/base/screenrc create mode 100644 salt/roots/gnuviechadmin/base.sls create mode 100644 salt/roots/gnuviechadmin/bash_functions create mode 100644 salt/roots/gnuviechadmin/celery.sls create mode 100644 salt/roots/gnuviechadmin/database.sls create mode 100644 salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx create mode 100644 salt/roots/gnuviechadmin/gva/settings.sh create mode 100644 salt/roots/gnuviechadmin/gvaldap.sls create mode 100644 salt/roots/gnuviechadmin/gvaldap/run_celery.sh create mode 100644 salt/roots/gnuviechadmin/gvaldap/settings.sh create mode 100644 salt/roots/gnuviechadmin/queues.sls create mode 100644 salt/roots/gnuviechadmin/vars.sls create mode 100644 salt/roots/gnuviechadmin/webinterface.sls create mode 100644 salt/roots/nginx/init.sls create mode 100644 salt/roots/nginx/nginx.conf create mode 100644 salt/roots/postgresql-server/init.sls create mode 100644 salt/roots/rabbitmq-server/init.sls create mode 100644 salt/roots/top.sls create mode 100644 salt/roots/vim/init.sls create mode 100644 salt/roots/vim/vimrc create mode 100644 salt/roots/webserver/init.sls create mode 100644 salt/roots/webserver/nginx-logformat.conf create mode 100644 salt/roots/webserver/nginx-security.conf create mode 100644 salt/roots/webserver/nginx-ssl.conf create mode 100644 salt/roots/webserver/sslcert.macros.sls diff --git a/.gitignore b/.gitignore index f2aee66..fcd5c5c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ Desktop.ini .ropeproject _build/ +.vagrant/ diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..e94f761 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,68 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure(2) do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://atlas.hashicorp.com/search. + config.vm.box = "debian/jessie64" + + config.vm.hostname = "gvaldap.local" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + config.vm.network "forwarded_port", guest: 8000, host: 8001 + + # Create a private network, which allows host-only access to the machine + # using a specific IP. + # config.vm.network "private_network", ip: "192.168.33.10" + config.vm.network "private_network", ip: "172.16.3.3" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + # config.vm.network "public_network" + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + config.vm.synced_folder "salt/roots/", "/srv/salt/" + config.vm.synced_folder "salt/pillar/", "/srv/pillar/" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + config.vm.provider "virtualbox" do |vb| + # # Display the VirtualBox GUI when booting the machine + # vb.gui = true + # + # # Customize the amount of memory on the VM: + vb.memory = "512" + end + + config.vm.provision :salt do |salt| + salt.bootstrap_script = "salt/bootstrap.sh" + salt.minion_id = "gvadev" + salt.masterless = true + salt.run_highstate = true + salt.verbose = true + salt.colorize = true + salt.log_level = "warning" + end +end diff --git a/salt/bootstrap.sh b/salt/bootstrap.sh new file mode 100755 index 0000000..f6ef8b3 --- /dev/null +++ b/salt/bootstrap.sh @@ -0,0 +1,31 @@ +#!/bin/sh - + +# We just download the bootstrap script by default and execute that. +if [ -x /usr/bin/fetch ]; then + /usr/bin/fetch -o - https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.sh | sh -s -- "$@" +elif [ -x /usr/bin/curl ]; then + /usr/bin/curl -L https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.sh | sh -s -- "$@" +else + python \ + -c 'import urllib; print urllib.urlopen("https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.sh").read()' \ + | sh -s -- "$@" +fi + +cat >/etc/salt/minion </etc/salt/grains < +''' + +from M2Crypto import X509 +from datetime import datetime +import os + + +def _error(ret, err_msg): + ret['result'] = False + ret['comment'] = err_msg + return ret + + +def valid_certificate( + name, mindays=14, keyfile=None, + checkchain=False, trustedcerts=None): + ''' + Checks whether the given certificate file is valid. + + name + The name of the certificate file to check + mindays + Mark the certificate as invalid if it is valid for less then this many + days + ''' + ret = { + 'name': name, + 'changes': {}, + 'result': None, + 'comment': ''} + if not os.path.isfile(name): + return _error( + ret, 'certificate file {0} does not exist'.format(name)) + try: + cert = X509.load_cert(name) + except Exception as e: + return _error( + ret, + 'error loading certificate {0}: {1}'.format(name, e)) + notafter = cert.get_not_after().get_datetime() + delta = notafter - datetime.now(notafter.tzinfo) + if delta.days < mindays: + return _error( + ret, + 'certificate {0} is only valid for {1} more day(s)'.format( + name, delta.days)) + # TODO: check keyfile match + # TODO: check trust chain + ret['comment'] = ( + 'certificate {0} is ok and still valid for {1} days'.format( + name, delta.days)) + ret['result'] = True + return ret diff --git a/salt/roots/base/bash_functions b/salt/roots/base/bash_functions new file mode 100644 index 0000000..00658d6 --- /dev/null +++ b/salt/roots/base/bash_functions @@ -0,0 +1,25 @@ +#!/bin/bash + +function devenv +{ + . $HOME/gvasettings.sh + . {{ venv }}/bin/activate + cd {{ appdir }} +} + +function testenv +{ + devenv + export DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE%%.local}.test +} + +function settitle +{ + if [ -n "$STY" ] ; then # We are in a screen session + echo "Setting screen titles to $@" + printf "\033k%s\033\\" "$@" + screen -X eval "at \\# title $@" "shelltitle $@" + else + printf "\033]0;%s\007" "$@" + fi +} diff --git a/salt/roots/base/bashrc b/salt/roots/base/bashrc new file mode 100644 index 0000000..4bc2a9f --- /dev/null +++ b/salt/roots/base/bashrc @@ -0,0 +1,117 @@ +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + +# don't put duplicate lines or lines starting with space in the history. +# See bash(1) for more options +HISTCONTROL=ignoreboth + +# append to the history file, don't overwrite it +shopt -s histappend + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# If set, the pattern "**" used in a pathname expansion context will +# match all files and zero or more directories and subdirectories. +#shopt -s globstar + +# make less more friendly for non-text input files, see lesspipe(1) +#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, unless we know we "want" color) +case "$TERM" in + xterm-color) color_prompt=yes;; +esac + +# uncomment for a colored prompt, if the terminal has the capability; turned +# off by default to not distract the user: the focus in a terminal window +# should be on the output of commands, not on the prompt +#force_color_prompt=yes + +if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + # We have color support; assume it's compliant with Ecma-48 + # (ISO/IEC-6429). (Lack of such support is extremely rare, and such + # a case would tend to support setf rather than setaf.) + color_prompt=yes + else + color_prompt= + fi +fi + +if [ "$color_prompt" = yes ]; then + PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' +else + PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' +fi +unset color_prompt force_color_prompt + +# If this is an xterm set the title to user@host:dir +case "$TERM" in +xterm*|rxvt*) + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" + ;; +*) + ;; +esac + +# enable color support of ls and also add handy aliases +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + #alias dir='dir --color=auto' + #alias vdir='vdir --color=auto' + + #alias grep='grep --color=auto' + #alias fgrep='fgrep --color=auto' + #alias egrep='egrep --color=auto' +fi + +# colored GCC warnings and errors +#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' + +# some more ls aliases +#alias ll='ls -l' +#alias la='ls -A' +#alias l='ls -CF' + +# Alias definitions. +# You may want to put all your additions into a separate file like +# ~/.bash_aliases, instead of adding them here directly. +# See /usr/share/doc/bash-doc/examples in the bash-doc package. + +if [ -f ~/.bash_aliases ]; then + . ~/.bash_aliases +fi + +# enable programmable completion features (you don't need to enable +# this, if it's already enabled in /etc/bash.bashrc and /etc/profile +# sources /etc/bash.bashrc). +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi + +if [ -f ~/.bash_functions ]; then + . ~/.bash_functions +fi diff --git a/salt/roots/base/init.sls b/salt/roots/base/init.sls new file mode 100644 index 0000000..3b896aa --- /dev/null +++ b/salt/roots/base/init.sls @@ -0,0 +1,30 @@ +base-packages: + pkg.installed: + - pkgs: + - screen + - htop + - git + +/home/vagrant/.screenrc: + file.managed: + - user: vagrant + - group: vagrant + - mode: 0644 + - source: salt://base/screenrc + +update-system: + pkg.uptodate: + - refresh: True + +/home/vagrant/bin: + file.directory: + - user: vagrant + - group: vagrant + - mode: 0750 + +/home/vagrant/.bashrc: + file.managed: + - user: vagrant + - group: vagrant + - mode: 0644 + - source: salt://base/bashrc diff --git a/salt/roots/base/screenrc b/salt/roots/base/screenrc new file mode 100644 index 0000000..a555c1e --- /dev/null +++ b/salt/roots/base/screenrc @@ -0,0 +1,14 @@ +# vim: syntax=screen + +hardstatus on +hardstatus alwayslastline +hardstatus string "%{= r}[ %{G}%H%{= r} ] %= %{=b b}%-w%{=rb db}%>%n %t%{-}%+w %=%{= r} [ %{G}%c %{M}%D %m-%d %{r}]" + +startup_message off + +defscrollback 10240 + +bind f eval "caption splitonly" "hardstatus ignore" +bind F eval "caption always" "hardstatus alwayslastline" + +defbce "on" diff --git a/salt/roots/gnuviechadmin/base.sls b/salt/roots/gnuviechadmin/base.sls new file mode 100644 index 0000000..b0e8ccb --- /dev/null +++ b/salt/roots/gnuviechadmin/base.sls @@ -0,0 +1,98 @@ +{% from 'gnuviechadmin/vars.sls' import home, gva_component, gva_amqp_user, checkout, appdir, venv %} + +gva.local: + host.present: + - ip: 172.16.3.2 + - names: + - mq + - gva.local + +gvaldap.local: + host.present: + - ip: 172.16.3.3 + +gvafile.local: + host.present: + - ip: 172.16.3.4 + +gvaweb.local: + host.present: + - ip: 172.16.3.5 + +gvamysql.local: + host.present: + - ip: 172.16.3.6 + +gvapgsql.local: + host.present: + - ip: 172.16.3.7 + +gnuviechadmin-packages: + pkg.installed: + - pkgs: + - libyaml-dev + - python-virtualenv + - python-dev + - python-pip + - gettext + +{{ home }}/gvasettings.sh: + file.managed: + - user: vagrant + - group: vagrant + - mode: 0640 + - source: salt://gnuviechadmin/{{ gva_component }}/settings.sh + - template: jinja + - context: + broker_url: {{ 'amqp://%s:%s@mq/%s' % (gva_amqp_user, salt['pillar.get']('gnuviechadmin:queues:users:%s:password' % gva_amqp_user), salt['pillar.get']('gnuviechadmin:queues:vhost')) }} + +gnuviechadmin-venv: + cmd.run: + - name: virtualenv {{ venv }} + - user: vagrant + - group: vagrant + - unless: test -f {{ venv }}/bin/pip + +gnuviechadmin-requires: + cmd.run: + - name: {{ venv }}/bin/pip install -U -r requirements/local.txt && touch {{ venv }}/lastinstall + - user: vagrant + - group: vagrant + - cwd: {{ checkout }} + - require: + - cmd: gnuviechadmin-venv + - pkg: gnuviechadmin-packages + - unless: test -e {{ venv }}/lastinstall && test {{ checkout }}/requirements/local.txt -ot {{ venv }}/lastinstall && test {{ checkout }}/requirements/base.txt -ot {{ venv }}/lastinstall + +gnuviechadmin-dbschema: + cmd.wait: + - name: . {{ home }}/gvasettings.sh ; unset LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME ; {{ venv }}/bin/python manage.py migrate --noinput + - user: vagrant + - group: vagrant + - cwd: {{ appdir }} + - watch: + - cmd: gnuviechadmin-requires + - file: {{ home }}/gvasettings.sh + +gnuviechadmin-locale-data-compile: + cmd.wait: + - name: . {{ home }}/gvasettings.sh ; {{ venv }}/bin/python {{ appdir }}/manage.py compilemessages + - user: vagrant + - group: vagrant + - cwd: {{ appdir }} + - require: + - pkg: gnuviechadmin-packages + - file: {{ home }}/gvasettings.sh + - cmd: gnuviechadmin-venv + +/home/vagrant/.bash_functions: + file.managed: + - user: vagrant + - group: vagrant + - mode: 0644 + - source: salt://base/bash_functions + - template: jinja + - context: + home: {{ home }} + venv: {{ venv }} + appdir: {{ appdir }} diff --git a/salt/roots/gnuviechadmin/bash_functions b/salt/roots/gnuviechadmin/bash_functions new file mode 100644 index 0000000..2c7fd41 --- /dev/null +++ b/salt/roots/gnuviechadmin/bash_functions @@ -0,0 +1,25 @@ +#!/bin/bash + +function devenv +{ + . $HOME/gvasettings.sh + . $HOME/gva-venv/bin/activate + cd /vagrant/gnuviechadmin +} + +function testenv +{ + devenv + export DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE%%.local}.test +} + +function settitle +{ + if [ -n "$STY" ] ; then # We are in a screen session + echo "Setting screen titles to $@" + printf "\033k%s\033\\" "$@" + screen -X eval "at \\# title $@" "shelltitle $@" + else + printf "\033]0;%s\007" "$@" + fi +} diff --git a/salt/roots/gnuviechadmin/celery.sls b/salt/roots/gnuviechadmin/celery.sls new file mode 100644 index 0000000..b27b504 --- /dev/null +++ b/salt/roots/gnuviechadmin/celery.sls @@ -0,0 +1,13 @@ +{% from 'gnuviechadmin/vars.sls' import home, gva_component, venv, appdir %} + +{{ home }}/bin/run_celery.sh: + file.managed: + - user: vagrant + - group: vagrant + - mode: 0750 + - source: salt://gnuviechadmin/{{ gva_component }}/run_celery.sh + - template: jinja + - context: + home: {{ home }} + virtualenv: {{ venv }} + appdir: {{ appdir }} diff --git a/salt/roots/gnuviechadmin/database.sls b/salt/roots/gnuviechadmin/database.sls new file mode 100644 index 0000000..ab57c2a --- /dev/null +++ b/salt/roots/gnuviechadmin/database.sls @@ -0,0 +1,33 @@ +include: + - postgresql-server + +gnuviechadmin-database: + postgres_user.present: + - name: {{ salt['pillar.get']('gnuviechadmin:database:owner:user') }} + - user: postgres + - password: {{ salt['pillar.get']('gnuviechadmin:database:owner:password') }} + - login: True + - createdb: {% if salt['pillar.get']('gnuviechadmin:deploymenttype', 'production') == 'local' %}True +{%- else %}False +{%- endif %} + - require: + - service: postgresql + postgres_database.present: + - name: {{ salt['pillar.get']('gnuviechadmin:database:name') }} + - user: postgres + - owner: {{ salt['pillar.get']('gnuviechadmin:database:owner:user') }} + - encoding: UTF8 + - template: template0 + - require: + - service: postgresql + - postgres_user: {{ salt['pillar.get']('gnuviechadmin:database:owner:user') }} + +{% for gnuviechadmin_db_role in salt['pillar.get']('gnuviechadmin:database:users') %} +gnuviechadmin-dbuser-{{ gnuviechadmin_db_role }}: + postgres_user.present: + - name: {{ salt['pillar.get']('gnuviechadmin:database:users:%s:user' % gnuviechadmin_db_role) }} + - password: {{ salt['pillar.get']('gnuviechadmin:database:users:%s:password' % gnuviechadmin_db_role) }} + - login: True + - require: + - service: postgresql +{% endfor %} diff --git a/salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx b/salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx new file mode 100644 index 0000000..d5768bd --- /dev/null +++ b/salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx @@ -0,0 +1,27 @@ +server { + server_name www.{{ domainname }}; + listen 443 ssl; + + ssl_certificate {{ ssl_certdir }}/{{ domainname }}.crt.pem; + ssl_certificate_key {{ ssl_keydir }}/{{ domainname }}.key.pem; + + if ( $host != '{{ domainname }}') { + return 301 https://{{ domainname }}$request_uri; + } + + client_max_body_size 1M; + gzip on; + gzip_types text/javascript application/x-javascript text/css; + + location /media { + alias /vagrant/gnuviechadmin/media; + } + + location /static { + alias /vagrant/gnuviechadmin/assets; + } + + location / { + proxy_pass http://localhost:8000; + } +} diff --git a/salt/roots/gnuviechadmin/gva/settings.sh b/salt/roots/gnuviechadmin/gva/settings.sh new file mode 100644 index 0000000..60bbb98 --- /dev/null +++ b/salt/roots/gnuviechadmin/gva/settings.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +export DJANGO_SETTINGS_MODULE="gnuviechadmin.settings.{{ salt['pillar.get']('gnuviechadmin:deploymenttype', 'production') }}" +export GVA_ADMIN_NAME="Jan Dittberner" +export GVA_ADMIN_EMAIL="{{ salt['pillar.get']('gnuviechadmin:adminemail') }}" +export GVA_PGSQL_DATABASE="{{ salt['pillar.get']('gnuviechadmin:database:name') }}" +export GVA_PGSQL_USER="{{ salt['pillar.get']('gnuviechadmin:database:owner:user') }}" +export GVA_PGSQL_PASSWORD="{{ salt['pillar.get']('gnuviechadmin:database:owner:password') }}" +export GVA_PGSQL_HOSTNAME="{{ salt['pillar.get']('gnuviechadmin:database:host') }}" +export GVA_PGSQL_PORT={{ salt['pillar.get']('gnuviechadmin:database:port') }} +export GVA_DOMAIN_NAME="{{ salt['pillar.get']('gnuviechadmin:domainname') }}" +export GVA_SITE_NAME="{{ salt['pillar.get']('gnuviechadmin:sitename') }}" +export GVA_SITE_SECRET="{{ salt['grains.get_or_set_hash']('gnuviechadmin:SECRET_KEY', 50) }}" +export GVA_SITE_ADMINMAIL="{{ salt['pillar.get']('gnuviechadmin:adminemail') }}" +export GVA_MIN_OS_UID={{ salt['pillar.get']('gnuviechadmin:minosuid') }} +export GVA_MIN_OS_GID={{ salt['pillar.get']('gnuviechadmin:minosgid') }} +export GVA_OSUSER_PREFIX="{{ salt['pillar.get']('gnuviechadmin:osuserprefix') }}" +export GVA_OSUSER_HOME_BASEPATH="{{ salt['pillar.get']('gnuviechadmin:osuserhomedirbase') }}" +export GVA_OSUSER_DEFAULT_SHELL="{{ salt['pillar.get']('gnuviechadmin:osuserdefaultshell') }}" +export GVA_BROKER_URL="{{ broker_url }}" +export GVA_OSUSER_UPLOADSERVER="{{ salt['pillar.get']('gnuviechadmin:uploadserver') }}" +export GVA_WEBMAIL_URL="{{ salt['pillar.get']('gnuviechadmin:webmail_url') }}" +export GVA_PHPMYADMIN_URL="{{ salt['pillar.get']('gnuviechadmin:phpmyadmin_url') }}" +export GVA_PHPPGADMIN_URL="{{ salt['pillar.get']('gnuviechadmin:phppgadmin_url') }}" diff --git a/salt/roots/gnuviechadmin/gvaldap.sls b/salt/roots/gnuviechadmin/gvaldap.sls new file mode 100644 index 0000000..f600b9f --- /dev/null +++ b/salt/roots/gnuviechadmin/gvaldap.sls @@ -0,0 +1,11 @@ +include: + - gnuviechadmin.base + - gnuviechadmin.celery + +gvaldap-packages: + pkg.installed: + - pkgs: + - libldap2-dev + - libsasl2-dev + - require_in: + - pkg: gnuviechadmin-packages diff --git a/salt/roots/gnuviechadmin/gvaldap/run_celery.sh b/salt/roots/gnuviechadmin/gvaldap/run_celery.sh new file mode 100644 index 0000000..eac31c8 --- /dev/null +++ b/salt/roots/gnuviechadmin/gvaldap/run_celery.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -ex + +. {{ home }}/gvasettings.sh +cd {{ appdir }} +{{ virtualenv }}/bin/celery worker -A gvaldap -Q ldap --loglevel=INFO diff --git a/salt/roots/gnuviechadmin/gvaldap/settings.sh b/salt/roots/gnuviechadmin/gvaldap/settings.sh new file mode 100644 index 0000000..e99308c --- /dev/null +++ b/salt/roots/gnuviechadmin/gvaldap/settings.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +export DJANGO_SETTINGS_MODULE="gvaldap.settings.{{ salt['pillar.get']('gnuviechadmin:deploymenttype', 'production') }}" +export GVALDAP_ADMIN_NAME="Jan Dittberner" +export GVALDAP_ADMIN_EMAIL="{{ salt['pillar.get']('gnuviechadmin-gvaldap:admin_email') }}" +export GVALDAP_LDAP_URL="{{ salt['pillar.get']('gnuviechadmin-gvaldap:ldap_url') }}" +export GVALDAP_LDAP_USER="{{ salt['pillar.get']('gnuviechadmin-gvaldap:ldap_user') }}" +export GVALDAP_LDAP_PASSWORD="{{ salt['pillar.get']('gnuviechadmin-gvaldap:ldap_password' ) }}" +export GVALDAP_BASEDN_GROUP="{{ salt['pillar.get']('gnuviechadmin-gvaldap:basedn_group') }}" +export GVALDAP_BASEDN_USER="{{ salt['pillar.get']('gnuviechadmin-gvaldap:basedn_user') }}" +export GVALDAP_SECRETKEY="{{ salt['grains.get_or_set_hash']('gnuviechadmin-gvaldap:SECRET_KEY', 50) }}" +export GVALDAP_BROKER_URL="{{ broker_url }}" +export GVALDAP_ALLOWED_HOSTS="{{ salt['pillar.get']('gnuviechadmin-gvaldap:allowed_hosts') }}" +export GVALDAP_SERVER_EMAIL="{{ salt['pillar.get']('gnuviechadmin-gvaldap:server_email') }}" diff --git a/salt/roots/gnuviechadmin/queues.sls b/salt/roots/gnuviechadmin/queues.sls new file mode 100644 index 0000000..5462fb7 --- /dev/null +++ b/salt/roots/gnuviechadmin/queues.sls @@ -0,0 +1,30 @@ +include: + - rabbitmq-server + +gnuviechadmin-queue-vhost: + rabbitmq_vhost.present: + - name: {{ salt['pillar.get']('gnuviechadmin:queues:vhost') }} + +{% for user in salt['pillar.get']('gnuviechadmin:queues:users') %} +gnuviechadmin-queue-user-{{ user }}: + rabbitmq_user.present: + - name: {{ user }} + - password: {{ salt['pillar.get']('gnuviechadmin:queues:users:%s:password' % user) }} +{% if salt['pillar.get']('gnuviechadmin:queues:users:%s:perms' % user) %} + - perms: +{% for vhost, perms in salt['pillar.get']('gnuviechadmin:queues:users:%s:perms' % user).iteritems() %} + - {{ vhost }}: + - {{ perms[0] }} + - {{ perms[1] }} + - {{ perms[2] }} +{% endfor %} +{% endif %} +{% if salt['pillar.get']('gnuviechadmin:queues:users:%s:tags' % user) %} + - tags: +{% for tag in salt['pillar.get']('gnuviechadmin:queues:users:%s:tags' % user) %} + - {{ tag }} +{% endfor %} +{% endif %} + - require: + - rabbitmq_vhost: {{ salt['pillar.get']('gnuviechadmin:queues:vhost') }} +{% endfor %} diff --git a/salt/roots/gnuviechadmin/vars.sls b/salt/roots/gnuviechadmin/vars.sls new file mode 100644 index 0000000..6ad1aa2 --- /dev/null +++ b/salt/roots/gnuviechadmin/vars.sls @@ -0,0 +1,7 @@ +{% set home = '/home/vagrant' %} +{% set venv = home + '/gva-venv' %} +{% set checkout = '/vagrant' %} +{% set gva_component = salt['pillar.get']('gnuviechadmin:component:name') %} +{% set gva_amqp_user = salt['pillar.get']('gnuviechadmin:component:amqp_user') %} +{% set python_module = salt['pillar.get']('gnuviechadmin:component:python_module', gva_component) %} +{% set appdir = checkout + '/' + python_module %} diff --git a/salt/roots/gnuviechadmin/webinterface.sls b/salt/roots/gnuviechadmin/webinterface.sls new file mode 100644 index 0000000..f94c060 --- /dev/null +++ b/salt/roots/gnuviechadmin/webinterface.sls @@ -0,0 +1,39 @@ +include: + - gnuviechadmin.base + - webserver + +libpq-dev: + pkg.installed: + - require_in: + - pkg: gnuviechadmin-packages + +python-m2crypto: + pkg.installed: + - reload_modules: true + +{% import "webserver/sslcert.macros.sls" as sslcert %} + +{% set domainname = salt['pillar.get']('gnuviechadmin:domainname') %} +{{ sslcert.key_cert(domainname) }} + +/etc/nginx/sites-available/{{ domainname }}: + file.managed: + - user: root + - group: root + - mode: 0640 + - source: salt://gnuviechadmin/gva/gnuviechadmin.nginx + - template: jinja + - context: + domainname: {{ domainname }} + ssl_keydir: {{ salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') }} + ssl_certdir: {{ salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') }} + - require: + - pkg: nginx + +/etc/nginx/sites-enabled/{{ domainname }}: + file.symlink: + - target: /etc/nginx/sites-available/{{ domainname }} + - require: + - file: /etc/nginx/sites-available/{{ domainname }} + - watch_in: + - service: nginx diff --git a/salt/roots/nginx/init.sls b/salt/roots/nginx/init.sls new file mode 100644 index 0000000..cd47736 --- /dev/null +++ b/salt/roots/nginx/init.sls @@ -0,0 +1,38 @@ +nginx: + pkg: + - installed + service.running: + - enable: True + - require: + - pkg: nginx + +nginx-common: + pkg.installed + +/etc/nginx/nginx.conf: + file.managed: + - source: salt://nginx/nginx.conf + - user: root + - group: root + - mode: 0644 + - require: + - pkg: nginx-common + - watch_in: + - service: nginx + +{% set nginx_ssl_keydir = salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') %} +{% set nginx_ssl_certdir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} + +{{ nginx_ssl_certdir }}: + file.directory: + - user: root + - group: root + - mode: 0755 + - makedirs: True + +{{ nginx_ssl_keydir }}: + file.directory: + - user: root + - group: root + - mode: 0750 + - makedirs: True diff --git a/salt/roots/nginx/nginx.conf b/salt/roots/nginx/nginx.conf new file mode 100644 index 0000000..dfeb36d --- /dev/null +++ b/salt/roots/nginx/nginx.conf @@ -0,0 +1,49 @@ +user www-data; +worker_processes 4; +pid /run/nginx.pid; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; + + server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + ## + # Gzip Settings + ## + + gzip on; + gzip_disable "msie6"; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} diff --git a/salt/roots/postgresql-server/init.sls b/salt/roots/postgresql-server/init.sls new file mode 100644 index 0000000..f08ace7 --- /dev/null +++ b/salt/roots/postgresql-server/init.sls @@ -0,0 +1,9 @@ +locales-all: + pkg.installed + +postgresql: + pkg: + - installed + service.running: + - require: + - pkg: postgresql diff --git a/salt/roots/rabbitmq-server/init.sls b/salt/roots/rabbitmq-server/init.sls new file mode 100644 index 0000000..6c3c7f6 --- /dev/null +++ b/salt/roots/rabbitmq-server/init.sls @@ -0,0 +1,17 @@ +rabbitmq-server: + pkg: + - installed + service: + - running + - requires: + - pkg: rabbitmq-server + +guest: + rabbitmq_user: + - absent + +rabbitmq_management: + rabbitmq_plugin: + - enabled + - watch_in: + - service: rabbitmq-server diff --git a/salt/roots/top.sls b/salt/roots/top.sls new file mode 100644 index 0000000..7075d53 --- /dev/null +++ b/salt/roots/top.sls @@ -0,0 +1,11 @@ +base: + '*': + - vim + - base +{% if 'roles' in grains %} +{% for role in grains['roles'] %} + 'roles:{{ role }}': + - match: grain + - {{ role }} +{% endfor %} +{% endif %} diff --git a/salt/roots/vim/init.sls b/salt/roots/vim/init.sls new file mode 100644 index 0000000..fa234e3 --- /dev/null +++ b/salt/roots/vim/init.sls @@ -0,0 +1,15 @@ +vim-nox: + pkg.installed + +editor: + alternatives.set: + - path: /usr/bin/vim.nox + - require: + - pkg: vim-nox + +/home/vagrant/.vimrc: + file.managed: + - user: vagrant + - group: vagrant + - mode: 0644 + - source: salt://vim/vimrc diff --git a/salt/roots/vim/vimrc b/salt/roots/vim/vimrc new file mode 100644 index 0000000..931195b --- /dev/null +++ b/salt/roots/vim/vimrc @@ -0,0 +1,34 @@ +syntax on + +set showcmd +set modeline +set modelines=3 +set expandtab +set shiftwidth=4 +set autoindent +set smarttab +set ruler +set list listchars=tab:▷⋅,trail:⋅,nbsp:⋅ +set cpoptions+=$ +set hlsearch +set virtualedit=all +set guioptions-=T +set guioptions-=m +set wildmenu +set complete=.,w,b,u,t +set number + +filetype plugin indent on + +autocmd BufNewFile,BufRead *.sls set filetype=yaml + +autocmd FileType make set noexpandtab +autocmd FileType python set tabstop=4 shiftwidth=4 autoindent smartindent textwidth=79 +autocmd FileType html set tabstop=2 shiftwidth=2 textwidth=200 smartindent autoindent +autocmd FileType htmldjango set tabstop=2 shiftwidth=2 textwidth=200 +autocmd FileType moin set tabstop=2 shiftwidth=2 +autocmd FileType rst set textwidth=79 +autocmd FileType yaml set tabstop=2 shiftwidth=2 + +set laststatus=2 +set statusline=%f%m%r%h%w\ [TYPE=%Y\ %{&ff}]\ \ [%c\ @\ %l/%L]\ (%p%%)\ [%b\ 0x%B] diff --git a/salt/roots/webserver/init.sls b/salt/roots/webserver/init.sls new file mode 100644 index 0000000..59fad3b --- /dev/null +++ b/salt/roots/webserver/init.sls @@ -0,0 +1,50 @@ +include: + - nginx + +/etc/nginx/conf.d/logformat.conf: + file.managed: + - user: root + - group: root + - mode: 0644 + - source: salt://webserver/nginx-logformat.conf + - require: + - pkg: nginx + - watch_in: + - service: nginx + +{% set ssldir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} + +generate-dhparam-nginx: + cmd.run: + - name: openssl dhparam -out {{ ssldir }}/dhparams.pem 2048 + - umask: 022 + - user: root + - group: root + - creates: {{ ssldir }}/dhparams.pem + - require_in: + - file: /etc/nginx/conf.d/ssl.conf + - watch_in: + - service: nginx + +/etc/nginx/conf.d/ssl.conf: + file.managed: + - user: root + - group: root + - mode: 0644 + - source: salt://webserver/nginx-ssl.conf + - template: jinja + - require: + - pkg: nginx + - watch_in: + - service: nginx + +/etc/nginx/snippets/security.conf: + file.managed: + - user: root + - group: root + - mode: 0644 + - source: salt://webserver/nginx-security.conf + - require: + - pkg: nginx + - watch_in: + - service: nginx diff --git a/salt/roots/webserver/nginx-logformat.conf b/salt/roots/webserver/nginx-logformat.conf new file mode 100644 index 0000000..bb26d9e --- /dev/null +++ b/salt/roots/webserver/nginx-logformat.conf @@ -0,0 +1,4 @@ +log_format main '$remote_addr - $remote_user [$time_local] ' + '$server_name ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent"'; diff --git a/salt/roots/webserver/nginx-security.conf b/salt/roots/webserver/nginx-security.conf new file mode 100644 index 0000000..5585189 --- /dev/null +++ b/salt/roots/webserver/nginx-security.conf @@ -0,0 +1,19 @@ +# Security - Basic configuration + location = /favicon.ico { + log_not_found off; + access_log off; + expires max; + } + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # Deny access to hidden files + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } diff --git a/salt/roots/webserver/nginx-ssl.conf b/salt/roots/webserver/nginx-ssl.conf new file mode 100644 index 0000000..305f31d --- /dev/null +++ b/salt/roots/webserver/nginx-ssl.conf @@ -0,0 +1,15 @@ +# Default TLS settings +ssl_protocols TLSv1 TLSv1.1 TLSv1.2; +ssl_ciphers kEECDH+AESGCM:kEECDH+AES:kEECDH:EDH+AESGCM:kEDH+AES:kEDH:AESGCM:ALL:!LOW:!EXP:!MD5:!aNULL:!eNULL:!RC4:!DSS; +ssl_prefer_server_ciphers on; +ssl_session_cache shared:SSL:10m; + +ssl_dhparam {{ salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') }}/dhparams.pem; + +# OCSP stapling +ssl_stapling on; +ssl_stapling_verify on; + +# use Google's DNS +resolver 8.8.8.8; +resolver_timeout 5s; diff --git a/salt/roots/webserver/sslcert.macros.sls b/salt/roots/webserver/sslcert.macros.sls new file mode 100644 index 0000000..e3bf201 --- /dev/null +++ b/salt/roots/webserver/sslcert.macros.sls @@ -0,0 +1,30 @@ +{%- macro key_cert(domain_name) %} +{% set nginx_ssl_keydir = salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') %} +{% set nginx_ssl_certdir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} +{% set keyfile = nginx_ssl_keydir + '/' + domain_name + '.key.pem' %} +{% set certfile = nginx_ssl_certdir + '/' + domain_name + '.crt.pem' %} + +{{ keyfile }}: + rsa_key.valid_key: + - bits: {{ salt['pillar.get']('nginx:keylength:' + domain_name, 2048) }} + - require: + - file: {{ nginx_ssl_keydir }} + - require_in: + - file: /etc/nginx/sites-available/{{ domain_name }} + - service: nginx + +{{ certfile }}: + cmd.run: + - name: openssl req -new -x509 -key {{ keyfile }} -subj '/CN={{ domain_name }}' -days 730 -out {{ certfile }} + - require: + - rsa_key: {{ keyfile }} + - creates: {{ certfile }} + x509_certificate.valid_certificate: + - require: + - file: {{ nginx_ssl_certdir }} + - cmd: {{ certfile }} + - pkg: python-m2crypto + - require_in: + - file: /etc/nginx/sites-available/{{ domain_name }} + - service: nginx +{% endmacro %} From 62d8ed64e2e2991e293ff484d0b05bb282c4e1f9 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 16:23:53 +0100 Subject: [PATCH 03/29] Move salt states and pillar data to separate repository This commit removes the salt states and pillar data and adds the ldapserver role to the gvaldap host. --- Vagrantfile | 4 +- salt/bootstrap.sh | 1 + salt/grains | 0 salt/minion | 11 -- salt/pillar/gnuviechadmin/database.sls | 8 -- salt/pillar/gnuviechadmin/database/common.sls | 5 - salt/pillar/gnuviechadmin/gvaldap.sls | 8 -- salt/pillar/gnuviechadmin/init.sls | 16 --- salt/pillar/gnuviechadmin/queues.sls | 77 ------------ salt/pillar/gnuviechadmin/queues/cli.sls | 7 -- salt/pillar/gnuviechadmin/queues/common.sls | 3 - salt/pillar/gnuviechadmin/queues/gva.sls | 5 - salt/pillar/gnuviechadmin/queues/gvafile.sls | 5 - salt/pillar/gnuviechadmin/queues/gvaldap.sls | 5 - salt/pillar/gnuviechadmin/queues/gvamysql.sls | 5 - salt/pillar/gnuviechadmin/queues/gvapgsql.sls | 5 - salt/pillar/gnuviechadmin/queues/gvaweb.sls | 5 - salt/pillar/gnuviechadmin/webinterface.sls | 9 -- salt/pillar/top.sls | 8 -- salt/roots/_states/rsa_key.py | 117 ------------------ salt/roots/_states/x509_certificate.py | 61 --------- salt/roots/base/bash_functions | 25 ---- salt/roots/base/bashrc | 117 ------------------ salt/roots/base/init.sls | 30 ----- salt/roots/base/screenrc | 14 --- salt/roots/gnuviechadmin/base.sls | 98 --------------- salt/roots/gnuviechadmin/bash_functions | 25 ---- salt/roots/gnuviechadmin/celery.sls | 13 -- salt/roots/gnuviechadmin/database.sls | 33 ----- .../gnuviechadmin/gva/gnuviechadmin.nginx | 27 ---- salt/roots/gnuviechadmin/gva/settings.sh | 24 ---- salt/roots/gnuviechadmin/gvaldap.sls | 11 -- .../roots/gnuviechadmin/gvaldap/run_celery.sh | 7 -- salt/roots/gnuviechadmin/gvaldap/settings.sh | 14 --- salt/roots/gnuviechadmin/queues.sls | 30 ----- salt/roots/gnuviechadmin/vars.sls | 7 -- salt/roots/gnuviechadmin/webinterface.sls | 39 ------ salt/roots/nginx/init.sls | 38 ------ salt/roots/nginx/nginx.conf | 49 -------- salt/roots/postgresql-server/init.sls | 9 -- salt/roots/rabbitmq-server/init.sls | 17 --- salt/roots/top.sls | 11 -- salt/roots/vim/init.sls | 15 --- salt/roots/vim/vimrc | 34 ----- salt/roots/webserver/init.sls | 50 -------- salt/roots/webserver/nginx-logformat.conf | 4 - salt/roots/webserver/nginx-security.conf | 19 --- salt/roots/webserver/nginx-ssl.conf | 15 --- salt/roots/webserver/sslcert.macros.sls | 30 ----- 49 files changed, 3 insertions(+), 1167 deletions(-) delete mode 100644 salt/grains delete mode 100644 salt/minion delete mode 100644 salt/pillar/gnuviechadmin/database.sls delete mode 100644 salt/pillar/gnuviechadmin/database/common.sls delete mode 100644 salt/pillar/gnuviechadmin/gvaldap.sls delete mode 100644 salt/pillar/gnuviechadmin/init.sls delete mode 100644 salt/pillar/gnuviechadmin/queues.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/cli.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/common.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/gva.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/gvafile.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/gvaldap.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/gvamysql.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/gvapgsql.sls delete mode 100644 salt/pillar/gnuviechadmin/queues/gvaweb.sls delete mode 100644 salt/pillar/gnuviechadmin/webinterface.sls delete mode 100644 salt/pillar/top.sls delete mode 100644 salt/roots/_states/rsa_key.py delete mode 100644 salt/roots/_states/x509_certificate.py delete mode 100644 salt/roots/base/bash_functions delete mode 100644 salt/roots/base/bashrc delete mode 100644 salt/roots/base/init.sls delete mode 100644 salt/roots/base/screenrc delete mode 100644 salt/roots/gnuviechadmin/base.sls delete mode 100644 salt/roots/gnuviechadmin/bash_functions delete mode 100644 salt/roots/gnuviechadmin/celery.sls delete mode 100644 salt/roots/gnuviechadmin/database.sls delete mode 100644 salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx delete mode 100644 salt/roots/gnuviechadmin/gva/settings.sh delete mode 100644 salt/roots/gnuviechadmin/gvaldap.sls delete mode 100644 salt/roots/gnuviechadmin/gvaldap/run_celery.sh delete mode 100644 salt/roots/gnuviechadmin/gvaldap/settings.sh delete mode 100644 salt/roots/gnuviechadmin/queues.sls delete mode 100644 salt/roots/gnuviechadmin/vars.sls delete mode 100644 salt/roots/gnuviechadmin/webinterface.sls delete mode 100644 salt/roots/nginx/init.sls delete mode 100644 salt/roots/nginx/nginx.conf delete mode 100644 salt/roots/postgresql-server/init.sls delete mode 100644 salt/roots/rabbitmq-server/init.sls delete mode 100644 salt/roots/top.sls delete mode 100644 salt/roots/vim/init.sls delete mode 100644 salt/roots/vim/vimrc delete mode 100644 salt/roots/webserver/init.sls delete mode 100644 salt/roots/webserver/nginx-logformat.conf delete mode 100644 salt/roots/webserver/nginx-security.conf delete mode 100644 salt/roots/webserver/nginx-ssl.conf delete mode 100644 salt/roots/webserver/sslcert.macros.sls diff --git a/Vagrantfile b/Vagrantfile index e94f761..e101fd3 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -41,8 +41,8 @@ Vagrant.configure(2) do |config| # the path on the guest to mount the folder. And the optional third # argument is a set of non-required options. # config.vm.synced_folder "../data", "/vagrant_data" - config.vm.synced_folder "salt/roots/", "/srv/salt/" - config.vm.synced_folder "salt/pillar/", "/srv/pillar/" + config.vm.synced_folder "../gvasalt/states/", "/srv/salt/" + config.vm.synced_folder "../gvasalt/pillar/", "/srv/pillar/" # Provider-specific configuration so you can fine-tune various # backing providers for Vagrant. These expose provider-specific options. diff --git a/salt/bootstrap.sh b/salt/bootstrap.sh index f6ef8b3..218f423 100755 --- a/salt/bootstrap.sh +++ b/salt/bootstrap.sh @@ -27,5 +27,6 @@ EOF cat >/etc/salt/grains < -''' - -from M2Crypto import X509 -from datetime import datetime -import os - - -def _error(ret, err_msg): - ret['result'] = False - ret['comment'] = err_msg - return ret - - -def valid_certificate( - name, mindays=14, keyfile=None, - checkchain=False, trustedcerts=None): - ''' - Checks whether the given certificate file is valid. - - name - The name of the certificate file to check - mindays - Mark the certificate as invalid if it is valid for less then this many - days - ''' - ret = { - 'name': name, - 'changes': {}, - 'result': None, - 'comment': ''} - if not os.path.isfile(name): - return _error( - ret, 'certificate file {0} does not exist'.format(name)) - try: - cert = X509.load_cert(name) - except Exception as e: - return _error( - ret, - 'error loading certificate {0}: {1}'.format(name, e)) - notafter = cert.get_not_after().get_datetime() - delta = notafter - datetime.now(notafter.tzinfo) - if delta.days < mindays: - return _error( - ret, - 'certificate {0} is only valid for {1} more day(s)'.format( - name, delta.days)) - # TODO: check keyfile match - # TODO: check trust chain - ret['comment'] = ( - 'certificate {0} is ok and still valid for {1} days'.format( - name, delta.days)) - ret['result'] = True - return ret diff --git a/salt/roots/base/bash_functions b/salt/roots/base/bash_functions deleted file mode 100644 index 00658d6..0000000 --- a/salt/roots/base/bash_functions +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -function devenv -{ - . $HOME/gvasettings.sh - . {{ venv }}/bin/activate - cd {{ appdir }} -} - -function testenv -{ - devenv - export DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE%%.local}.test -} - -function settitle -{ - if [ -n "$STY" ] ; then # We are in a screen session - echo "Setting screen titles to $@" - printf "\033k%s\033\\" "$@" - screen -X eval "at \\# title $@" "shelltitle $@" - else - printf "\033]0;%s\007" "$@" - fi -} diff --git a/salt/roots/base/bashrc b/salt/roots/base/bashrc deleted file mode 100644 index 4bc2a9f..0000000 --- a/salt/roots/base/bashrc +++ /dev/null @@ -1,117 +0,0 @@ -# ~/.bashrc: executed by bash(1) for non-login shells. -# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) -# for examples - -# If not running interactively, don't do anything -case $- in - *i*) ;; - *) return;; -esac - -# don't put duplicate lines or lines starting with space in the history. -# See bash(1) for more options -HISTCONTROL=ignoreboth - -# append to the history file, don't overwrite it -shopt -s histappend - -# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) -HISTSIZE=1000 -HISTFILESIZE=2000 - -# check the window size after each command and, if necessary, -# update the values of LINES and COLUMNS. -shopt -s checkwinsize - -# If set, the pattern "**" used in a pathname expansion context will -# match all files and zero or more directories and subdirectories. -#shopt -s globstar - -# make less more friendly for non-text input files, see lesspipe(1) -#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" - -# set variable identifying the chroot you work in (used in the prompt below) -if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then - debian_chroot=$(cat /etc/debian_chroot) -fi - -# set a fancy prompt (non-color, unless we know we "want" color) -case "$TERM" in - xterm-color) color_prompt=yes;; -esac - -# uncomment for a colored prompt, if the terminal has the capability; turned -# off by default to not distract the user: the focus in a terminal window -# should be on the output of commands, not on the prompt -#force_color_prompt=yes - -if [ -n "$force_color_prompt" ]; then - if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then - # We have color support; assume it's compliant with Ecma-48 - # (ISO/IEC-6429). (Lack of such support is extremely rare, and such - # a case would tend to support setf rather than setaf.) - color_prompt=yes - else - color_prompt= - fi -fi - -if [ "$color_prompt" = yes ]; then - PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' -else - PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' -fi -unset color_prompt force_color_prompt - -# If this is an xterm set the title to user@host:dir -case "$TERM" in -xterm*|rxvt*) - PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" - ;; -*) - ;; -esac - -# enable color support of ls and also add handy aliases -if [ -x /usr/bin/dircolors ]; then - test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" - alias ls='ls --color=auto' - #alias dir='dir --color=auto' - #alias vdir='vdir --color=auto' - - #alias grep='grep --color=auto' - #alias fgrep='fgrep --color=auto' - #alias egrep='egrep --color=auto' -fi - -# colored GCC warnings and errors -#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' - -# some more ls aliases -#alias ll='ls -l' -#alias la='ls -A' -#alias l='ls -CF' - -# Alias definitions. -# You may want to put all your additions into a separate file like -# ~/.bash_aliases, instead of adding them here directly. -# See /usr/share/doc/bash-doc/examples in the bash-doc package. - -if [ -f ~/.bash_aliases ]; then - . ~/.bash_aliases -fi - -# enable programmable completion features (you don't need to enable -# this, if it's already enabled in /etc/bash.bashrc and /etc/profile -# sources /etc/bash.bashrc). -if ! shopt -oq posix; then - if [ -f /usr/share/bash-completion/bash_completion ]; then - . /usr/share/bash-completion/bash_completion - elif [ -f /etc/bash_completion ]; then - . /etc/bash_completion - fi -fi - -if [ -f ~/.bash_functions ]; then - . ~/.bash_functions -fi diff --git a/salt/roots/base/init.sls b/salt/roots/base/init.sls deleted file mode 100644 index 3b896aa..0000000 --- a/salt/roots/base/init.sls +++ /dev/null @@ -1,30 +0,0 @@ -base-packages: - pkg.installed: - - pkgs: - - screen - - htop - - git - -/home/vagrant/.screenrc: - file.managed: - - user: vagrant - - group: vagrant - - mode: 0644 - - source: salt://base/screenrc - -update-system: - pkg.uptodate: - - refresh: True - -/home/vagrant/bin: - file.directory: - - user: vagrant - - group: vagrant - - mode: 0750 - -/home/vagrant/.bashrc: - file.managed: - - user: vagrant - - group: vagrant - - mode: 0644 - - source: salt://base/bashrc diff --git a/salt/roots/base/screenrc b/salt/roots/base/screenrc deleted file mode 100644 index a555c1e..0000000 --- a/salt/roots/base/screenrc +++ /dev/null @@ -1,14 +0,0 @@ -# vim: syntax=screen - -hardstatus on -hardstatus alwayslastline -hardstatus string "%{= r}[ %{G}%H%{= r} ] %= %{=b b}%-w%{=rb db}%>%n %t%{-}%+w %=%{= r} [ %{G}%c %{M}%D %m-%d %{r}]" - -startup_message off - -defscrollback 10240 - -bind f eval "caption splitonly" "hardstatus ignore" -bind F eval "caption always" "hardstatus alwayslastline" - -defbce "on" diff --git a/salt/roots/gnuviechadmin/base.sls b/salt/roots/gnuviechadmin/base.sls deleted file mode 100644 index b0e8ccb..0000000 --- a/salt/roots/gnuviechadmin/base.sls +++ /dev/null @@ -1,98 +0,0 @@ -{% from 'gnuviechadmin/vars.sls' import home, gva_component, gva_amqp_user, checkout, appdir, venv %} - -gva.local: - host.present: - - ip: 172.16.3.2 - - names: - - mq - - gva.local - -gvaldap.local: - host.present: - - ip: 172.16.3.3 - -gvafile.local: - host.present: - - ip: 172.16.3.4 - -gvaweb.local: - host.present: - - ip: 172.16.3.5 - -gvamysql.local: - host.present: - - ip: 172.16.3.6 - -gvapgsql.local: - host.present: - - ip: 172.16.3.7 - -gnuviechadmin-packages: - pkg.installed: - - pkgs: - - libyaml-dev - - python-virtualenv - - python-dev - - python-pip - - gettext - -{{ home }}/gvasettings.sh: - file.managed: - - user: vagrant - - group: vagrant - - mode: 0640 - - source: salt://gnuviechadmin/{{ gva_component }}/settings.sh - - template: jinja - - context: - broker_url: {{ 'amqp://%s:%s@mq/%s' % (gva_amqp_user, salt['pillar.get']('gnuviechadmin:queues:users:%s:password' % gva_amqp_user), salt['pillar.get']('gnuviechadmin:queues:vhost')) }} - -gnuviechadmin-venv: - cmd.run: - - name: virtualenv {{ venv }} - - user: vagrant - - group: vagrant - - unless: test -f {{ venv }}/bin/pip - -gnuviechadmin-requires: - cmd.run: - - name: {{ venv }}/bin/pip install -U -r requirements/local.txt && touch {{ venv }}/lastinstall - - user: vagrant - - group: vagrant - - cwd: {{ checkout }} - - require: - - cmd: gnuviechadmin-venv - - pkg: gnuviechadmin-packages - - unless: test -e {{ venv }}/lastinstall && test {{ checkout }}/requirements/local.txt -ot {{ venv }}/lastinstall && test {{ checkout }}/requirements/base.txt -ot {{ venv }}/lastinstall - -gnuviechadmin-dbschema: - cmd.wait: - - name: . {{ home }}/gvasettings.sh ; unset LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME ; {{ venv }}/bin/python manage.py migrate --noinput - - user: vagrant - - group: vagrant - - cwd: {{ appdir }} - - watch: - - cmd: gnuviechadmin-requires - - file: {{ home }}/gvasettings.sh - -gnuviechadmin-locale-data-compile: - cmd.wait: - - name: . {{ home }}/gvasettings.sh ; {{ venv }}/bin/python {{ appdir }}/manage.py compilemessages - - user: vagrant - - group: vagrant - - cwd: {{ appdir }} - - require: - - pkg: gnuviechadmin-packages - - file: {{ home }}/gvasettings.sh - - cmd: gnuviechadmin-venv - -/home/vagrant/.bash_functions: - file.managed: - - user: vagrant - - group: vagrant - - mode: 0644 - - source: salt://base/bash_functions - - template: jinja - - context: - home: {{ home }} - venv: {{ venv }} - appdir: {{ appdir }} diff --git a/salt/roots/gnuviechadmin/bash_functions b/salt/roots/gnuviechadmin/bash_functions deleted file mode 100644 index 2c7fd41..0000000 --- a/salt/roots/gnuviechadmin/bash_functions +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -function devenv -{ - . $HOME/gvasettings.sh - . $HOME/gva-venv/bin/activate - cd /vagrant/gnuviechadmin -} - -function testenv -{ - devenv - export DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE%%.local}.test -} - -function settitle -{ - if [ -n "$STY" ] ; then # We are in a screen session - echo "Setting screen titles to $@" - printf "\033k%s\033\\" "$@" - screen -X eval "at \\# title $@" "shelltitle $@" - else - printf "\033]0;%s\007" "$@" - fi -} diff --git a/salt/roots/gnuviechadmin/celery.sls b/salt/roots/gnuviechadmin/celery.sls deleted file mode 100644 index b27b504..0000000 --- a/salt/roots/gnuviechadmin/celery.sls +++ /dev/null @@ -1,13 +0,0 @@ -{% from 'gnuviechadmin/vars.sls' import home, gva_component, venv, appdir %} - -{{ home }}/bin/run_celery.sh: - file.managed: - - user: vagrant - - group: vagrant - - mode: 0750 - - source: salt://gnuviechadmin/{{ gva_component }}/run_celery.sh - - template: jinja - - context: - home: {{ home }} - virtualenv: {{ venv }} - appdir: {{ appdir }} diff --git a/salt/roots/gnuviechadmin/database.sls b/salt/roots/gnuviechadmin/database.sls deleted file mode 100644 index ab57c2a..0000000 --- a/salt/roots/gnuviechadmin/database.sls +++ /dev/null @@ -1,33 +0,0 @@ -include: - - postgresql-server - -gnuviechadmin-database: - postgres_user.present: - - name: {{ salt['pillar.get']('gnuviechadmin:database:owner:user') }} - - user: postgres - - password: {{ salt['pillar.get']('gnuviechadmin:database:owner:password') }} - - login: True - - createdb: {% if salt['pillar.get']('gnuviechadmin:deploymenttype', 'production') == 'local' %}True -{%- else %}False -{%- endif %} - - require: - - service: postgresql - postgres_database.present: - - name: {{ salt['pillar.get']('gnuviechadmin:database:name') }} - - user: postgres - - owner: {{ salt['pillar.get']('gnuviechadmin:database:owner:user') }} - - encoding: UTF8 - - template: template0 - - require: - - service: postgresql - - postgres_user: {{ salt['pillar.get']('gnuviechadmin:database:owner:user') }} - -{% for gnuviechadmin_db_role in salt['pillar.get']('gnuviechadmin:database:users') %} -gnuviechadmin-dbuser-{{ gnuviechadmin_db_role }}: - postgres_user.present: - - name: {{ salt['pillar.get']('gnuviechadmin:database:users:%s:user' % gnuviechadmin_db_role) }} - - password: {{ salt['pillar.get']('gnuviechadmin:database:users:%s:password' % gnuviechadmin_db_role) }} - - login: True - - require: - - service: postgresql -{% endfor %} diff --git a/salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx b/salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx deleted file mode 100644 index d5768bd..0000000 --- a/salt/roots/gnuviechadmin/gva/gnuviechadmin.nginx +++ /dev/null @@ -1,27 +0,0 @@ -server { - server_name www.{{ domainname }}; - listen 443 ssl; - - ssl_certificate {{ ssl_certdir }}/{{ domainname }}.crt.pem; - ssl_certificate_key {{ ssl_keydir }}/{{ domainname }}.key.pem; - - if ( $host != '{{ domainname }}') { - return 301 https://{{ domainname }}$request_uri; - } - - client_max_body_size 1M; - gzip on; - gzip_types text/javascript application/x-javascript text/css; - - location /media { - alias /vagrant/gnuviechadmin/media; - } - - location /static { - alias /vagrant/gnuviechadmin/assets; - } - - location / { - proxy_pass http://localhost:8000; - } -} diff --git a/salt/roots/gnuviechadmin/gva/settings.sh b/salt/roots/gnuviechadmin/gva/settings.sh deleted file mode 100644 index 60bbb98..0000000 --- a/salt/roots/gnuviechadmin/gva/settings.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -export DJANGO_SETTINGS_MODULE="gnuviechadmin.settings.{{ salt['pillar.get']('gnuviechadmin:deploymenttype', 'production') }}" -export GVA_ADMIN_NAME="Jan Dittberner" -export GVA_ADMIN_EMAIL="{{ salt['pillar.get']('gnuviechadmin:adminemail') }}" -export GVA_PGSQL_DATABASE="{{ salt['pillar.get']('gnuviechadmin:database:name') }}" -export GVA_PGSQL_USER="{{ salt['pillar.get']('gnuviechadmin:database:owner:user') }}" -export GVA_PGSQL_PASSWORD="{{ salt['pillar.get']('gnuviechadmin:database:owner:password') }}" -export GVA_PGSQL_HOSTNAME="{{ salt['pillar.get']('gnuviechadmin:database:host') }}" -export GVA_PGSQL_PORT={{ salt['pillar.get']('gnuviechadmin:database:port') }} -export GVA_DOMAIN_NAME="{{ salt['pillar.get']('gnuviechadmin:domainname') }}" -export GVA_SITE_NAME="{{ salt['pillar.get']('gnuviechadmin:sitename') }}" -export GVA_SITE_SECRET="{{ salt['grains.get_or_set_hash']('gnuviechadmin:SECRET_KEY', 50) }}" -export GVA_SITE_ADMINMAIL="{{ salt['pillar.get']('gnuviechadmin:adminemail') }}" -export GVA_MIN_OS_UID={{ salt['pillar.get']('gnuviechadmin:minosuid') }} -export GVA_MIN_OS_GID={{ salt['pillar.get']('gnuviechadmin:minosgid') }} -export GVA_OSUSER_PREFIX="{{ salt['pillar.get']('gnuviechadmin:osuserprefix') }}" -export GVA_OSUSER_HOME_BASEPATH="{{ salt['pillar.get']('gnuviechadmin:osuserhomedirbase') }}" -export GVA_OSUSER_DEFAULT_SHELL="{{ salt['pillar.get']('gnuviechadmin:osuserdefaultshell') }}" -export GVA_BROKER_URL="{{ broker_url }}" -export GVA_OSUSER_UPLOADSERVER="{{ salt['pillar.get']('gnuviechadmin:uploadserver') }}" -export GVA_WEBMAIL_URL="{{ salt['pillar.get']('gnuviechadmin:webmail_url') }}" -export GVA_PHPMYADMIN_URL="{{ salt['pillar.get']('gnuviechadmin:phpmyadmin_url') }}" -export GVA_PHPPGADMIN_URL="{{ salt['pillar.get']('gnuviechadmin:phppgadmin_url') }}" diff --git a/salt/roots/gnuviechadmin/gvaldap.sls b/salt/roots/gnuviechadmin/gvaldap.sls deleted file mode 100644 index f600b9f..0000000 --- a/salt/roots/gnuviechadmin/gvaldap.sls +++ /dev/null @@ -1,11 +0,0 @@ -include: - - gnuviechadmin.base - - gnuviechadmin.celery - -gvaldap-packages: - pkg.installed: - - pkgs: - - libldap2-dev - - libsasl2-dev - - require_in: - - pkg: gnuviechadmin-packages diff --git a/salt/roots/gnuviechadmin/gvaldap/run_celery.sh b/salt/roots/gnuviechadmin/gvaldap/run_celery.sh deleted file mode 100644 index eac31c8..0000000 --- a/salt/roots/gnuviechadmin/gvaldap/run_celery.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -set -ex - -. {{ home }}/gvasettings.sh -cd {{ appdir }} -{{ virtualenv }}/bin/celery worker -A gvaldap -Q ldap --loglevel=INFO diff --git a/salt/roots/gnuviechadmin/gvaldap/settings.sh b/salt/roots/gnuviechadmin/gvaldap/settings.sh deleted file mode 100644 index e99308c..0000000 --- a/salt/roots/gnuviechadmin/gvaldap/settings.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -export DJANGO_SETTINGS_MODULE="gvaldap.settings.{{ salt['pillar.get']('gnuviechadmin:deploymenttype', 'production') }}" -export GVALDAP_ADMIN_NAME="Jan Dittberner" -export GVALDAP_ADMIN_EMAIL="{{ salt['pillar.get']('gnuviechadmin-gvaldap:admin_email') }}" -export GVALDAP_LDAP_URL="{{ salt['pillar.get']('gnuviechadmin-gvaldap:ldap_url') }}" -export GVALDAP_LDAP_USER="{{ salt['pillar.get']('gnuviechadmin-gvaldap:ldap_user') }}" -export GVALDAP_LDAP_PASSWORD="{{ salt['pillar.get']('gnuviechadmin-gvaldap:ldap_password' ) }}" -export GVALDAP_BASEDN_GROUP="{{ salt['pillar.get']('gnuviechadmin-gvaldap:basedn_group') }}" -export GVALDAP_BASEDN_USER="{{ salt['pillar.get']('gnuviechadmin-gvaldap:basedn_user') }}" -export GVALDAP_SECRETKEY="{{ salt['grains.get_or_set_hash']('gnuviechadmin-gvaldap:SECRET_KEY', 50) }}" -export GVALDAP_BROKER_URL="{{ broker_url }}" -export GVALDAP_ALLOWED_HOSTS="{{ salt['pillar.get']('gnuviechadmin-gvaldap:allowed_hosts') }}" -export GVALDAP_SERVER_EMAIL="{{ salt['pillar.get']('gnuviechadmin-gvaldap:server_email') }}" diff --git a/salt/roots/gnuviechadmin/queues.sls b/salt/roots/gnuviechadmin/queues.sls deleted file mode 100644 index 5462fb7..0000000 --- a/salt/roots/gnuviechadmin/queues.sls +++ /dev/null @@ -1,30 +0,0 @@ -include: - - rabbitmq-server - -gnuviechadmin-queue-vhost: - rabbitmq_vhost.present: - - name: {{ salt['pillar.get']('gnuviechadmin:queues:vhost') }} - -{% for user in salt['pillar.get']('gnuviechadmin:queues:users') %} -gnuviechadmin-queue-user-{{ user }}: - rabbitmq_user.present: - - name: {{ user }} - - password: {{ salt['pillar.get']('gnuviechadmin:queues:users:%s:password' % user) }} -{% if salt['pillar.get']('gnuviechadmin:queues:users:%s:perms' % user) %} - - perms: -{% for vhost, perms in salt['pillar.get']('gnuviechadmin:queues:users:%s:perms' % user).iteritems() %} - - {{ vhost }}: - - {{ perms[0] }} - - {{ perms[1] }} - - {{ perms[2] }} -{% endfor %} -{% endif %} -{% if salt['pillar.get']('gnuviechadmin:queues:users:%s:tags' % user) %} - - tags: -{% for tag in salt['pillar.get']('gnuviechadmin:queues:users:%s:tags' % user) %} - - {{ tag }} -{% endfor %} -{% endif %} - - require: - - rabbitmq_vhost: {{ salt['pillar.get']('gnuviechadmin:queues:vhost') }} -{% endfor %} diff --git a/salt/roots/gnuviechadmin/vars.sls b/salt/roots/gnuviechadmin/vars.sls deleted file mode 100644 index 6ad1aa2..0000000 --- a/salt/roots/gnuviechadmin/vars.sls +++ /dev/null @@ -1,7 +0,0 @@ -{% set home = '/home/vagrant' %} -{% set venv = home + '/gva-venv' %} -{% set checkout = '/vagrant' %} -{% set gva_component = salt['pillar.get']('gnuviechadmin:component:name') %} -{% set gva_amqp_user = salt['pillar.get']('gnuviechadmin:component:amqp_user') %} -{% set python_module = salt['pillar.get']('gnuviechadmin:component:python_module', gva_component) %} -{% set appdir = checkout + '/' + python_module %} diff --git a/salt/roots/gnuviechadmin/webinterface.sls b/salt/roots/gnuviechadmin/webinterface.sls deleted file mode 100644 index f94c060..0000000 --- a/salt/roots/gnuviechadmin/webinterface.sls +++ /dev/null @@ -1,39 +0,0 @@ -include: - - gnuviechadmin.base - - webserver - -libpq-dev: - pkg.installed: - - require_in: - - pkg: gnuviechadmin-packages - -python-m2crypto: - pkg.installed: - - reload_modules: true - -{% import "webserver/sslcert.macros.sls" as sslcert %} - -{% set domainname = salt['pillar.get']('gnuviechadmin:domainname') %} -{{ sslcert.key_cert(domainname) }} - -/etc/nginx/sites-available/{{ domainname }}: - file.managed: - - user: root - - group: root - - mode: 0640 - - source: salt://gnuviechadmin/gva/gnuviechadmin.nginx - - template: jinja - - context: - domainname: {{ domainname }} - ssl_keydir: {{ salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') }} - ssl_certdir: {{ salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') }} - - require: - - pkg: nginx - -/etc/nginx/sites-enabled/{{ domainname }}: - file.symlink: - - target: /etc/nginx/sites-available/{{ domainname }} - - require: - - file: /etc/nginx/sites-available/{{ domainname }} - - watch_in: - - service: nginx diff --git a/salt/roots/nginx/init.sls b/salt/roots/nginx/init.sls deleted file mode 100644 index cd47736..0000000 --- a/salt/roots/nginx/init.sls +++ /dev/null @@ -1,38 +0,0 @@ -nginx: - pkg: - - installed - service.running: - - enable: True - - require: - - pkg: nginx - -nginx-common: - pkg.installed - -/etc/nginx/nginx.conf: - file.managed: - - source: salt://nginx/nginx.conf - - user: root - - group: root - - mode: 0644 - - require: - - pkg: nginx-common - - watch_in: - - service: nginx - -{% set nginx_ssl_keydir = salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') %} -{% set nginx_ssl_certdir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} - -{{ nginx_ssl_certdir }}: - file.directory: - - user: root - - group: root - - mode: 0755 - - makedirs: True - -{{ nginx_ssl_keydir }}: - file.directory: - - user: root - - group: root - - mode: 0750 - - makedirs: True diff --git a/salt/roots/nginx/nginx.conf b/salt/roots/nginx/nginx.conf deleted file mode 100644 index dfeb36d..0000000 --- a/salt/roots/nginx/nginx.conf +++ /dev/null @@ -1,49 +0,0 @@ -user www-data; -worker_processes 4; -pid /run/nginx.pid; - -events { - worker_connections 768; - # multi_accept on; -} - -http { - - ## - # Basic Settings - ## - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - # server_tokens off; - - server_names_hash_bucket_size 64; - # server_name_in_redirect off; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - ## - # Logging Settings - ## - - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - ## - # Gzip Settings - ## - - gzip on; - gzip_disable "msie6"; - - ## - # Virtual Host Configs - ## - - include /etc/nginx/conf.d/*.conf; - include /etc/nginx/sites-enabled/*; -} diff --git a/salt/roots/postgresql-server/init.sls b/salt/roots/postgresql-server/init.sls deleted file mode 100644 index f08ace7..0000000 --- a/salt/roots/postgresql-server/init.sls +++ /dev/null @@ -1,9 +0,0 @@ -locales-all: - pkg.installed - -postgresql: - pkg: - - installed - service.running: - - require: - - pkg: postgresql diff --git a/salt/roots/rabbitmq-server/init.sls b/salt/roots/rabbitmq-server/init.sls deleted file mode 100644 index 6c3c7f6..0000000 --- a/salt/roots/rabbitmq-server/init.sls +++ /dev/null @@ -1,17 +0,0 @@ -rabbitmq-server: - pkg: - - installed - service: - - running - - requires: - - pkg: rabbitmq-server - -guest: - rabbitmq_user: - - absent - -rabbitmq_management: - rabbitmq_plugin: - - enabled - - watch_in: - - service: rabbitmq-server diff --git a/salt/roots/top.sls b/salt/roots/top.sls deleted file mode 100644 index 7075d53..0000000 --- a/salt/roots/top.sls +++ /dev/null @@ -1,11 +0,0 @@ -base: - '*': - - vim - - base -{% if 'roles' in grains %} -{% for role in grains['roles'] %} - 'roles:{{ role }}': - - match: grain - - {{ role }} -{% endfor %} -{% endif %} diff --git a/salt/roots/vim/init.sls b/salt/roots/vim/init.sls deleted file mode 100644 index fa234e3..0000000 --- a/salt/roots/vim/init.sls +++ /dev/null @@ -1,15 +0,0 @@ -vim-nox: - pkg.installed - -editor: - alternatives.set: - - path: /usr/bin/vim.nox - - require: - - pkg: vim-nox - -/home/vagrant/.vimrc: - file.managed: - - user: vagrant - - group: vagrant - - mode: 0644 - - source: salt://vim/vimrc diff --git a/salt/roots/vim/vimrc b/salt/roots/vim/vimrc deleted file mode 100644 index 931195b..0000000 --- a/salt/roots/vim/vimrc +++ /dev/null @@ -1,34 +0,0 @@ -syntax on - -set showcmd -set modeline -set modelines=3 -set expandtab -set shiftwidth=4 -set autoindent -set smarttab -set ruler -set list listchars=tab:▷⋅,trail:⋅,nbsp:⋅ -set cpoptions+=$ -set hlsearch -set virtualedit=all -set guioptions-=T -set guioptions-=m -set wildmenu -set complete=.,w,b,u,t -set number - -filetype plugin indent on - -autocmd BufNewFile,BufRead *.sls set filetype=yaml - -autocmd FileType make set noexpandtab -autocmd FileType python set tabstop=4 shiftwidth=4 autoindent smartindent textwidth=79 -autocmd FileType html set tabstop=2 shiftwidth=2 textwidth=200 smartindent autoindent -autocmd FileType htmldjango set tabstop=2 shiftwidth=2 textwidth=200 -autocmd FileType moin set tabstop=2 shiftwidth=2 -autocmd FileType rst set textwidth=79 -autocmd FileType yaml set tabstop=2 shiftwidth=2 - -set laststatus=2 -set statusline=%f%m%r%h%w\ [TYPE=%Y\ %{&ff}]\ \ [%c\ @\ %l/%L]\ (%p%%)\ [%b\ 0x%B] diff --git a/salt/roots/webserver/init.sls b/salt/roots/webserver/init.sls deleted file mode 100644 index 59fad3b..0000000 --- a/salt/roots/webserver/init.sls +++ /dev/null @@ -1,50 +0,0 @@ -include: - - nginx - -/etc/nginx/conf.d/logformat.conf: - file.managed: - - user: root - - group: root - - mode: 0644 - - source: salt://webserver/nginx-logformat.conf - - require: - - pkg: nginx - - watch_in: - - service: nginx - -{% set ssldir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} - -generate-dhparam-nginx: - cmd.run: - - name: openssl dhparam -out {{ ssldir }}/dhparams.pem 2048 - - umask: 022 - - user: root - - group: root - - creates: {{ ssldir }}/dhparams.pem - - require_in: - - file: /etc/nginx/conf.d/ssl.conf - - watch_in: - - service: nginx - -/etc/nginx/conf.d/ssl.conf: - file.managed: - - user: root - - group: root - - mode: 0644 - - source: salt://webserver/nginx-ssl.conf - - template: jinja - - require: - - pkg: nginx - - watch_in: - - service: nginx - -/etc/nginx/snippets/security.conf: - file.managed: - - user: root - - group: root - - mode: 0644 - - source: salt://webserver/nginx-security.conf - - require: - - pkg: nginx - - watch_in: - - service: nginx diff --git a/salt/roots/webserver/nginx-logformat.conf b/salt/roots/webserver/nginx-logformat.conf deleted file mode 100644 index bb26d9e..0000000 --- a/salt/roots/webserver/nginx-logformat.conf +++ /dev/null @@ -1,4 +0,0 @@ -log_format main '$remote_addr - $remote_user [$time_local] ' - '$server_name ' - '"$request" $status $body_bytes_sent ' - '"$http_referer" "$http_user_agent"'; diff --git a/salt/roots/webserver/nginx-security.conf b/salt/roots/webserver/nginx-security.conf deleted file mode 100644 index 5585189..0000000 --- a/salt/roots/webserver/nginx-security.conf +++ /dev/null @@ -1,19 +0,0 @@ -# Security - Basic configuration - location = /favicon.ico { - log_not_found off; - access_log off; - expires max; - } - - location = /robots.txt { - allow all; - log_not_found off; - access_log off; - } - - # Deny access to hidden files - location ~ /\. { - deny all; - access_log off; - log_not_found off; - } diff --git a/salt/roots/webserver/nginx-ssl.conf b/salt/roots/webserver/nginx-ssl.conf deleted file mode 100644 index 305f31d..0000000 --- a/salt/roots/webserver/nginx-ssl.conf +++ /dev/null @@ -1,15 +0,0 @@ -# Default TLS settings -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; -ssl_ciphers kEECDH+AESGCM:kEECDH+AES:kEECDH:EDH+AESGCM:kEDH+AES:kEDH:AESGCM:ALL:!LOW:!EXP:!MD5:!aNULL:!eNULL:!RC4:!DSS; -ssl_prefer_server_ciphers on; -ssl_session_cache shared:SSL:10m; - -ssl_dhparam {{ salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') }}/dhparams.pem; - -# OCSP stapling -ssl_stapling on; -ssl_stapling_verify on; - -# use Google's DNS -resolver 8.8.8.8; -resolver_timeout 5s; diff --git a/salt/roots/webserver/sslcert.macros.sls b/salt/roots/webserver/sslcert.macros.sls deleted file mode 100644 index e3bf201..0000000 --- a/salt/roots/webserver/sslcert.macros.sls +++ /dev/null @@ -1,30 +0,0 @@ -{%- macro key_cert(domain_name) %} -{% set nginx_ssl_keydir = salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') %} -{% set nginx_ssl_certdir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} -{% set keyfile = nginx_ssl_keydir + '/' + domain_name + '.key.pem' %} -{% set certfile = nginx_ssl_certdir + '/' + domain_name + '.crt.pem' %} - -{{ keyfile }}: - rsa_key.valid_key: - - bits: {{ salt['pillar.get']('nginx:keylength:' + domain_name, 2048) }} - - require: - - file: {{ nginx_ssl_keydir }} - - require_in: - - file: /etc/nginx/sites-available/{{ domain_name }} - - service: nginx - -{{ certfile }}: - cmd.run: - - name: openssl req -new -x509 -key {{ keyfile }} -subj '/CN={{ domain_name }}' -days 730 -out {{ certfile }} - - require: - - rsa_key: {{ keyfile }} - - creates: {{ certfile }} - x509_certificate.valid_certificate: - - require: - - file: {{ nginx_ssl_certdir }} - - cmd: {{ certfile }} - - pkg: python-m2crypto - - require_in: - - file: /etc/nginx/sites-available/{{ domain_name }} - - service: nginx -{% endmacro %} From 02768a4b95d52d6235773f2e40655a747fbd011f Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 16:31:13 +0100 Subject: [PATCH 04/29] Use separate AMQP vhost for tests --- gvaldap/gvaldap/settings/test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/gvaldap/gvaldap/settings/test.py b/gvaldap/gvaldap/settings/test.py index c39ee49..dc5d82b 100644 --- a/gvaldap/gvaldap/settings/test.py +++ b/gvaldap/gvaldap/settings/test.py @@ -5,7 +5,8 @@ Test settings based on :py:mod:`gvaldap.settings.base`. """ from __future__ import absolute_import -from .base import * +# use import * to import all settings from base +from .base import * # NOQA ########## IN-MEMORY TEST DATABASE DATABASES = { @@ -18,3 +19,19 @@ DATABASES = { "PORT": "", }, } +LOGGING['handlers'].update({ + 'console': { + 'level': 'ERROR', + 'class': 'logging.StreamHandler', + 'formatter': 'simple', + } +}) +LOGGING['loggers'].update(dict( + [(key, {'handlers': ['console'], 'level': 'ERROR', 'propagate': True, }) + for key in [ + 'dashboard', 'domains', 'fileservertasks', 'gvacommon', + 'gvawebcore', 'hostingpackages', 'ldaptasks', 'managemails', + 'mysqltasks', 'osusers', 'pgsqltasks', 'taskresults', + 'userdbs', 'websites']])) +BROKER_URL = BROKER_URL + '_test' +CELERY_RESULT_PERSISTENT = False From 5094990c9ab97c6cc86f1708c340b7ad26e18588 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 16:32:14 +0100 Subject: [PATCH 05/29] Switch from deprecated amqp backend to rpc The previously used amqp result backend has been marked as deprecated by the celery developers. This commit switches to the rpc backend that should be used instead. This commit renames get_env_setting to get_env_variable to be consistent with the gva settings modules. --- gvaldap/gvaldap/settings/base.py | 36 +++++++++++++------------- gvaldap/gvaldap/settings/production.py | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py index 3d12927..02fec0f 100644 --- a/gvaldap/gvaldap/settings/base.py +++ b/gvaldap/gvaldap/settings/base.py @@ -5,28 +5,28 @@ Common settings and globals. """ +from os import environ from os.path import abspath, basename, dirname, join, normpath from sys import path -from os import environ # Normally you should not import ANYTHING from Django directly # into your settings, but ImproperlyConfigured is an exception. from django.core.exceptions import ImproperlyConfigured -def get_env_setting(setting): +def get_env_variable(var_name): """ - Get the environment setting or return exception. + Get a setting from an environment variable. - :param str setting: name of an environment setting + :param str var_name: variable name :raises ImproperlyConfigured: if the environment setting is not defined :return: environment setting value :rtype: str """ try: - return environ[setting] + return environ[var_name] except KeyError: - error_msg = "Set the %s env variable" % setting + error_msg = "Set the %s environment variable" % var_name raise ImproperlyConfigured(error_msg) @@ -58,7 +58,7 @@ TEMPLATE_DEBUG = DEBUG ########## MANAGER CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#admins ADMINS = ( - (get_env_setting('GVALDAP_ADMIN_NAME'), get_env_setting('GVALDAP_ADMIN_EMAIL')), + (get_env_variable('GVALDAP_ADMIN_NAME'), get_env_variable('GVALDAP_ADMIN_EMAIL')), ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#managers @@ -79,9 +79,9 @@ DATABASES = { }, 'ldap': { 'ENGINE': 'ldapdb.backends.ldap', - 'NAME': get_env_setting('GVALDAP_LDAP_URL'), - 'USER': get_env_setting('GVALDAP_LDAP_USER'), - 'PASSWORD': get_env_setting('GVALDAP_LDAP_PASSWORD'), + 'NAME': get_env_variable('GVALDAP_LDAP_URL'), + 'USER': get_env_variable('GVALDAP_LDAP_USER'), + 'PASSWORD': get_env_variable('GVALDAP_LDAP_PASSWORD'), } } DATABASE_ROUTERS = ['ldapdb.router.Router'] @@ -141,7 +141,7 @@ STATICFILES_FINDERS = ( ########## SECRET CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # Note: This key should only be used for development and testing. -SECRET_KEY = get_env_setting('GVALDAP_SECRETKEY') +SECRET_KEY = get_env_variable('GVALDAP_SECRETKEY') ########## END SECRET CONFIGURATION @@ -279,15 +279,15 @@ WSGI_APPLICATION = '%s.wsgi.application' % SITE_NAME ########## END WSGI CONFIGURATION -########## LDAP SETTINGS -GROUP_BASE_DN = get_env_setting('GVALDAP_BASEDN_GROUP') -USER_BASE_DN = get_env_setting('GVALDAP_BASEDN_USER') -########## END LDAP SETTINGS +# ######### LDAP SETTINGS +GROUP_BASE_DN = get_env_variable('GVALDAP_BASEDN_GROUP') +USER_BASE_DN = get_env_variable('GVALDAP_BASEDN_USER') +# ######### END LDAP SETTINGS ########## CELERY CONFIGURATION -BROKER_URL = get_env_setting('GVALDAP_BROKER_URL') -CELERY_RESULT_BACKEND = 'amqp' +BROKER_URL = get_env_variable('GVALDAP_BROKER_URL') +CELERY_RESULT_BACKEND = 'rpc://' CELERY_RESULT_PERSISTENT = True CELERY_TASK_RESULT_EXPIRES = None CELERY_ROUTES = ( @@ -296,6 +296,6 @@ CELERY_ROUTES = ( CELERY_TIMEZONE = 'Europe/Berlin' CELERY_ENABLE_UTC = True CELERY_ACCEPT_CONTENT = ['json'] -CELERY_TASK_SERAILIZER = 'json' +CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' ########## END CELERY CONFIGURATION diff --git a/gvaldap/gvaldap/settings/production.py b/gvaldap/gvaldap/settings/production.py index e24de0d..c8eb1f4 100644 --- a/gvaldap/gvaldap/settings/production.py +++ b/gvaldap/gvaldap/settings/production.py @@ -10,7 +10,7 @@ from .base import * ########## HOST CONFIGURATION # See: https://docs.djangoproject.com/en/1.5/releases/1.5/#allowed-hosts-required-in-production -ALLOWED_HOSTS = get_env_setting('GVALDAP_ALLOWED_HOSTS').split(',') +ALLOWED_HOSTS = get_env_variable('GVALDAP_ALLOWED_HOSTS').split(',') ########## END HOST CONFIGURATION ########## EMAIL CONFIGURATION @@ -36,7 +36,7 @@ EMAIL_SUBJECT_PREFIX = '[%s] ' % SITE_NAME #EMAIL_USE_TLS = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#server-email -SERVER_EMAIL = get_env_setting('GVALDAP_SERVER_EMAIL') +SERVER_EMAIL = get_env_variable('GVALDAP_SERVER_EMAIL') ########## END EMAIL CONFIGURATION ########## DATABASE CONFIGURATION From e9ee69f6e5e281344dadcc2e731f53bbb8bb6007 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 16:40:09 +0100 Subject: [PATCH 06/29] Add code quality requirements --- requirements/local.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/requirements/local.txt b/requirements/local.txt index af0d444..0b60d4a 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -1,8 +1,11 @@ # Local development dependencies go here --r base.txt -coverage==3.7.1 +-r test.txt django-debug-toolbar==1.2.2 Sphinx==1.2.3 sqlparse==0.1.14 releases==0.7.0 Pygments==2.0.2 +flake8==2.5.2 +mccabe==0.4.0 +pep8==1.7.0 +pyflakes==1.0.0 From 7c6ed136ebe1780d58049aa9d67f4b562b6794dc Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 20:34:54 +0100 Subject: [PATCH 07/29] Switch result backend to redis The AMQP result backend proved as impractical, this commit switches to redis instead. --- gvaldap/gvaldap/settings/base.py | 3 +-- requirements/base.txt | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py index 02fec0f..dbe55a8 100644 --- a/gvaldap/gvaldap/settings/base.py +++ b/gvaldap/gvaldap/settings/base.py @@ -287,8 +287,7 @@ USER_BASE_DN = get_env_variable('GVALDAP_BASEDN_USER') ########## CELERY CONFIGURATION BROKER_URL = get_env_variable('GVALDAP_BROKER_URL') -CELERY_RESULT_BACKEND = 'rpc://' -CELERY_RESULT_PERSISTENT = True +CELERY_RESULT_BACKEND = get_env_variable('GVALDAP_RESULTS_REDIS_URL') CELERY_TASK_RESULT_EXPIRES = None CELERY_ROUTES = ( 'gvacommon.celeryrouters.GvaRouter', diff --git a/requirements/base.txt b/requirements/base.txt index b42ce77..0f0c966 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,6 +4,7 @@ bpython==0.13.2 django-braces==1.4.0 django-model-utils==2.2 logutils==0.3.3 -celery==3.1.17 +celery==3.1.20 passlib==1.6.2 requests==2.5.1 +redis==2.10.5 From ed18c4a6f9225e30f5dd5b58f210a5026d6cce80 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 23:19:26 +0100 Subject: [PATCH 08/29] Modernize dependencies, sync with gva This commit modernizes all requirements to the latest versions, adapts the settings to Django 1.9 and synchronizes the settings layout with gva. --- .gitignore | 1 + gvaldap/gvacommon/.gitignore | 3 -- gvaldap/gvacommon/__init__.py | 0 gvaldap/gvacommon/celeryrouters.py | 15 ------ gvaldap/gvaldap/settings/base.py | 69 ++++++++++++-------------- gvaldap/gvaldap/settings/local.py | 33 ++++++++---- gvaldap/gvaldap/settings/production.py | 41 +++++---------- gvaldap/gvaldap/settings/test.py | 9 ++-- gvaldap/gvaldap/urls.py | 16 +++--- requirements/base.txt | 24 ++++++--- requirements/local.txt | 12 +++-- requirements/test.txt | 2 +- 12 files changed, 105 insertions(+), 120 deletions(-) delete mode 100644 gvaldap/gvacommon/.gitignore delete mode 100644 gvaldap/gvacommon/__init__.py delete mode 100644 gvaldap/gvacommon/celeryrouters.py diff --git a/.gitignore b/.gitignore index fcd5c5c..debdad8 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ Desktop.ini .ropeproject _build/ .vagrant/ +.coverage diff --git a/gvaldap/gvacommon/.gitignore b/gvaldap/gvacommon/.gitignore deleted file mode 100644 index 5f1ace6..0000000 --- a/gvaldap/gvacommon/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.*.swp -*.pyc -.ropeproject/ diff --git a/gvaldap/gvacommon/__init__.py b/gvaldap/gvacommon/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gvaldap/gvacommon/celeryrouters.py b/gvaldap/gvacommon/celeryrouters.py deleted file mode 100644 index ec7b122..0000000 --- a/gvaldap/gvacommon/celeryrouters.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - - -class GvaRouter(object): - - def route_for_task(self, task, args=None, kwargs=None): - for route in ['ldap', 'file', 'mysql', 'pgsql']: - if route in task: - return { - 'exchange': route, - 'exchange_type': 'direct', - 'queue': route, - } - return None diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py index dbe55a8..f03937e 100644 --- a/gvaldap/gvaldap/settings/base.py +++ b/gvaldap/gvaldap/settings/base.py @@ -50,9 +50,6 @@ path.append(DJANGO_ROOT) # See: https://docs.djangoproject.com/en/dev/ref/settings/#debug DEBUG = False -# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug -TEMPLATE_DEBUG = DEBUG -########## END DEBUG CONFIGURATION ########## MANAGER CONFIGURATION @@ -119,20 +116,11 @@ MEDIA_URL = '/media/' ########## STATIC FILE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root -STATIC_ROOT = normpath(join(SITE_ROOT, 'assets')) - # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url STATIC_URL = '/static/' -# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS -STATICFILES_DIRS = ( - normpath(join(SITE_ROOT, 'static')), -) - # See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) ########## END STATIC FILE CONFIGURATION @@ -161,28 +149,29 @@ FIXTURE_DIRS = ( ########## TEMPLATE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.contrib.auth.context_processors.auth', - 'django.core.context_processors.debug', - 'django.core.context_processors.i18n', - 'django.core.context_processors.media', - 'django.core.context_processors.static', - 'django.core.context_processors.tz', - 'django.contrib.messages.context_processors.messages', - 'django.core.context_processors.request', -) +# See: https://docs.djangoproject.com/en/1.9/ref/settings/#std:setting-TEMPLATES # noqa +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + normpath(join(SITE_ROOT, 'templates')), + ], + '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.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + 'django.template.context_processors.request', + ], + }, + }, +] -# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -) - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs -TEMPLATE_DIRS = ( - normpath(join(SITE_ROOT, 'templates')), -) ########## END TEMPLATE CONFIGURATION @@ -195,6 +184,7 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) ########## END MIDDLEWARE CONFIGURATION @@ -221,12 +211,8 @@ DJANGO_APPS = ( 'django.contrib.messages', 'django.contrib.staticfiles', - # Useful template tags: - # 'django.contrib.humanize', - # Admin panel and documentation: 'django.contrib.admin', - # 'django.contrib.admindocs', ) # Apps specific for this project go here. @@ -250,6 +236,15 @@ INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS LOGGING = { 'version': 1, 'disable_existing_loggers': False, + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(name)s ' + '%(module)s:%(lineno)d %(process)d %(thread)d %(message)s', + }, + 'simple': { + 'format': '%(levelname)s %(name)s:%(lineno)d %(message)s', + }, + }, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse' diff --git a/gvaldap/gvaldap/settings/local.py b/gvaldap/gvaldap/settings/local.py index 8a8d441..d0d8fef 100644 --- a/gvaldap/gvaldap/settings/local.py +++ b/gvaldap/gvaldap/settings/local.py @@ -1,3 +1,4 @@ +# -*- python -*- # pymode:lint_ignore=W0401,E501 """ Development settings and globals based on :py:mod:`gvaldap.settings.base`. @@ -6,32 +7,33 @@ Development settings and globals based on :py:mod:`gvaldap.settings.base`. from __future__ import absolute_import -from .base import * +# use import * to import all settings from base +from .base import * # NOQA -########## DEBUG CONFIGURATION +# ######### DEBUG CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#debug DEBUG = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug -TEMPLATE_DEBUG = DEBUG -########## END DEBUG CONFIGURATION +TEMPLATES[0]['OPTIONS']['debug'] = DEBUG +# ######### END DEBUG CONFIGURATION -########## EMAIL CONFIGURATION +# ######### EMAIL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-backend EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -########## END EMAIL CONFIGURATION +# ######### END EMAIL CONFIGURATION -########## CACHE CONFIGURATION +# ######### CACHE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#caches CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', } } -########## END CACHE CONFIGURATION +# ######### END CACHE CONFIGURATION ########## TOOLBAR CONFIGURATION @@ -44,8 +46,19 @@ MIDDLEWARE_CLASSES += ( 'debug_toolbar.middleware.DebugToolbarMiddleware', ) +LOGGING['handlers'].update({ + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'simple', + } +}) +LOGGING['loggers'].update(dict( + [(key, {'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }) + for key in ['ldapentities', 'ldaptasks']])) + DEBUG_TOOLBAR_PATCH_SETTINGS = False # http://django-debug-toolbar.readthedocs.org/en/latest/installation.html -INTERNAL_IPS = ('127.0.0.1',) -########## END TOOLBAR CONFIGURATION +INTERNAL_IPS = ('127.0.0.1', '10.0.2.2') +# ######### END TOOLBAR CONFIGURATION diff --git a/gvaldap/gvaldap/settings/production.py b/gvaldap/gvaldap/settings/production.py index c8eb1f4..03d35a2 100644 --- a/gvaldap/gvaldap/settings/production.py +++ b/gvaldap/gvaldap/settings/production.py @@ -1,3 +1,4 @@ +# -*- python -*- # pymode:lint_ignore=W0401,E501 """ Production settings and globals based on :py:mod:`gvaldap.settings.base`. @@ -6,45 +7,29 @@ Production settings and globals based on :py:mod:`gvaldap.settings.base`. from __future__ import absolute_import -from .base import * +# use import * to import all settings from base +from .base import * # NOQA -########## HOST CONFIGURATION -# See: https://docs.djangoproject.com/en/1.5/releases/1.5/#allowed-hosts-required-in-production +# ######### HOST CONFIGURATION +# See: https://docs.djangoproject.com/en/1.5/releases/1.5/#allowed-hosts-required-in-production # noqa ALLOWED_HOSTS = get_env_variable('GVALDAP_ALLOWED_HOSTS').split(',') -########## END HOST CONFIGURATION +# ######### END HOST CONFIGURATION -########## EMAIL CONFIGURATION +# ######### EMAIL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-backend EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-host -#EMAIL_HOST = environ.get('EMAIL_HOST', 'smtp.gmail.com') - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-host-password -#EMAIL_HOST_PASSWORD = environ.get('EMAIL_HOST_PASSWORD', '') - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-host-user -#EMAIL_HOST_USER = environ.get('EMAIL_HOST_USER', 'your_email@example.com') - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-port -#EMAIL_PORT = environ.get('EMAIL_PORT', 587) - # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix EMAIL_SUBJECT_PREFIX = '[%s] ' % SITE_NAME -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-use-tls -#EMAIL_USE_TLS = True +# See: https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email +DEFAULT_FROM_EMAIL = get_env_variable('GVALDAP_ADMIN_EMAIL') # See: https://docs.djangoproject.com/en/dev/ref/settings/#server-email SERVER_EMAIL = get_env_variable('GVALDAP_SERVER_EMAIL') -########## END EMAIL CONFIGURATION +# ######### END EMAIL CONFIGURATION -########## DATABASE CONFIGURATION -#DATABASES = {} -########## END DATABASE CONFIGURATION - - -########## CACHE CONFIGURATION +# ######### CACHE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#caches -#CACHES = {} -########## END CACHE CONFIGURATION +# CACHES = {} +# ######### END CACHE CONFIGURATION diff --git a/gvaldap/gvaldap/settings/test.py b/gvaldap/gvaldap/settings/test.py index dc5d82b..b83ae47 100644 --- a/gvaldap/gvaldap/settings/test.py +++ b/gvaldap/gvaldap/settings/test.py @@ -8,6 +8,9 @@ from __future__ import absolute_import # use import * to import all settings from base from .base import * # NOQA +PASSWORD_HASHERS = ( + 'django.contrib.auth.hashers.MD5PasswordHasher', +) ########## IN-MEMORY TEST DATABASE DATABASES = { "default": { @@ -28,10 +31,6 @@ LOGGING['handlers'].update({ }) LOGGING['loggers'].update(dict( [(key, {'handlers': ['console'], 'level': 'ERROR', 'propagate': True, }) - for key in [ - 'dashboard', 'domains', 'fileservertasks', 'gvacommon', - 'gvawebcore', 'hostingpackages', 'ldaptasks', 'managemails', - 'mysqltasks', 'osusers', 'pgsqltasks', 'taskresults', - 'userdbs', 'websites']])) + for key in ['ldapentities', 'ldaptasks']])) BROKER_URL = BROKER_URL + '_test' CELERY_RESULT_PERSISTENT = False diff --git a/gvaldap/gvaldap/urls.py b/gvaldap/gvaldap/urls.py index ca59fb7..1ca71d4 100644 --- a/gvaldap/gvaldap/urls.py +++ b/gvaldap/gvaldap/urls.py @@ -3,23 +3,21 @@ This module defines the main URLConf for gvaldap. """ -from django.conf.urls import patterns, include, url +from django.conf.urls import include, url from django.conf import settings -# Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() -urlpatterns = patterns( - '', +urlpatterns = [ url(r'^admin/', include(admin.site.urls)), -) +] # Uncomment the next line to serve media files in dev. # urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -if settings.DEBUG: +if settings.DEBUG: # pragma: no cover import debug_toolbar - urlpatterns += patterns('', - url(r'^__debug__/', include(debug_toolbar.urls)), - ) + urlpatterns += [ + url(r'^__debug__/', include(debug_toolbar.urls)), + ] diff --git a/requirements/base.txt b/requirements/base.txt index 0f0c966..72a3736 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,10 +1,20 @@ -Django==1.7.4 -django-ldapdb==0.3.2 -bpython==0.13.2 -django-braces==1.4.0 -django-model-utils==2.2 +Django==1.9.1 +Jinja2==2.8 +#django-ldapdb==0.4.0 +-e git+https://github.com/jandd/django-ldapdb@django19#egg=django-ldapdb +python-ldap==2.4.25 +bpython==0.15 +curtsies==0.2.6 +django-braces==1.8.1 +django-model-utils==2.4 logutils==0.3.3 celery==3.1.20 -passlib==1.6.2 -requests==2.5.1 +amqp==1.4.9 +billiard==3.3.0.22 +kombu==3.0.33 +pytz==2015.7 +passlib==1.6.5 +requests==2.9.1 +simplejson==3.8.1 +-e git+https://git.gnuviech-server.de/gvacommon.git@0.2.1#egg=gvacommon redis==2.10.5 diff --git a/requirements/local.txt b/requirements/local.txt index 0b60d4a..e7f6872 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -1,10 +1,12 @@ # Local development dependencies go here -r test.txt -django-debug-toolbar==1.2.2 -Sphinx==1.2.3 -sqlparse==0.1.14 -releases==0.7.0 -Pygments==2.0.2 +django-debug-toolbar==1.4 +sqlparse==0.1.18 +Sphinx==1.3.5 +Babel==2.2.0 +snowballstemmer==1.2.1 +releases==1.0.0 +Pygments==2.1 flake8==2.5.2 mccabe==0.4.0 pep8==1.7.0 diff --git a/requirements/test.txt b/requirements/test.txt index bb78fde..47897db 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,3 +1,3 @@ # Test dependencies go here. -r base.txt -coverage==3.7.1 +coverage==4.0.3 From 32366e93dd0affb8f22f105dd15219e822d7d33c Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 31 Jan 2016 23:29:56 +0100 Subject: [PATCH 09/29] Add setup.cfg for QA tools, fix flake8 warnings --- .gitignore | 1 + gvaldap/gvaldap/settings/base.py | 80 ++++++++++++++++--------------- gvaldap/gvaldap/settings/local.py | 4 +- gvaldap/gvaldap/settings/test.py | 2 +- gvaldap/gvaldap/wsgi.py | 2 +- gvaldap/setup.cfg | 16 +++++++ 6 files changed, 62 insertions(+), 43 deletions(-) create mode 100644 gvaldap/setup.cfg diff --git a/.gitignore b/.gitignore index debdad8..32dece9 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ Desktop.ini _build/ .vagrant/ .coverage +coverage-report/ diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py index f03937e..a837266 100644 --- a/gvaldap/gvaldap/settings/base.py +++ b/gvaldap/gvaldap/settings/base.py @@ -30,7 +30,7 @@ def get_env_variable(var_name): raise ImproperlyConfigured(error_msg) -########## PATH CONFIGURATION +# ######### PATH CONFIGURATION # Absolute filesystem path to the Django project directory: DJANGO_ROOT = dirname(dirname(abspath(__file__))) @@ -43,27 +43,27 @@ SITE_NAME = basename(DJANGO_ROOT) # Add our project to our pythonpath, this way we don't need to type our project # name in our dotted import paths: path.append(DJANGO_ROOT) -########## END PATH CONFIGURATION +# ######### END PATH CONFIGURATION -########## DEBUG CONFIGURATION +# ######### DEBUG CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#debug DEBUG = False - -########## MANAGER CONFIGURATION +# ######### MANAGER CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#admins ADMINS = ( - (get_env_variable('GVALDAP_ADMIN_NAME'), get_env_variable('GVALDAP_ADMIN_EMAIL')), + (get_env_variable('GVALDAP_ADMIN_NAME'), + get_env_variable('GVALDAP_ADMIN_EMAIL')), ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#managers MANAGERS = ADMINS -########## END MANAGER CONFIGURATION +# ######### END MANAGER CONFIGURATION -########## DATABASE CONFIGURATION +# ######### DATABASE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases DATABASES = { 'default': { @@ -82,10 +82,10 @@ DATABASES = { } } DATABASE_ROUTERS = ['ldapdb.router.Router'] -########## END DATABASE CONFIGURATION +# ######### END DATABASE CONFIGURATION -########## GENERAL CONFIGURATION +# ######### GENERAL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#time-zone TIME_ZONE = 'Europe/Berlin' @@ -103,52 +103,54 @@ USE_L10N = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz USE_TZ = True -########## END GENERAL CONFIGURATION +# ######### END GENERAL CONFIGURATION -########## MEDIA CONFIGURATION +# ######### MEDIA CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root MEDIA_ROOT = normpath(join(SITE_ROOT, 'media')) # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url MEDIA_URL = '/media/' -########## END MEDIA CONFIGURATION +# ######### END MEDIA CONFIGURATION -########## STATIC FILE CONFIGURATION +# ######### STATIC FILE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url STATIC_URL = '/static/' -# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders +# See: +# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders # noqa STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) -########## END STATIC FILE CONFIGURATION +# ######### END STATIC FILE CONFIGURATION -########## SECRET CONFIGURATION +# ######### SECRET CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # Note: This key should only be used for development and testing. SECRET_KEY = get_env_variable('GVALDAP_SECRETKEY') -########## END SECRET CONFIGURATION +# ######### END SECRET CONFIGURATION -########## SITE CONFIGURATION +# ######### SITE CONFIGURATION # Hosts/domain names that are valid for this site # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts ALLOWED_HOSTS = [] -########## END SITE CONFIGURATION +# ######### END SITE CONFIGURATION -########## FIXTURE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS +# ######### FIXTURE CONFIGURATION +# See: +# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS # noqa FIXTURE_DIRS = ( normpath(join(SITE_ROOT, 'fixtures')), ) -########## END FIXTURE CONFIGURATION +# ######### END FIXTURE CONFIGURATION -########## TEMPLATE CONFIGURATION +# ######### TEMPLATE CONFIGURATION # See: https://docs.djangoproject.com/en/1.9/ref/settings/#std:setting-TEMPLATES # noqa TEMPLATES = [ { @@ -172,10 +174,10 @@ TEMPLATES = [ }, ] -########## END TEMPLATE CONFIGURATION +# ######### END TEMPLATE CONFIGURATION -########## MIDDLEWARE CONFIGURATION +# ######### MIDDLEWARE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes MIDDLEWARE_CLASSES = ( # Default Django middleware. @@ -187,21 +189,21 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.locale.LocaleMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) -########## END MIDDLEWARE CONFIGURATION +# ######### END MIDDLEWARE CONFIGURATION -########## URL CONFIGURATION +# ######### URL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf ROOT_URLCONF = '%s.urls' % SITE_NAME -########## END URL CONFIGURATION +# ######### END URL CONFIGURATION -########## TEST RUNNER CONFIGURATION +# ######### TEST RUNNER CONFIGURATION TEST_RUNNER = 'django.test.runner.DiscoverRunner' -########## END TEST RUNNER CONFIGURATION +# ######### END TEST RUNNER CONFIGURATION -########## APP CONFIGURATION +# ######### APP CONFIGURATION DJANGO_APPS = ( # Default Django apps: 'django.contrib.auth', @@ -223,10 +225,10 @@ LOCAL_APPS = ( # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS -########## END APP CONFIGURATION +# ######### END APP CONFIGURATION -########## LOGGING CONFIGURATION +# ######### LOGGING CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#logging # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to @@ -265,13 +267,13 @@ LOGGING = { }, } } -########## END LOGGING CONFIGURATION +# ######### END LOGGING CONFIGURATION -########## WSGI CONFIGURATION +# ######### WSGI CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application WSGI_APPLICATION = '%s.wsgi.application' % SITE_NAME -########## END WSGI CONFIGURATION +# ######### END WSGI CONFIGURATION # ######### LDAP SETTINGS @@ -280,7 +282,7 @@ USER_BASE_DN = get_env_variable('GVALDAP_BASEDN_USER') # ######### END LDAP SETTINGS -########## CELERY CONFIGURATION +# ######### CELERY CONFIGURATION BROKER_URL = get_env_variable('GVALDAP_BROKER_URL') CELERY_RESULT_BACKEND = get_env_variable('GVALDAP_RESULTS_REDIS_URL') CELERY_TASK_RESULT_EXPIRES = None @@ -292,4 +294,4 @@ CELERY_ENABLE_UTC = True CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' -########## END CELERY CONFIGURATION +# ######### END CELERY CONFIGURATION diff --git a/gvaldap/gvaldap/settings/local.py b/gvaldap/gvaldap/settings/local.py index d0d8fef..308158e 100644 --- a/gvaldap/gvaldap/settings/local.py +++ b/gvaldap/gvaldap/settings/local.py @@ -36,8 +36,8 @@ CACHES = { # ######### END CACHE CONFIGURATION -########## TOOLBAR CONFIGURATION -# See: http://django-debug-toolbar.readthedocs.org/en/latest/installation.html#explicit-setup +# ######### TOOLBAR CONFIGURATION +# See: http://django-debug-toolbar.readthedocs.org/en/latest/installation.html#explicit-setup # noqa INSTALLED_APPS += ( 'debug_toolbar', ) diff --git a/gvaldap/gvaldap/settings/test.py b/gvaldap/gvaldap/settings/test.py index b83ae47..d424ce1 100644 --- a/gvaldap/gvaldap/settings/test.py +++ b/gvaldap/gvaldap/settings/test.py @@ -11,7 +11,7 @@ from .base import * # NOQA PASSWORD_HASHERS = ( 'django.contrib.auth.hashers.MD5PasswordHasher', ) -########## IN-MEMORY TEST DATABASE +# ######### IN-MEMORY TEST DATABASE DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", diff --git a/gvaldap/gvaldap/wsgi.py b/gvaldap/gvaldap/wsgi.py index af02caa..b297d4d 100644 --- a/gvaldap/gvaldap/wsgi.py +++ b/gvaldap/gvaldap/wsgi.py @@ -26,10 +26,10 @@ path.append(SITE_ROOT) # os.environ["DJANGO_SETTINGS_MODULE"] = "jajaja.settings" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gvaldap.settings.production") -from django.core.wsgi import get_wsgi_application # 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 # noqa application = get_wsgi_application() # Apply WSGI middleware here. diff --git a/gvaldap/setup.cfg b/gvaldap/setup.cfg new file mode 100644 index 0000000..f2bd595 --- /dev/null +++ b/gvaldap/setup.cfg @@ -0,0 +1,16 @@ +[pep8] +exclude = migrations + +[flake8] +exclude = migrations + +[coverage:run] +source = gvaldap,ldapentities,ldaptasks +branch = True + +[coverage:report] +omit = */migrations/*,*/tests/*.py,*/tests.py,gvaldap/settings/local.py,gvaldap/settings/production.py +show_missing = True + +[coverage:html] +directory = ../coverage-report From 4b060c51f4f7b3250b47c13e07d833d42430d2c3 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Mon, 1 Feb 2016 00:55:59 +0000 Subject: [PATCH 10/29] Add unit tests This commit adds test coverage for gvaldap and ldapentities and starts to provide coverage for ldaptasks using mockldap. --- gvaldap/gvaldap/celery.py | 7 +- gvaldap/gvaldap/settings/test.py | 17 ++- gvaldap/gvaldap/tests/__init__.py | 0 gvaldap/gvaldap/tests/test_celery.py | 16 +++ gvaldap/gvaldap/tests/test_settings.py | 27 +++++ gvaldap/gvaldap/tests/test_wsgi.py | 14 +++ gvaldap/ldapentities/models.py | 1 + gvaldap/ldapentities/tests/__init__.py | 0 gvaldap/ldapentities/tests/test_admin.py | 62 ++++++++++ gvaldap/ldapentities/tests/test_models.py | 37 ++++++ gvaldap/ldaptasks/tests/__init__.py | 0 gvaldap/ldaptasks/tests/test_tasks.py | 138 ++++++++++++++++++++++ requirements/test.txt | 1 + 13 files changed, 309 insertions(+), 11 deletions(-) create mode 100644 gvaldap/gvaldap/tests/__init__.py create mode 100644 gvaldap/gvaldap/tests/test_celery.py create mode 100644 gvaldap/gvaldap/tests/test_settings.py create mode 100644 gvaldap/gvaldap/tests/test_wsgi.py create mode 100644 gvaldap/ldapentities/tests/__init__.py create mode 100644 gvaldap/ldapentities/tests/test_admin.py create mode 100644 gvaldap/ldapentities/tests/test_models.py create mode 100644 gvaldap/ldaptasks/tests/__init__.py create mode 100644 gvaldap/ldaptasks/tests/test_tasks.py diff --git a/gvaldap/gvaldap/celery.py b/gvaldap/gvaldap/celery.py index e9a2f75..2219818 100644 --- a/gvaldap/gvaldap/celery.py +++ b/gvaldap/gvaldap/celery.py @@ -16,8 +16,11 @@ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gvaldap.settings.production') -#: The Celery application app = Celery('gvaldap') + +def get_installed_apps(): + return settings.INSTALLED_APPS + app.config_from_object('django.conf:settings') -app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) +app.autodiscover_tasks(get_installed_apps) diff --git a/gvaldap/gvaldap/settings/test.py b/gvaldap/gvaldap/settings/test.py index d424ce1..f52f224 100644 --- a/gvaldap/gvaldap/settings/test.py +++ b/gvaldap/gvaldap/settings/test.py @@ -12,16 +12,15 @@ PASSWORD_HASHERS = ( 'django.contrib.auth.hashers.MD5PasswordHasher', ) # ######### IN-MEMORY TEST DATABASE -DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": ":memory:", - "USER": "", - "PASSWORD": "", - "HOST": "", - "PORT": "", - }, +DATABASES['default'] = { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", } + LOGGING['handlers'].update({ 'console': { 'level': 'ERROR', diff --git a/gvaldap/gvaldap/tests/__init__.py b/gvaldap/gvaldap/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gvaldap/gvaldap/tests/test_celery.py b/gvaldap/gvaldap/tests/test_celery.py new file mode 100644 index 0000000..a7437e8 --- /dev/null +++ b/gvaldap/gvaldap/tests/test_celery.py @@ -0,0 +1,16 @@ +""" +This module implements tests for :py:mod:`gvaldap.celery`. + +""" +from __future__ import absolute_import + +from unittest import TestCase + +from gvaldap.celery import get_installed_apps +from django.conf import settings + + +class GetInstalledAppsTest(TestCase): + + def test_get_installed_apps(self): + self.assertEqual(get_installed_apps(), settings.INSTALLED_APPS) diff --git a/gvaldap/gvaldap/tests/test_settings.py b/gvaldap/gvaldap/tests/test_settings.py new file mode 100644 index 0000000..8fed62f --- /dev/null +++ b/gvaldap/gvaldap/tests/test_settings.py @@ -0,0 +1,27 @@ +""" +This module implements tests for :py:mod:`gvaldap.settings`. + +""" +from __future__ import absolute_import + +import os +from unittest import TestCase + +from django.core.exceptions import ImproperlyConfigured + +from gvaldap.settings.base import get_env_variable + + +class GetEnvVariableTest(TestCase): + + def test_get_existing_env_variable(self): + os.environ['testvariable'] = 'myvalue' + self.assertEqual(get_env_variable('testvariable'), 'myvalue') + + def test_get_missing_env_variable(self): + if 'missingvariable' in os.environ: + del os.environ['missingvariable'] + with self.assertRaises(ImproperlyConfigured) as e: + get_env_variable('missingvariable') + self.assertEqual( + str(e.exception), 'Set the missingvariable environment variable') diff --git a/gvaldap/gvaldap/tests/test_wsgi.py b/gvaldap/gvaldap/tests/test_wsgi.py new file mode 100644 index 0000000..4c9775d --- /dev/null +++ b/gvaldap/gvaldap/tests/test_wsgi.py @@ -0,0 +1,14 @@ +""" +This module provides tests for :py:mod:`gvaldap.wsgi`. + +""" +from __future__ import absolute_import + +from unittest import TestCase + + +class WSGITest(TestCase): + + def test_wsgi_application(self): + from gvaldap import wsgi + self.assertIsNotNone(wsgi.application) diff --git a/gvaldap/ldapentities/models.py b/gvaldap/ldapentities/models.py index 89ee373..0fd72f3 100644 --- a/gvaldap/ldapentities/models.py +++ b/gvaldap/ldapentities/models.py @@ -6,6 +6,7 @@ The models are based on :py:class:`ldapmodels.Model` from `django-ldapdb`_. .. _django-ldapdb: https://github.com/jlaine/django-ldapdb#readme """ +from __future__ import unicode_literals from django.conf import settings from django.utils.encoding import python_2_unicode_compatible diff --git a/gvaldap/ldapentities/tests/__init__.py b/gvaldap/ldapentities/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gvaldap/ldapentities/tests/test_admin.py b/gvaldap/ldapentities/tests/test_admin.py new file mode 100644 index 0000000..3b48e9b --- /dev/null +++ b/gvaldap/ldapentities/tests/test_admin.py @@ -0,0 +1,62 @@ +""" +This module provides tests for :py:mod:`ldapentities.admin`. + +""" +from __future__ import absolute_import + +from django.conf import settings +from django.core.urlresolvers import reverse +from django.test import TestCase +from django.contrib.auth import get_user_model + +from mockldap import MockLdap + + +User = get_user_model() + +TEST_USER = 'admin' +TEST_EMAIL = 'admin@example.org' +TEST_PASSWORD = 'secret' + +admin = ( + settings.DATABASES['ldap']['USER'], { + 'userPassword': [settings.DATABASES['ldap']['PASSWORD']]}) +groups = ( + settings.GROUP_BASE_DN, { + 'objectClass': ['top', 'organizationalUnit'], 'ou': ['groups']}) +users = ( + settings.USER_BASE_DN, { + 'objectClass': ['top', 'organizationalUnit'], 'ou': ['users']}) + + +class LdapUserAdminTest(TestCase): + directory = dict([admin, groups, users]) + + @classmethod + def setUpClass(cls): + cls.mockldap = MockLdap(cls.directory) + + @classmethod + def tearDownClass(cls): + del cls.mockldap + + def setUp(self): + User.objects.create_superuser( + TEST_USER, email=TEST_EMAIL, password=TEST_PASSWORD) + self.client.login(username=TEST_USER, password=TEST_PASSWORD) + self.mockldap.start() + self.ldapobj = self.mockldap[settings.DATABASES['ldap']['NAME']] + + def tearDown(self): + self.mockldap.stop() + del self.ldapobj + + def test_can_administer_groups(self): + response = self.client.get(reverse( + 'admin:ldapentities_ldapgroup_changelist')) + self.assertEqual(response.status_code, 200) + + def test_can_administer_users(self): + response = self.client.get(reverse( + 'admin:ldapentities_ldapuser_changelist')) + self.assertEqual(response.status_code, 200) diff --git a/gvaldap/ldapentities/tests/test_models.py b/gvaldap/ldapentities/tests/test_models.py new file mode 100644 index 0000000..b5557a6 --- /dev/null +++ b/gvaldap/ldapentities/tests/test_models.py @@ -0,0 +1,37 @@ +""" +This model provides tests for :py:mod:`ldapentities.models`. + +""" +from __future__ import absolute_import, unicode_literals +from django.test import TestCase + +from passlib.hash import ldap_salted_sha1 + +from ldapentities.models import LdapGroup, LdapUser + + +class LdapGroupTest(TestCase): + + def test___str__(self): + ldapgroup = LdapGroup( + gid=5000, name='test', description='test group') + self.assertEqual(str(ldapgroup), 'test') + + +class LdapUserTest(TestCase): + + def test___str__(self): + ldapuser = LdapUser( + uid=5000, group=5000, gecos="a test user", + home_directory='/home/test', login_shell='/bin/bash', + username='test', password='test', common_name='Test') + self.assertEqual(str(ldapuser), 'test') + + def test_set_password(self): + ldapuser = LdapUser( + uid=5000, group=5000, gecos="a test user", + home_directory='/home/test', login_shell='/bin/bash', + username='test', password='test', common_name='Test') + self.assertEqual(ldapuser.password, 'test') + ldapuser.set_password('test2') + self.assertTrue(ldap_salted_sha1.verify('test2', ldapuser.password)) diff --git a/gvaldap/ldaptasks/tests/__init__.py b/gvaldap/ldaptasks/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gvaldap/ldaptasks/tests/test_tasks.py b/gvaldap/ldaptasks/tests/test_tasks.py new file mode 100644 index 0000000..3b601f0 --- /dev/null +++ b/gvaldap/ldaptasks/tests/test_tasks.py @@ -0,0 +1,138 @@ +""" +This module provides tests for :py:mod:`ldaptasks.tasks`. + +""" +from __future__ import absolute_import + +from django.conf import settings +from django.test import TestCase +from celery.exceptions import Reject + +from mockldap import MockLdap + +from ldaptasks.tasks import create_ldap_group, create_ldap_user + + +class LdapTaskTestCase(TestCase): + directory = { + settings.DATABASES['ldap']['USER']: { + 'userPassword': [settings.DATABASES['ldap']['PASSWORD']] + }, + settings.GROUP_BASE_DN: { + 'objectClass': ['top', 'organizationalUnit'], + 'ou': ['groups'] + }, + settings.USER_BASE_DN: { + 'objectClass': ['top', 'organizationalUnit'], + 'ou': ['users'] + }, + 'cn=existing,' + settings.GROUP_BASE_DN: { + 'objectClass': ['posixGroup'], + 'gidNumber': ['4711'], + 'cn': ['existing'], + 'description': ['existing test group'], + 'memberUid': ['existing'], + }, + 'uid=existing,' + settings.USER_BASE_DN: { + 'objectClass': ['account', 'posixAccount'], + 'uidNumber': ['815'], + 'gidNumber': ['4711'], + 'gecos': ['existing test user'], + 'homeDirectory': ['/home/existing'], + 'loginShell': ['/bin/bash'], + 'uid': ['existing'], + 'userPassword': ['secret'], + 'cn': ['existing'] + } + } + + @classmethod + def setUpClass(cls): + cls.mockldap = MockLdap(cls.directory) + + @classmethod + def tearDownClass(cls): + del cls.mockldap + + def setUp(self): + self.mockldap.start() + self.ldapobj = self.mockldap[settings.DATABASES['ldap']['NAME']] + + def tearDown(self): + self.mockldap.stop() + del self.ldapobj + + def test_create_ldap_group(self): + dn = create_ldap_group('test', 5000, 'test group') + self.assertEqual('cn=test,%s' % settings.GROUP_BASE_DN, dn) + self.assertEquals( + self.ldapobj.methods_called(), + ['initialize', 'simple_bind_s', 'search_s', 'add_s'] + ) + + def test_create_ldap_group_existing(self): + dn = create_ldap_group('existing', 4711, 'existing test group') + self.assertEqual('cn=existing,%s' % settings.GROUP_BASE_DN, dn) + self.assertEquals( + self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', + 'search_s', 'search_s' + ] + ) + + def test_create_ldap_group_existing_modify(self): + dn = create_ldap_group('existing', 4711, 'change existing test group') + self.assertEqual('cn=existing,%s' % settings.GROUP_BASE_DN, dn) + self.assertEquals( + self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'modify_s' + ] + ) + + def test_create_ldap_user(self): + dn = create_ldap_user( + 'test', 5000, 4711, 'Test User', '/home/test', '/bin/bash', + 'secret') + self.assertEqual('uid=test,%s' % settings.USER_BASE_DN, dn) + self.assertEquals( + self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', + 'search_s', 'add_s', 'search_s', 'search_s', 'modify_s' + ] + ) + + def test_create_ldap_user_invalid_group(self): + with self.assertRaises(Reject): + create_ldap_user( + 'test', 5000, 5000, 'Test User', '/home/test', '/bin/bash', + 'secret') + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s' + ] + ) + + def test_create_ldap_user_no_password(self): + dn = create_ldap_user( + 'test', 5000, 4711, 'Test User', '/home/test', '/bin/bash', + None) + self.assertEqual('uid=test,%s' % settings.USER_BASE_DN, dn) + self.assertEquals( + self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', + 'search_s', 'add_s', 'search_s', 'search_s', 'modify_s' + ] + ) + + def test_create_ldap_user_existing(self): + dn = create_ldap_user( + 'existing', 815, 4711, 'existing test user', '/home/existing', + '/bin/bash', 'secret' + ) + self.assertEqual('uid=existing,%s' % settings.USER_BASE_DN, dn) + self.assertEquals( + self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'search_s', 'search_s', 'modify_s' + ] + ) diff --git a/requirements/test.txt b/requirements/test.txt index 47897db..2ba9934 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,3 +1,4 @@ # Test dependencies go here. -r base.txt coverage==4.0.3 +mockldap==0.2.6 From 23015af083c9e56972eb4a9201d79ff70f58a1fb Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Mon, 1 Feb 2016 23:37:39 +0100 Subject: [PATCH 11/29] Update Django and gvacommon dependencies This commit updates the Django dependency version to 1.9.2 and gvacommon to 0.3.0 that provides gvacommon.settings_utils.get_env_variable. The gnuviechadmin.settings.base module now uses this implementation instead of an own copy and the corresponding test has been removed too. --- gvaldap/gvaldap/settings/base.py | 21 +------------------- gvaldap/gvaldap/tests/test_settings.py | 27 -------------------------- requirements/base.txt | 4 ++-- 3 files changed, 3 insertions(+), 49 deletions(-) delete mode 100644 gvaldap/gvaldap/tests/test_settings.py diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py index a837266..a0b950b 100644 --- a/gvaldap/gvaldap/settings/base.py +++ b/gvaldap/gvaldap/settings/base.py @@ -5,29 +5,10 @@ Common settings and globals. """ -from os import environ from os.path import abspath, basename, dirname, join, normpath from sys import path -# Normally you should not import ANYTHING from Django directly -# into your settings, but ImproperlyConfigured is an exception. -from django.core.exceptions import ImproperlyConfigured - - -def get_env_variable(var_name): - """ - Get a setting from an environment variable. - - :param str var_name: variable name - :raises ImproperlyConfigured: if the environment setting is not defined - :return: environment setting value - :rtype: str - """ - try: - return environ[var_name] - except KeyError: - error_msg = "Set the %s environment variable" % var_name - raise ImproperlyConfigured(error_msg) +from gvacommon.settings_utils import get_env_variable # ######### PATH CONFIGURATION diff --git a/gvaldap/gvaldap/tests/test_settings.py b/gvaldap/gvaldap/tests/test_settings.py deleted file mode 100644 index 8fed62f..0000000 --- a/gvaldap/gvaldap/tests/test_settings.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -This module implements tests for :py:mod:`gvaldap.settings`. - -""" -from __future__ import absolute_import - -import os -from unittest import TestCase - -from django.core.exceptions import ImproperlyConfigured - -from gvaldap.settings.base import get_env_variable - - -class GetEnvVariableTest(TestCase): - - def test_get_existing_env_variable(self): - os.environ['testvariable'] = 'myvalue' - self.assertEqual(get_env_variable('testvariable'), 'myvalue') - - def test_get_missing_env_variable(self): - if 'missingvariable' in os.environ: - del os.environ['missingvariable'] - with self.assertRaises(ImproperlyConfigured) as e: - get_env_variable('missingvariable') - self.assertEqual( - str(e.exception), 'Set the missingvariable environment variable') diff --git a/requirements/base.txt b/requirements/base.txt index 72a3736..19c87b4 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,4 @@ -Django==1.9.1 +Django==1.9.2 Jinja2==2.8 #django-ldapdb==0.4.0 -e git+https://github.com/jandd/django-ldapdb@django19#egg=django-ldapdb @@ -16,5 +16,5 @@ pytz==2015.7 passlib==1.6.5 requests==2.9.1 simplejson==3.8.1 --e git+https://git.gnuviech-server.de/gvacommon.git@0.2.1#egg=gvacommon +-e git+https://git.gnuviech-server.de/gvacommon.git@0.3.0#egg=gvacommon redis==2.10.5 From 67ccdbb7c8b00c648c0d68b4dcad851f9e6dfd5e Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Mon, 1 Feb 2016 23:15:57 +0000 Subject: [PATCH 12/29] Add tests for ldaptasks functions This commit adds tests for ldaptasks.set_ldap_user_password, ldaptasks.add_ldap_user_to_group and ldaptasks.remove_ldap_user_from_group. --- gvaldap/ldaptasks/tests/test_tasks.py | 151 +++++++++++++++++++------- 1 file changed, 113 insertions(+), 38 deletions(-) diff --git a/gvaldap/ldaptasks/tests/test_tasks.py b/gvaldap/ldaptasks/tests/test_tasks.py index 3b601f0..125b6a5 100644 --- a/gvaldap/ldaptasks/tests/test_tasks.py +++ b/gvaldap/ldaptasks/tests/test_tasks.py @@ -10,7 +10,14 @@ from celery.exceptions import Reject from mockldap import MockLdap -from ldaptasks.tasks import create_ldap_group, create_ldap_user +from ldapentities.models import LdapUser +from ldaptasks.tasks import ( + add_ldap_user_to_group, + create_ldap_group, + create_ldap_user, + remove_ldap_user_from_group, + set_ldap_user_password, +) class LdapTaskTestCase(TestCase): @@ -65,42 +72,35 @@ class LdapTaskTestCase(TestCase): def test_create_ldap_group(self): dn = create_ldap_group('test', 5000, 'test group') self.assertEqual('cn=test,%s' % settings.GROUP_BASE_DN, dn) - self.assertEquals( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s', 'add_s'] - ) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'add_s' + ]) def test_create_ldap_group_existing(self): dn = create_ldap_group('existing', 4711, 'existing test group') self.assertEqual('cn=existing,%s' % settings.GROUP_BASE_DN, dn) - self.assertEquals( - self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', - 'search_s', 'search_s' - ] - ) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s' + ]) def test_create_ldap_group_existing_modify(self): dn = create_ldap_group('existing', 4711, 'change existing test group') self.assertEqual('cn=existing,%s' % settings.GROUP_BASE_DN, dn) - self.assertEquals( - self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'modify_s' - ] - ) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'modify_s' + ]) def test_create_ldap_user(self): dn = create_ldap_user( 'test', 5000, 4711, 'Test User', '/home/test', '/bin/bash', 'secret') self.assertEqual('uid=test,%s' % settings.USER_BASE_DN, dn) - self.assertEquals( - self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', - 'search_s', 'add_s', 'search_s', 'search_s', 'modify_s' - ] - ) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'add_s', 'search_s', 'search_s', 'modify_s' + ]) def test_create_ldap_user_invalid_group(self): with self.assertRaises(Reject): @@ -108,21 +108,18 @@ class LdapTaskTestCase(TestCase): 'test', 5000, 5000, 'Test User', '/home/test', '/bin/bash', 'secret') self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s' - ] - ) + 'initialize', 'simple_bind_s', 'search_s', 'search_s' + ]) def test_create_ldap_user_no_password(self): dn = create_ldap_user( 'test', 5000, 4711, 'Test User', '/home/test', '/bin/bash', None) self.assertEqual('uid=test,%s' % settings.USER_BASE_DN, dn) - self.assertEquals( - self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', - 'search_s', 'add_s', 'search_s', 'search_s', 'modify_s' - ] - ) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'add_s', 'search_s', 'search_s', 'modify_s' + ]) def test_create_ldap_user_existing(self): dn = create_ldap_user( @@ -130,9 +127,87 @@ class LdapTaskTestCase(TestCase): '/bin/bash', 'secret' ) self.assertEqual('uid=existing,%s' % settings.USER_BASE_DN, dn) - self.assertEquals( - self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'search_s', 'search_s', 'modify_s' - ] - ) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'search_s', 'modify_s' + ]) + + def test_set_ldap_user_password_existing(self): + res = set_ldap_user_password('existing', 'newpassword') + self.assertTrue(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s', 'modify_s' + ]) + + def test_set_ldap_user_password_missing(self): + res = set_ldap_user_password('missing', 'newpassword') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s' + ]) + + def test_add_ldap_user_to_group_existing(self): + res = add_ldap_user_to_group('existing', 'existing') + self.assertTrue(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s' + ]) + + def test_add_ldap_user_to_group_new_user(self): + create_ldap_group('test', 5000, 'test group') + res = add_ldap_user_to_group('existing', 'test') + self.assertTrue(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'add_s', 'search_s', + 'search_s', 'search_s', 'search_s', 'search_s', 'search_s', + 'modify_s' + ]) + + def test_add_ldap_user_to_group_no_group(self): + res = add_ldap_user_to_group('existing', 'test') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s' + ]) + + def test_add_ldap_user_to_group_no_user(self): + with self.assertRaises(LdapUser.DoesNotExist): + add_ldap_user_to_group('test', 'existing') + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s' + ]) + + def test_remove_ldap_user_from_group_existing(self): + res = remove_ldap_user_from_group('existing', 'existing') + self.assertTrue(res) + self.assertNotIn('memberUid', self.ldapobj.directory[ + 'cn=existing,' + settings.GROUP_BASE_DN]) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'search_s', 'modify_s' + ]) + + def test_remove_ldap_user_from_group_not_in_group(self): + create_ldap_group('test', 5000, 'test group') + res = remove_ldap_user_from_group('existing', 'test') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'add_s', 'search_s', + 'search_s', 'search_s', 'search_s' + ]) + + def test_remove_ldap_user_from_group_no_group(self): + res = remove_ldap_user_from_group('existing', 'test') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s' + ]) + + def test_remove_ldap_user_from_group_no_user(self): + res = remove_ldap_user_from_group('test', 'existing') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s' + ]) From 94aacf1398cfaf3c5c176800e665898e88ce3aa1 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 2 Feb 2016 18:31:37 +0000 Subject: [PATCH 13/29] Add tests for delete tasks This commit raises coverage for ldaptasks.tasks to 100% by adding tests for delete_ldap_group, delete_ldap_group_if_empty and delete_ldap_user tasks. --- gvaldap/ldaptasks/tests/test_tasks.py | 89 +++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/gvaldap/ldaptasks/tests/test_tasks.py b/gvaldap/ldaptasks/tests/test_tasks.py index 125b6a5..330604f 100644 --- a/gvaldap/ldaptasks/tests/test_tasks.py +++ b/gvaldap/ldaptasks/tests/test_tasks.py @@ -15,6 +15,9 @@ from ldaptasks.tasks import ( add_ldap_user_to_group, create_ldap_group, create_ldap_user, + delete_ldap_group, + delete_ldap_group_if_empty, + delete_ldap_user, remove_ldap_user_from_group, set_ldap_user_password, ) @@ -211,3 +214,89 @@ class LdapTaskTestCase(TestCase): self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s' ]) + + def test_delete_ldap_user_existing(self): + res = delete_ldap_user('existing') + self.assertTrue(res) + self.assertNotIn( + 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) + self.assertNotIn('memberUid', self.ldapobj.directory[ + 'cn=existing,' + settings.GROUP_BASE_DN]) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'search_s', 'modify_s', 'delete_s' + ]) + + def test_delete_ldap_user_missing(self): + res = delete_ldap_user('missing') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s' + ]) + + def test_delete_ldap_user_no_group(self): + self.ldapobj.directory[ + 'uid=existing,' + settings.USER_BASE_DN]['gidNumber'] = ['5000'] + res = delete_ldap_user('existing') + self.assertTrue(res) + self.assertNotIn( + 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'delete_s' + ]) + + def test_delete_ldap_user_not_in_group(self): + del self.ldapobj.directory[ + 'cn=existing,' + settings.GROUP_BASE_DN]['memberUid'] + res = delete_ldap_user('existing') + self.assertTrue(res) + self.assertNotIn( + 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s', 'delete_s' + ]) + + def test_delete_ldap_group_if_empty_nonempty(self): + res = delete_ldap_group_if_empty('existing') + self.assertFalse(res) + self.assertIn( + 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s' + ]) + + def test_delete_ldap_group_if_empty_missing(self): + res = delete_ldap_group_if_empty('missing') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s' + ]) + + def test_delete_ldap_group_if_empty_empty(self): + del self.ldapobj.directory[ + 'cn=existing,' + settings.GROUP_BASE_DN]['memberUid'] + res = delete_ldap_group_if_empty('existing') + self.assertTrue(res) + self.assertNotIn( + 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'delete_s' + ]) + + def test_delete_ldap_group_existing(self): + res = delete_ldap_group('existing') + self.assertTrue(res) + self.assertNotIn( + 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'delete_s' + ]) + + def test_delete_ldap_group_missing(self): + res = delete_ldap_group('missing') + self.assertFalse(res) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s' + ]) From 1a24cf9c5057c500a3e378fd0c72517d78bfae67 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sat, 6 Feb 2016 13:37:53 +0100 Subject: [PATCH 14/29] Change salt minion id in Vagrantfile --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index e101fd3..37cdbf2 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -58,7 +58,7 @@ Vagrant.configure(2) do |config| config.vm.provision :salt do |salt| salt.bootstrap_script = "salt/bootstrap.sh" - salt.minion_id = "gvadev" + salt.minion_id = "gvaldap" salt.masterless = true salt.run_highstate = true salt.verbose = true From 54875619aa432c52e36ccd42b350ecab7f54b147 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 7 Feb 2016 22:40:19 +0100 Subject: [PATCH 15/29] Mark LDAP field names as byte strings The django-ldapdb code cannot handle unicode field names with real LDAP directories. This commit marks the field names of LDAP entities as byte strings. --- gvaldap/ldapentities/models.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/gvaldap/ldapentities/models.py b/gvaldap/ldapentities/models.py index 0fd72f3..7d0d609 100644 --- a/gvaldap/ldapentities/models.py +++ b/gvaldap/ldapentities/models.py @@ -39,16 +39,16 @@ class LdapGroup(ldapmodels.Model): # LDAP meta-data base_dn = settings.GROUP_BASE_DN #: list of object classes - object_classes = ['posixGroup'] + object_classes = [b'posixGroup'] # posixGroup attributes #: group id (`gidNumber`) - gid = IntegerField(db_column='gidNumber', unique=True) + gid = IntegerField(db_column=b'gidNumber', unique=True) #: group name (`cn`) - name = CharField(db_column='cn', max_length=200, primary_key=True) + name = CharField(db_column=b'cn', max_length=200, primary_key=True) #: group description (`description`) - description = CharField(db_column='description') - members = ListField(db_column='memberUid', blank=True) + description = CharField(db_column=b'description') + members = ListField(db_column=b'memberUid', blank=True) def __str__(self): """ @@ -72,25 +72,25 @@ class LdapUser(ldapmodels.Model): """ base_dn = settings.USER_BASE_DN #: list of object classes - object_classes = ['account', 'posixAccount'] + object_classes = [b'account', b'posixAccount'] # posixAccount #: user id (`uidNumber`) - uid = IntegerField(db_column='uidNumber', unique=True) + uid = IntegerField(db_column=b'uidNumber', unique=True) #: group id (`gidNumber`) of the user's primary group - group = IntegerField(db_column='gidNumber') + group = IntegerField(db_column=b'gidNumber') #: GECOS field (`gecos`) - gecos = CharField(db_column='gecos') + gecos = CharField(db_column=b'gecos') #: home directory (`homeDirectory`) - home_directory = CharField(db_column='homeDirectory') + home_directory = CharField(db_column=b'homeDirectory') #: login shell (`loginShell`) - login_shell = CharField(db_column='loginShell', default='/bin/bash') + login_shell = CharField(db_column=b'loginShell', default='/bin/bash') #: user name (`uid`) - username = CharField(db_column='uid', primary_key=True) + username = CharField(db_column=b'uid', primary_key=True) #: password (`userPassword`) in an LDAP compatible format - password = CharField(db_column='userPassword') + password = CharField(db_column=b'userPassword') #: common name (`cn`) - common_name = CharField(db_column='cn') + common_name = CharField(db_column=b'cn') def __str__(self): """ From 2ff7dd8902611bdb42602534324a65c323a4a3ac Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 7 Feb 2016 22:41:36 +0100 Subject: [PATCH 16/29] Refactoring of ldaptasks All LDAP tasks return a dictionary now to allow chaining with other tasks, the new task delete_ldap_user_chained has been added to allow user deletion after other Celery tasks. --- gvaldap/ldaptasks/tasks.py | 142 +++++++++++++++++------- gvaldap/ldaptasks/tests/test_tasks.py | 152 ++++++++++++++++++-------- 2 files changed, 208 insertions(+), 86 deletions(-) diff --git a/gvaldap/ldaptasks/tasks.py b/gvaldap/ldaptasks/tasks.py index 05c2da8..50c0324 100644 --- a/gvaldap/ldaptasks/tasks.py +++ b/gvaldap/ldaptasks/tasks.py @@ -7,6 +7,7 @@ This module defines `Celery`_ tasks to manage LDAP entities. from __future__ import absolute_import +from copy import deepcopy from django.core.exceptions import ObjectDoesNotExist from celery import shared_task from celery.utils.log import get_task_logger @@ -22,7 +23,7 @@ _LOGGER = get_task_logger(__name__) @shared_task -def create_ldap_group(groupname, gid, descr): +def create_ldap_group(groupname, gid, description): """ This task creates an :py:class:`LDAP group ` if it does not exist yet. @@ -32,9 +33,12 @@ def create_ldap_group(groupname, gid, descr): :param str groupname: the group name :param int gid: the group id - :param str descr: description text for the group - :return: the distinguished name of the group - :rtype: str + :param str description: description text for the group + :return: dictionary containing groupname, gid, description and + :py:const:`group_dn` set to the distinguished name of the newly created + or existing LDAP group + :rtype: dict + """ try: ldapgroup = LdapGroup.objects.get(name=groupname) @@ -45,10 +49,15 @@ def create_ldap_group(groupname, gid, descr): except LdapGroup.DoesNotExist: ldapgroup = LdapGroup(gid=gid, name=groupname) _LOGGER.info('created LDAP group %s', ldapgroup.dn) - ldapgroup.description = descr + ldapgroup.description = description ldapgroup.save() _LOGGER.info('set description of LDAP group %s', ldapgroup.dn) - return ldapgroup.dn + return { + 'groupname': groupname, + 'gid': gid, + 'description': description, + 'group_dn': ldapgroup.dn, + } @shared_task @@ -71,8 +80,10 @@ def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): is passed the password is not touched :raises celery.exceptions.Reject: if the specified primary group does not exist - :return: the distinguished name of the user - :rtype: str + :return: dictionary containing username, uid, gid, gecos, homedir, shell, + password and :py:const:`user_dn` set to the distinguished name of the + newly created or existing LDAP user + :rtype: dict """ try: @@ -109,30 +120,42 @@ def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): _LOGGER.info( 'LDAP user %s has been added to LDAP group %s', ldapuser.dn, ldapgroup.dn) - return ldapuser.dn + return { + 'username': username, + 'uid': uid, + 'gid': gid, + 'gecos': gecos, + 'homedir': homedir, + 'shell': shell, + 'user_dn': ldapuser.dn, + } -@shared_task(bind=True) -def set_ldap_user_password(self, username, password): +@shared_task +def set_ldap_user_password(username, password): """ This task sets the password of an existing :py:class:`LDAP user `. :param str username: the user name :param str password: teh clear text password - :return: :py:const:`True` if the password has been set, :py:const:`False` - if the user does not exist. + :return: dictionary containing the username and a flag + :py:const:`password_set` that is set to :py:const:`True` if the + password has been set, :py:const:`False` if the user does not exist. + :rtype: dict """ + retval = {'username': username, 'password_set': False} try: ldapuser = LdapUser.objects.get(username=username) except LdapUser.DoesNotExist: _LOGGER.info('there is no LDAP user with username %s', username) - return False + return retval ldapuser.set_password(password) ldapuser.save() _LOGGER.info("set new password for LDAP user %s", ldapuser.dn) - return True + retval['password_set'] = True + return retval @shared_task(bind=True) @@ -146,10 +169,13 @@ def add_ldap_user_to_group(self, username, groupname): :param str groupname: the group name :raises celery.exceptions.Retry: if the user does not exist yet, :py:func:`create_ldap_user` should be called before - :return: True if the user has been added to the group otherwise False - :rtype: boolean + :return: dictionary containing the username, groupname and a flag + :py:const`added` that is as a :py:const:`True` if the user has been + added to the group otherwise to :py:const:`False` + :rtype: dict """ + retval = {'username': username, 'groupname': groupname, 'added': False} try: ldapgroup = LdapGroup.objects.get(name=groupname) ldapuser = LdapUser.objects.get(username=username) @@ -169,8 +195,8 @@ def add_ldap_user_to_group(self, username, groupname): _LOGGER.info( 'LDAP user %s is already in LDAP group %s', ldapuser.username, ldapgroup.dn) - return True - return False + retval['added'] = True + return retval @shared_task @@ -180,10 +206,13 @@ def remove_ldap_user_from_group(username, groupname): :param str username: the user name :param str groupname: the group name - :return: True if the user has been removed, False otherwise - :rtype: boolean + :return: dictionary containing the input parameters and a flag + :py:const:`removed` that is set to :py:const:`True` if the user has + been removed, False otherwise + :rtype: dict """ + retval = {'username': username, 'groupname': groupname, 'removed': False} try: ldapgroup = LdapGroup.objects.get(name=groupname) ldapuser = LdapUser.objects.get(username=username) @@ -198,24 +227,35 @@ def remove_ldap_user_from_group(username, groupname): 'removed LDAP user %s from LDAP group %s', ldapuser.dn, ldapgroup.dn) ldapgroup.save() - return True + retval['removed'] = True else: _LOGGER.info( 'LDAP user %s is not a member of LDAP group %s', ldapuser.dn, ldapgroup.dn) - return False + return retval @shared_task -def delete_ldap_user(username): +def delete_ldap_user(username, *args, **kwargs): """ This task deletes the given user. :param str username: the user name - :return: True if the user has been deleted, False otherwise - :rtype: boolean + :return: dictionary containing the username and a flag :py:const:`deleted` + that is set to :py:const:`True` if the user has been deleted and is set + to :py:const:`False` otherwise + :rtype: dict + + .. note:: + + This variant can only be used at the beginning of a Celery task chain + or as a standalone task. + + Use :py:func:`ldaptasks.tasks.delete_ldap_user_chained` at other + positions in the task chain """ + retval = {'username': username, 'deleted': False} try: ldapuser = LdapUser.objects.get(username=username) except LdapUser.DoesNotExist: @@ -237,20 +277,43 @@ def delete_ldap_user(username): userdn = ldapuser.dn ldapuser.delete() _LOGGER.info('deleted LDAP user %s', userdn) - return True - return False + retval['deleted'] = True + return retval + + +@shared_task +def delete_ldap_user_chained(previous_result, *args, **kwargs): + """ + This task deletes the given user. + + :param dict previous_result: a dictionary describing the result of the + previous step in the Celery task chain. This dictionary must contain a + :py:const:`username` key + :return: a copy of the :py:obj:`previous_result` dictionary with a new + :py:const:`deleted` key set to :py:const:`True` if the user has been + deleted and set to :py:const:`False` otherwise + :rtype: dict + + """ + username = previous_result['username'] + retval = deepcopy(previous_result) + retval.update(delete_ldap_user(username)) + return retval @shared_task def delete_ldap_group_if_empty(groupname): """ - This task deletes the given group. + This task deletes the given group if it is empty. :param str groupname: the group name - :return: True if the user has been deleted, False otherwise - :rtype: boolean + :return: dictionary that contains the groupname and a flag + :py:const:`deleted` that is set to :py:const:`True` if the group has + been deleted and is set to :py:const:`False` otherwise + :rtype: dict """ + retval = {'groupname': groupname, 'deleted': False} try: ldapgroup = LdapGroup.objects.get(name=groupname) except LdapGroup.DoesNotExist: @@ -261,24 +324,27 @@ def delete_ldap_group_if_empty(groupname): ldapgroup.delete() _LOGGER.info( 'deleted LDAP group %s', groupdn) - return True + retval['deleted'] = True else: _LOGGER.info( 'LDAP group %s has not been deleted. It still has %d members', ldapgroup.dn, len(ldapgroup.members)) - return False + return retval @shared_task def delete_ldap_group(groupname): """ - This taks deletes the given group. + This task deletes the given group. :param str groupname: the group name - :return: True if the user has been deleted, False otherwise - :rtype: boolean + :return: dictionary that contains the groupname and a flag + :py:const:`deleted` that is set to :py:const:`True` if the group has + been deleted and is set to :py:const:`False` otherwise + :rtype: dict """ + retval = {'groupname': groupname, 'deleted': False} try: ldapgroup = LdapGroup.objects.get(name=groupname) except LdapGroup.DoesNotExist: @@ -287,5 +353,5 @@ def delete_ldap_group(groupname): groupdn = ldapgroup.dn ldapgroup.delete() _LOGGER.info('deleted LDAP group %s', groupdn) - return True - return False + retval['deleted'] = True + return retval diff --git a/gvaldap/ldaptasks/tests/test_tasks.py b/gvaldap/ldaptasks/tests/test_tasks.py index 330604f..3661b10 100644 --- a/gvaldap/ldaptasks/tests/test_tasks.py +++ b/gvaldap/ldaptasks/tests/test_tasks.py @@ -18,6 +18,7 @@ from ldaptasks.tasks import ( delete_ldap_group, delete_ldap_group_if_empty, delete_ldap_user, + delete_ldap_user_chained, remove_ldap_user_from_group, set_ldap_user_password, ) @@ -73,33 +74,49 @@ class LdapTaskTestCase(TestCase): del self.ldapobj def test_create_ldap_group(self): - dn = create_ldap_group('test', 5000, 'test group') - self.assertEqual('cn=test,%s' % settings.GROUP_BASE_DN, dn) + result = create_ldap_group('test', 5000, 'test group') + self.assertEqual({ + 'groupname': 'test', 'gid': 5000, 'description': 'test group', + 'group_dn': 'cn=test,%s' % settings.GROUP_BASE_DN + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'add_s' ]) def test_create_ldap_group_existing(self): - dn = create_ldap_group('existing', 4711, 'existing test group') - self.assertEqual('cn=existing,%s' % settings.GROUP_BASE_DN, dn) + result = create_ldap_group('existing', 4711, 'existing test group') + self.assertEqual({ + 'groupname': 'existing', 'gid': 4711, + 'description': 'existing test group', + 'group_dn': 'cn=existing,%s' % settings.GROUP_BASE_DN + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'search_s' ]) def test_create_ldap_group_existing_modify(self): - dn = create_ldap_group('existing', 4711, 'change existing test group') - self.assertEqual('cn=existing,%s' % settings.GROUP_BASE_DN, dn) + result = create_ldap_group( + 'existing', 4711, 'change existing test group') + self.assertEqual({ + 'groupname': 'existing', 'gid': 4711, + 'description': 'change existing test group', + 'group_dn': 'cn=existing,%s' % settings.GROUP_BASE_DN + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'search_s', 'modify_s' ]) def test_create_ldap_user(self): - dn = create_ldap_user( + result = create_ldap_user( 'test', 5000, 4711, 'Test User', '/home/test', '/bin/bash', 'secret') - self.assertEqual('uid=test,%s' % settings.USER_BASE_DN, dn) + self.assertEqual({ + 'username': 'test', 'uid': 5000, 'gid': 4711, 'gecos': 'Test User', + 'homedir': '/home/test', 'shell': '/bin/bash', + 'user_dn': 'uid=test,%s' % settings.USER_BASE_DN + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'add_s', 'search_s', 'search_s', 'modify_s' @@ -115,44 +132,59 @@ class LdapTaskTestCase(TestCase): ]) def test_create_ldap_user_no_password(self): - dn = create_ldap_user( + result = create_ldap_user( 'test', 5000, 4711, 'Test User', '/home/test', '/bin/bash', None) - self.assertEqual('uid=test,%s' % settings.USER_BASE_DN, dn) + self.assertEqual({ + 'username': 'test', 'uid': 5000, 'gid': 4711, 'gecos': 'Test User', + 'homedir': '/home/test', 'shell': '/bin/bash', + 'user_dn': 'uid=test,%s' % settings.USER_BASE_DN + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'add_s', 'search_s', 'search_s', 'modify_s' ]) def test_create_ldap_user_existing(self): - dn = create_ldap_user( + result = create_ldap_user( 'existing', 815, 4711, 'existing test user', '/home/existing', '/bin/bash', 'secret' ) - self.assertEqual('uid=existing,%s' % settings.USER_BASE_DN, dn) + self.assertEqual({ + 'username': 'existing', 'uid': 815, 'gid': 4711, + 'gecos': 'existing test user', 'homedir': '/home/existing', + 'shell': '/bin/bash', + 'user_dn': u'uid=existing,%s' % settings.USER_BASE_DN + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'search_s', 'search_s', 'search_s', 'modify_s' ]) def test_set_ldap_user_password_existing(self): - res = set_ldap_user_password('existing', 'newpassword') - self.assertTrue(res) + result = set_ldap_user_password('existing', 'newpassword') + self.assertEqual({ + 'username': 'existing', 'password_set': True + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'search_s', 'modify_s' ]) def test_set_ldap_user_password_missing(self): - res = set_ldap_user_password('missing', 'newpassword') - self.assertFalse(res) + result = set_ldap_user_password('missing', 'newpassword') + self.assertEqual({ + 'username': 'missing', 'password_set': False + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s' ]) def test_add_ldap_user_to_group_existing(self): - res = add_ldap_user_to_group('existing', 'existing') - self.assertTrue(res) + result = add_ldap_user_to_group('existing', 'existing') + self.assertEqual({ + 'username': 'existing', 'groupname': 'existing', 'added': True + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', 'search_s' @@ -160,8 +192,10 @@ class LdapTaskTestCase(TestCase): def test_add_ldap_user_to_group_new_user(self): create_ldap_group('test', 5000, 'test group') - res = add_ldap_user_to_group('existing', 'test') - self.assertTrue(res) + result = add_ldap_user_to_group('existing', 'test') + self.assertEqual({ + 'username': 'existing', 'groupname': 'test', 'added': True + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'add_s', 'search_s', 'search_s', 'search_s', 'search_s', 'search_s', 'search_s', @@ -169,8 +203,10 @@ class LdapTaskTestCase(TestCase): ]) def test_add_ldap_user_to_group_no_group(self): - res = add_ldap_user_to_group('existing', 'test') - self.assertFalse(res) + result = add_ldap_user_to_group('existing', 'test') + self.assertEqual({ + 'username': 'existing', 'groupname': 'test', 'added': False + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s' ]) @@ -183,8 +219,10 @@ class LdapTaskTestCase(TestCase): ]) def test_remove_ldap_user_from_group_existing(self): - res = remove_ldap_user_from_group('existing', 'existing') - self.assertTrue(res) + result = remove_ldap_user_from_group('existing', 'existing') + self.assertEqual({ + 'username': 'existing', 'groupname': 'existing', 'removed': True + }, result) self.assertNotIn('memberUid', self.ldapobj.directory[ 'cn=existing,' + settings.GROUP_BASE_DN]) self.assertEqual(self.ldapobj.methods_called(), [ @@ -194,30 +232,36 @@ class LdapTaskTestCase(TestCase): def test_remove_ldap_user_from_group_not_in_group(self): create_ldap_group('test', 5000, 'test group') - res = remove_ldap_user_from_group('existing', 'test') - self.assertFalse(res) + result = remove_ldap_user_from_group('existing', 'test') + self.assertEqual({ + 'username': 'existing', 'groupname': 'test', 'removed': False + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'add_s', 'search_s', 'search_s', 'search_s', 'search_s' ]) def test_remove_ldap_user_from_group_no_group(self): - res = remove_ldap_user_from_group('existing', 'test') - self.assertFalse(res) + result = remove_ldap_user_from_group('existing', 'test') + self.assertEqual({ + 'username': 'existing', 'groupname': 'test', 'removed': False + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s' ]) def test_remove_ldap_user_from_group_no_user(self): - res = remove_ldap_user_from_group('test', 'existing') - self.assertFalse(res) + result = remove_ldap_user_from_group('test', 'existing') + self.assertEqual({ + 'username': 'test', 'groupname': 'existing', 'removed': False + }, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s' ]) def test_delete_ldap_user_existing(self): - res = delete_ldap_user('existing') - self.assertTrue(res) + result = delete_ldap_user('existing') + self.assertEqual({'username': 'existing', 'deleted': True}, result) self.assertNotIn( 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) self.assertNotIn('memberUid', self.ldapobj.directory[ @@ -228,8 +272,8 @@ class LdapTaskTestCase(TestCase): ]) def test_delete_ldap_user_missing(self): - res = delete_ldap_user('missing') - self.assertFalse(res) + result = delete_ldap_user('missing') + self.assertEqual({'username': 'missing', 'deleted': False}, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s' ]) @@ -237,8 +281,8 @@ class LdapTaskTestCase(TestCase): def test_delete_ldap_user_no_group(self): self.ldapobj.directory[ 'uid=existing,' + settings.USER_BASE_DN]['gidNumber'] = ['5000'] - res = delete_ldap_user('existing') - self.assertTrue(res) + result = delete_ldap_user('existing') + self.assertEqual({'username': 'existing', 'deleted': True}, result) self.assertNotIn( 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) self.assertEqual(self.ldapobj.methods_called(), [ @@ -249,8 +293,8 @@ class LdapTaskTestCase(TestCase): def test_delete_ldap_user_not_in_group(self): del self.ldapobj.directory[ 'cn=existing,' + settings.GROUP_BASE_DN]['memberUid'] - res = delete_ldap_user('existing') - self.assertTrue(res) + result = delete_ldap_user('existing') + self.assertEqual({'username': 'existing', 'deleted': True}, result) self.assertNotIn( 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) self.assertEqual(self.ldapobj.methods_called(), [ @@ -258,9 +302,21 @@ class LdapTaskTestCase(TestCase): 'search_s', 'delete_s' ]) + def test_delete_ldap_user_chained_exsting(self): + result = delete_ldap_user_chained({'username': 'existing'}) + self.assertEqual({'username': 'existing', 'deleted': True}, result) + self.assertNotIn( + 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) + self.assertNotIn('memberUid', self.ldapobj.directory[ + 'cn=existing,' + settings.GROUP_BASE_DN]) + self.assertEqual(self.ldapobj.methods_called(), [ + 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', + 'search_s', 'search_s', 'search_s', 'modify_s', 'delete_s' + ]) + def test_delete_ldap_group_if_empty_nonempty(self): - res = delete_ldap_group_if_empty('existing') - self.assertFalse(res) + result = delete_ldap_group_if_empty('existing') + self.assertEqual({'groupname': 'existing', 'deleted': False}, result) self.assertIn( 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) self.assertEqual(self.ldapobj.methods_called(), [ @@ -268,8 +324,8 @@ class LdapTaskTestCase(TestCase): ]) def test_delete_ldap_group_if_empty_missing(self): - res = delete_ldap_group_if_empty('missing') - self.assertFalse(res) + result = delete_ldap_group_if_empty('missing') + self.assertEqual({'groupname': 'missing', 'deleted': False}, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s' ]) @@ -277,8 +333,8 @@ class LdapTaskTestCase(TestCase): def test_delete_ldap_group_if_empty_empty(self): del self.ldapobj.directory[ 'cn=existing,' + settings.GROUP_BASE_DN]['memberUid'] - res = delete_ldap_group_if_empty('existing') - self.assertTrue(res) + result = delete_ldap_group_if_empty('existing') + self.assertEqual({'groupname': 'existing', 'deleted': True}, result) self.assertNotIn( 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) self.assertEqual(self.ldapobj.methods_called(), [ @@ -286,8 +342,8 @@ class LdapTaskTestCase(TestCase): ]) def test_delete_ldap_group_existing(self): - res = delete_ldap_group('existing') - self.assertTrue(res) + result = delete_ldap_group('existing') + self.assertEqual({'groupname': 'existing', 'deleted': True}, result) self.assertNotIn( 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) self.assertEqual(self.ldapobj.methods_called(), [ @@ -295,8 +351,8 @@ class LdapTaskTestCase(TestCase): ]) def test_delete_ldap_group_missing(self): - res = delete_ldap_group('missing') - self.assertFalse(res) + result = delete_ldap_group('missing') + self.assertEqual({'groupname': 'missing', 'deleted': False}, result) self.assertEqual(self.ldapobj.methods_called(), [ 'initialize', 'simple_bind_s', 'search_s' ]) From 937d0aff974dbc21ffcbdca8c4072aaba47881ee Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 25 Sep 2016 01:10:17 +0200 Subject: [PATCH 17/29] Improve Vagrant setup Use debian/contrib-jessie64 base box, install python-cryptography before saltstack bootstrap. --- Vagrantfile | 45 +++------------------------------------------ salt/bootstrap.sh | 5 +++++ 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 37cdbf2..4a99c82 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,58 +1,19 @@ # -*- mode: ruby -*- # vi: set ft=ruby : -# All Vagrant configuration is done below. The "2" in Vagrant.configure -# configures the configuration version (we support older styles for -# backwards compatibility). Please don't change it unless you know what -# you're doing. Vagrant.configure(2) do |config| - # The most common configuration options are documented and commented below. - # For a complete reference, please see the online documentation at - # https://docs.vagrantup.com. - - # Every Vagrant development environment requires a box. You can search for - # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "debian/jessie64" + config.vm.box = "debian/contrib-jessie64" config.vm.hostname = "gvaldap.local" - - # Disable automatic box update checking. If you disable this, then - # boxes will only be checked for updates when the user runs - # `vagrant box outdated`. This is not recommended. - # config.vm.box_check_update = false - - # Create a forwarded port mapping which allows access to a specific port - # within the machine from a port on the host machine. In the example below, - # accessing "localhost:8080" will access port 80 on the guest machine. - config.vm.network "forwarded_port", guest: 8000, host: 8001 - - # Create a private network, which allows host-only access to the machine - # using a specific IP. - # config.vm.network "private_network", ip: "192.168.33.10" config.vm.network "private_network", ip: "172.16.3.3" - # Create a public network, which generally matched to bridged network. - # Bridged networks make the machine appear as another physical device on - # your network. - # config.vm.network "public_network" + config.vm.network "forwarded_port", guest: 8000, host: 8001 - # Share an additional folder to the guest VM. The first argument is - # the path on the host to the actual folder. The second argument is - # the path on the guest to mount the folder. And the optional third - # argument is a set of non-required options. - # config.vm.synced_folder "../data", "/vagrant_data" config.vm.synced_folder "../gvasalt/states/", "/srv/salt/" config.vm.synced_folder "../gvasalt/pillar/", "/srv/pillar/" - # Provider-specific configuration so you can fine-tune various - # backing providers for Vagrant. These expose provider-specific options. - # Example for VirtualBox: - # config.vm.provider "virtualbox" do |vb| - # # Display the VirtualBox GUI when booting the machine - # vb.gui = true - # - # # Customize the amount of memory on the VM: + # vb.gui = true vb.memory = "512" end diff --git a/salt/bootstrap.sh b/salt/bootstrap.sh index 218f423..1ed0951 100755 --- a/salt/bootstrap.sh +++ b/salt/bootstrap.sh @@ -1,5 +1,10 @@ #!/bin/sh - +echo "deb http://httpredir.debian.org/debian jessie-backports main" >/etc/apt/sources.list.d/backports.list + +apt-get update +apt-get install -y -t jessie-backports python-cryptography + # We just download the bootstrap script by default and execute that. if [ -x /usr/bin/fetch ]; then /usr/bin/fetch -o - https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.sh | sh -s -- "$@" From 2d347e6e9636a2f56c8a085b792fd4dad82f7636 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 25 Sep 2016 01:10:45 +0200 Subject: [PATCH 18/29] Ignore PyCharm files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 32dece9..a3e8bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ _build/ .vagrant/ .coverage coverage-report/ +.idea/ From cab9e9701be3a3dda234dcccc0e7b0b6bc6609c1 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 25 Sep 2016 17:27:42 +0200 Subject: [PATCH 19/29] Protect /etc/salt/grains Make sure that the permissions of /etc/salt/grains only allow access for the root user. --- salt/bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/bootstrap.sh b/salt/bootstrap.sh index 1ed0951..b87fc55 100755 --- a/salt/bootstrap.sh +++ b/salt/bootstrap.sh @@ -30,6 +30,7 @@ pillar_roots: log_file: file:///dev/log EOF +umask 077 cat >/etc/salt/grains < Date: Fri, 10 Aug 2018 11:56:29 +0200 Subject: [PATCH 20/29] Update vagrant setup to stretch64 with LXC --- Vagrantfile | 9 ++------- salt/bootstrap.sh | 4 +--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 4a99c82..64decd5 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -2,21 +2,16 @@ # vi: set ft=ruby : Vagrant.configure(2) do |config| - config.vm.box = "debian/contrib-jessie64" + config.vm.box = "debian/stretch64" config.vm.hostname = "gvaldap.local" - config.vm.network "private_network", ip: "172.16.3.3" + config.vm.network "private_network", ip: "172.16.3.3", lxc__bridge_name: 'vlxcbr1' config.vm.network "forwarded_port", guest: 8000, host: 8001 config.vm.synced_folder "../gvasalt/states/", "/srv/salt/" config.vm.synced_folder "../gvasalt/pillar/", "/srv/pillar/" - config.vm.provider "virtualbox" do |vb| - # vb.gui = true - vb.memory = "512" - end - config.vm.provision :salt do |salt| salt.bootstrap_script = "salt/bootstrap.sh" salt.minion_id = "gvaldap" diff --git a/salt/bootstrap.sh b/salt/bootstrap.sh index b87fc55..faeed2e 100755 --- a/salt/bootstrap.sh +++ b/salt/bootstrap.sh @@ -1,9 +1,7 @@ #!/bin/sh - -echo "deb http://httpredir.debian.org/debian jessie-backports main" >/etc/apt/sources.list.d/backports.list - apt-get update -apt-get install -y -t jessie-backports python-cryptography +apt-get install -y python-cryptography # We just download the bootstrap script by default and execute that. if [ -x /usr/bin/fetch ]; then From ea07d533072acc4b8bb3559ed7fd59eb3c910125 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Wed, 26 Jun 2019 22:54:35 +0200 Subject: [PATCH 21/29] Change gvacommon dependency URL --- requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/base.txt b/requirements/base.txt index 19c87b4..20d2c12 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -16,5 +16,5 @@ pytz==2015.7 passlib==1.6.5 requests==2.9.1 simplejson==3.8.1 --e git+https://git.gnuviech-server.de/gvacommon.git@0.3.0#egg=gvacommon +-e git+https://git.dittberner.info/gnuviech/gvacommon.git@0.3.0#egg=gvacommon redis==2.10.5 From c4485945fc99057bea1251f67df7035c31867bec Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Mon, 2 Mar 2020 15:39:29 +0100 Subject: [PATCH 22/29] Use Pipenv for dependency management --- Pipfile | 33 +++ Pipfile.lock | 462 ++++++++++++++++++++++++++++++++++++ requirements.txt | 3 - requirements/base.txt | 20 -- requirements/local.txt | 13 - requirements/production.txt | 3 - requirements/test.txt | 4 - 7 files changed, 495 insertions(+), 43 deletions(-) create mode 100644 Pipfile create mode 100644 Pipfile.lock delete mode 100644 requirements.txt delete mode 100644 requirements/base.txt delete mode 100644 requirements/local.txt delete mode 100644 requirements/production.txt delete mode 100644 requirements/test.txt diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..570f4f0 --- /dev/null +++ b/Pipfile @@ -0,0 +1,33 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[[source]] +url = "https://$PYPI_GNUVIECH_USERNAME:${PYPI_GNUVIECH_PASSWORD}@pypi.gnuviech-server.de/simple" +name = "gnuviech" +verify_ssl = true + +[dev-packages] +Sphinx = "*" +coverage = "*" +django-debug-toolbar = "*" +releases = "==1.0.0" +volatildap = "*" + +[packages] +gvacommon = {version = "*",index = "gnuviech"} +Django = "<3" +amqp = "*" +celery = "*" +django-braces = "*" +django-ldapdb = "*" +django-model-utils = "*" +kombu = "*" +passlib = "*" +python-ldap = "*" +pytz = "*" +redis = "*" + +[requires] +python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..a551c9b --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,462 @@ +{ + "_meta": { + "hash": { + "sha256": "447a8091237b0e5a54b560066ec2329cce2fc5d564bbc2b37e2f9ec0c1af8ea2" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + }, + { + "name": "gnuviech", + "url": "https://$PYPI_GNUVIECH_USERNAME:${PYPI_GNUVIECH_PASSWORD}@pypi.gnuviech-server.de/simple", + "verify_ssl": true + } + ] + }, + "default": { + "amqp": { + "hashes": [ + "sha256:6e649ca13a7df3faacdc8bbb280aa9a6602d22fd9d545336077e573a1f4ff3b8", + "sha256:77f1aef9410698d20eaeac5b73a87817365f457a507d82edf292e12cbb83b08d" + ], + "index": "pypi", + "version": "==2.5.2" + }, + "billiard": { + "hashes": [ + "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede", + "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a" + ], + "version": "==3.6.3.0" + }, + "celery": { + "hashes": [ + "sha256:3c5fcd6bfcf9a6323cb742cfc121d1790d50cfeddf300ba723cfa0b356413f07", + "sha256:a650525303ee866fb0c62c82f68681fcc2183eebbfafae552c27d30125fe518b" + ], + "index": "pypi", + "version": "==4.4.1" + }, + "django": { + "hashes": [ + "sha256:1226168be1b1c7efd0e66ee79b0e0b58b2caa7ed87717909cd8a57bb13a7079a", + "sha256:9a4635813e2d498a3c01b10c701fe4a515d76dd290aaa792ccb65ca4ccb6b038" + ], + "index": "pypi", + "version": "==2.2.10" + }, + "django-braces": { + "hashes": [ + "sha256:83705b78948de00804bfacf40c315d001bb39630f35bbdd8588211c2d5b4d43f", + "sha256:a6d9b34cf3e4949635e54884097c30410d7964fc7bec7231445ea7079b8c5722" + ], + "index": "pypi", + "version": "==1.14.0" + }, + "django-ldapdb": { + "hashes": [ + "sha256:36990757f26c1bd7642bbb0ed88cc1a4d8fe945dfcae6094142b9889b976e3f8", + "sha256:6c2d3b645fab20f97f1d33d8924114b85f699fca1bdf2cdd251074fa0331d75e" + ], + "index": "pypi", + "version": "==1.4.0" + }, + "django-model-utils": { + "hashes": [ + "sha256:9cf882e5b604421b62dbe57ad2b18464dc9c8f963fc3f9831badccae66c1139c", + "sha256:adf09e5be15122a7f4e372cb5a6dd512bbf8d78a23a90770ad0983ee9d909061" + ], + "index": "pypi", + "version": "==4.0.0" + }, + "gvacommon": { + "hashes": [ + "sha256:adf1ebc824433196d112764c61d9ca869481d33f612818c2840069f57ab42c25" + ], + "index": "gnuviech", + "version": "==0.5.0" + }, + "importlib-metadata": { + "hashes": [ + "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302", + "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b" + ], + "markers": "python_version < '3.8'", + "version": "==1.5.0" + }, + "kombu": { + "hashes": [ + "sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76", + "sha256:598e7e749d6ab54f646b74b2d2df67755dee13894f73ab02a2a9feb8870c7cb2" + ], + "index": "pypi", + "version": "==4.6.8" + }, + "passlib": { + "hashes": [ + "sha256:68c35c98a7968850e17f1b6892720764cc7eed0ef2b7cb3116a89a28e43fe177", + "sha256:8d666cef936198bc2ab47ee9b0410c94adf2ba798e5a84bf220be079ae7ab6a8" + ], + "index": "pypi", + "version": "==1.7.2" + }, + "pyasn1": { + "hashes": [ + "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", + "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba" + ], + "version": "==0.4.8" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", + "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74" + ], + "version": "==0.2.8" + }, + "python-ldap": { + "hashes": [ + "sha256:7d1c4b15375a533564aad3d3deade789221e450052b21ebb9720fb822eccdb8e" + ], + "index": "pypi", + "version": "==3.2.0" + }, + "pytz": { + "hashes": [ + "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", + "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" + ], + "index": "pypi", + "version": "==2019.3" + }, + "redis": { + "hashes": [ + "sha256:0dcfb335921b88a850d461dc255ff4708294943322bd55de6cfd68972490ca1f", + "sha256:b205cffd05ebfd0a468db74f0eedbff8df1a7bfc47521516ade4692991bb0833" + ], + "index": "pypi", + "version": "==3.4.1" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "sqlparse": { + "hashes": [ + "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e", + "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548" + ], + "version": "==0.3.1" + }, + "vine": { + "hashes": [ + "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87", + "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af" + ], + "version": "==1.3.0" + }, + "zipp": { + "hashes": [ + "sha256:12248a63bbdf7548f89cb4c7cda4681e537031eda29c02ea29674bc6854460c2", + "sha256:7c0f8e91abc0dc07a5068f315c52cb30c66bfbc581e5b50704c8a2f6ebae794a" + ], + "version": "==3.0.0" + } + }, + "develop": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "asgiref": { + "hashes": [ + "sha256:7e06d934a7718bf3975acbf87780ba678957b87c7adc056f13b6215d610695a0", + "sha256:ea448f92fc35a0ef4b1508f53a04c4670255a3f33d22a81c8fc9c872036adbe5" + ], + "version": "==3.2.3" + }, + "babel": { + "hashes": [ + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" + ], + "version": "==2.8.0" + }, + "certifi": { + "hashes": [ + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + ], + "version": "==2019.11.28" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "coverage": { + "hashes": [ + "sha256:15cf13a6896048d6d947bf7d222f36e4809ab926894beb748fc9caa14605d9c3", + "sha256:1daa3eceed220f9fdb80d5ff950dd95112cd27f70d004c7918ca6dfc6c47054c", + "sha256:1e44a022500d944d42f94df76727ba3fc0a5c0b672c358b61067abb88caee7a0", + "sha256:25dbf1110d70bab68a74b4b9d74f30e99b177cde3388e07cc7272f2168bd1477", + "sha256:3230d1003eec018ad4a472d254991e34241e0bbd513e97a29727c7c2f637bd2a", + "sha256:3dbb72eaeea5763676a1a1efd9b427a048c97c39ed92e13336e726117d0b72bf", + "sha256:5012d3b8d5a500834783689a5d2292fe06ec75dc86ee1ccdad04b6f5bf231691", + "sha256:51bc7710b13a2ae0c726f69756cf7ffd4362f4ac36546e243136187cfcc8aa73", + "sha256:527b4f316e6bf7755082a783726da20671a0cc388b786a64417780b90565b987", + "sha256:722e4557c8039aad9592c6a4213db75da08c2cd9945320220634f637251c3894", + "sha256:76e2057e8ffba5472fd28a3a010431fd9e928885ff480cb278877c6e9943cc2e", + "sha256:77afca04240c40450c331fa796b3eab6f1e15c5ecf8bf2b8bee9706cd5452fef", + "sha256:7afad9835e7a651d3551eab18cbc0fdb888f0a6136169fbef0662d9cdc9987cf", + "sha256:9bea19ac2f08672636350f203db89382121c9c2ade85d945953ef3c8cf9d2a68", + "sha256:a8b8ac7876bc3598e43e2603f772d2353d9931709345ad6c1149009fd1bc81b8", + "sha256:b0840b45187699affd4c6588286d429cd79a99d509fe3de0f209594669bb0954", + "sha256:b26aaf69713e5674efbde4d728fb7124e429c9466aeaf5f4a7e9e699b12c9fe2", + "sha256:b63dd43f455ba878e5e9f80ba4f748c0a2156dde6e0e6e690310e24d6e8caf40", + "sha256:be18f4ae5a9e46edae3f329de2191747966a34a3d93046dbdf897319923923bc", + "sha256:c312e57847db2526bc92b9bfa78266bfbaabac3fdcd751df4d062cd4c23e46dc", + "sha256:c60097190fe9dc2b329a0eb03393e2e0829156a589bd732e70794c0dd804258e", + "sha256:c62a2143e1313944bf4a5ab34fd3b4be15367a02e9478b0ce800cb510e3bbb9d", + "sha256:cc1109f54a14d940b8512ee9f1c3975c181bbb200306c6d8b87d93376538782f", + "sha256:cd60f507c125ac0ad83f05803063bed27e50fa903b9c2cfee3f8a6867ca600fc", + "sha256:d513cc3db248e566e07a0da99c230aca3556d9b09ed02f420664e2da97eac301", + "sha256:d649dc0bcace6fcdb446ae02b98798a856593b19b637c1b9af8edadf2b150bea", + "sha256:d7008a6796095a79544f4da1ee49418901961c97ca9e9d44904205ff7d6aa8cb", + "sha256:da93027835164b8223e8e5af2cf902a4c80ed93cb0909417234f4a9df3bcd9af", + "sha256:e69215621707119c6baf99bda014a45b999d37602cb7043d943c76a59b05bf52", + "sha256:ea9525e0fef2de9208250d6c5aeeee0138921057cd67fcef90fbed49c4d62d37", + "sha256:fca1669d464f0c9831fd10be2eef6b86f5ebd76c724d1e0706ebdff86bb4adf0" + ], + "index": "pypi", + "version": "==5.0.3" + }, + "django": { + "hashes": [ + "sha256:1226168be1b1c7efd0e66ee79b0e0b58b2caa7ed87717909cd8a57bb13a7079a", + "sha256:9a4635813e2d498a3c01b10c701fe4a515d76dd290aaa792ccb65ca4ccb6b038" + ], + "index": "pypi", + "version": "==2.2.10" + }, + "django-debug-toolbar": { + "hashes": [ + "sha256:eabbefe89881bbe4ca7c980ff102e3c35c8e8ad6eb725041f538988f2f39a943", + "sha256:ff94725e7aae74b133d0599b9bf89bd4eb8f5d2c964106e61d11750228c8774c" + ], + "index": "pypi", + "version": "==2.2" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "version": "==0.16" + }, + "idna": { + "hashes": [ + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + ], + "version": "==2.9" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "version": "==1.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" + ], + "version": "==2.11.1" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "version": "==1.1.1" + }, + "packaging": { + "hashes": [ + "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73", + "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334" + ], + "version": "==20.1" + }, + "pygments": { + "hashes": [ + "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b", + "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe" + ], + "version": "==2.5.2" + }, + "pyparsing": { + "hashes": [ + "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", + "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + ], + "version": "==2.4.6" + }, + "pytz": { + "hashes": [ + "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", + "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" + ], + "index": "pypi", + "version": "==2019.3" + }, + "releases": { + "hashes": [ + "sha256:23792ba473dca124e1b60f3bb6428d775b84b05ee73c0bfd1ba8439b833c5749", + "sha256:a9e65295578bf2e352ccc86d33c12b6b7ba27e3da1342d2ffee7f3f7d602a604" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "requests": { + "hashes": [ + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + ], + "version": "==2.23.0" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", + "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + ], + "version": "==2.0.0" + }, + "sphinx": { + "hashes": [ + "sha256:776ff8333181138fae52df65be733127539623bb46cc692e7fa0fcfc80d7aa88", + "sha256:ca762da97c3b5107cbf0ab9e11d3ec7ab8d3c31377266fd613b962ed971df709" + ], + "index": "pypi", + "version": "==2.4.3" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "version": "==1.1.4" + }, + "sqlparse": { + "hashes": [ + "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e", + "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548" + ], + "version": "==0.3.1" + }, + "urllib3": { + "hashes": [ + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + ], + "version": "==1.25.8" + }, + "volatildap": { + "hashes": [ + "sha256:7ef4cac02c4f907b87d5e3f5e872287a874d0c0d0a7c1054a8caae8e9c17b367", + "sha256:d9ef3ee7fcdf8d3ae1dd243e0a8c3892e404e4552caa60153fa0de97287bcfc6" + ], + "index": "pypi", + "version": "==1.3.0" + } + } +} diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d119713..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -# This file is here because many Platforms as a Service look for -# requirements.txt in the root directory of a project. --r requirements/production.txt diff --git a/requirements/base.txt b/requirements/base.txt deleted file mode 100644 index 20d2c12..0000000 --- a/requirements/base.txt +++ /dev/null @@ -1,20 +0,0 @@ -Django==1.9.2 -Jinja2==2.8 -#django-ldapdb==0.4.0 --e git+https://github.com/jandd/django-ldapdb@django19#egg=django-ldapdb -python-ldap==2.4.25 -bpython==0.15 -curtsies==0.2.6 -django-braces==1.8.1 -django-model-utils==2.4 -logutils==0.3.3 -celery==3.1.20 -amqp==1.4.9 -billiard==3.3.0.22 -kombu==3.0.33 -pytz==2015.7 -passlib==1.6.5 -requests==2.9.1 -simplejson==3.8.1 --e git+https://git.dittberner.info/gnuviech/gvacommon.git@0.3.0#egg=gvacommon -redis==2.10.5 diff --git a/requirements/local.txt b/requirements/local.txt deleted file mode 100644 index e7f6872..0000000 --- a/requirements/local.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Local development dependencies go here --r test.txt -django-debug-toolbar==1.4 -sqlparse==0.1.18 -Sphinx==1.3.5 -Babel==2.2.0 -snowballstemmer==1.2.1 -releases==1.0.0 -Pygments==2.1 -flake8==2.5.2 -mccabe==0.4.0 -pep8==1.7.0 -pyflakes==1.0.0 diff --git a/requirements/production.txt b/requirements/production.txt deleted file mode 100644 index 696dc7c..0000000 --- a/requirements/production.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Pro-tip: Try not to put anything here. There should be no dependency in -# production that isn't in development. --r base.txt diff --git a/requirements/test.txt b/requirements/test.txt deleted file mode 100644 index 2ba9934..0000000 --- a/requirements/test.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Test dependencies go here. --r base.txt -coverage==4.0.3 -mockldap==0.2.6 From 427fdd9c03fc11aaebb7e365d4702250d40ddfd9 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Mon, 2 Mar 2020 15:40:08 +0100 Subject: [PATCH 23/29] Fix compatibility with Django 2.2 and other dependencies - drop mockldap in favour of volatildap - fix URLs and settings - fix tests --- .gitignore | 1 + gvaldap/gvaldap/celery.py | 5 +- gvaldap/{ => gvaldap}/ldaptasks/__init__.py | 0 gvaldap/{ => gvaldap}/ldaptasks/tasks.py | 0 .../{ => gvaldap}/ldaptasks/tests/__init__.py | 0 .../ldaptasks/tests/test_tasks.py | 191 +++++------------- gvaldap/gvaldap/settings/base.py | 4 +- gvaldap/gvaldap/settings/local.py | 2 +- gvaldap/gvaldap/tests/test_celery.py | 2 - gvaldap/gvaldap/tests/test_wsgi.py | 2 - gvaldap/gvaldap/urls.py | 18 +- gvaldap/ldapentities/admin.py | 2 +- gvaldap/ldapentities/models.py | 31 ++- gvaldap/ldapentities/tests/test_admin.py | 43 ++-- gvaldap/setup.cfg | 2 +- 15 files changed, 106 insertions(+), 197 deletions(-) rename gvaldap/{ => gvaldap}/ldaptasks/__init__.py (100%) rename gvaldap/{ => gvaldap}/ldaptasks/tasks.py (100%) rename gvaldap/{ => gvaldap}/ldaptasks/tests/__init__.py (100%) rename gvaldap/{ => gvaldap}/ldaptasks/tests/test_tasks.py (54%) diff --git a/.gitignore b/.gitignore index a3e8bd7..d9cffa9 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ _build/ .coverage coverage-report/ .idea/ +.env \ No newline at end of file diff --git a/gvaldap/gvaldap/celery.py b/gvaldap/gvaldap/celery.py index 2219818..7544110 100644 --- a/gvaldap/gvaldap/celery.py +++ b/gvaldap/gvaldap/celery.py @@ -4,10 +4,7 @@ This module defines the Celery_ app for gvaldap. .. _Celery: http://www.celeryproject.org/ """ -from __future__ import absolute_import - import os - from celery import Celery from django.conf import settings @@ -15,12 +12,12 @@ from django.conf import settings os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gvaldap.settings.production') - app = Celery('gvaldap') def get_installed_apps(): return settings.INSTALLED_APPS + app.config_from_object('django.conf:settings') app.autodiscover_tasks(get_installed_apps) diff --git a/gvaldap/ldaptasks/__init__.py b/gvaldap/gvaldap/ldaptasks/__init__.py similarity index 100% rename from gvaldap/ldaptasks/__init__.py rename to gvaldap/gvaldap/ldaptasks/__init__.py diff --git a/gvaldap/ldaptasks/tasks.py b/gvaldap/gvaldap/ldaptasks/tasks.py similarity index 100% rename from gvaldap/ldaptasks/tasks.py rename to gvaldap/gvaldap/ldaptasks/tasks.py diff --git a/gvaldap/ldaptasks/tests/__init__.py b/gvaldap/gvaldap/ldaptasks/tests/__init__.py similarity index 100% rename from gvaldap/ldaptasks/tests/__init__.py rename to gvaldap/gvaldap/ldaptasks/tests/__init__.py diff --git a/gvaldap/ldaptasks/tests/test_tasks.py b/gvaldap/gvaldap/ldaptasks/tests/test_tasks.py similarity index 54% rename from gvaldap/ldaptasks/tests/test_tasks.py rename to gvaldap/gvaldap/ldaptasks/tests/test_tasks.py index 3661b10..b0c1ce8 100644 --- a/gvaldap/ldaptasks/tests/test_tasks.py +++ b/gvaldap/gvaldap/ldaptasks/tests/test_tasks.py @@ -2,16 +2,13 @@ This module provides tests for :py:mod:`ldaptasks.tasks`. """ -from __future__ import absolute_import - +import volatildap from django.conf import settings from django.test import TestCase from celery.exceptions import Reject -from mockldap import MockLdap - from ldapentities.models import LdapUser -from ldaptasks.tasks import ( +from gvaldap.ldaptasks.tasks import ( add_ldap_user_to_group, create_ldap_group, create_ldap_user, @@ -25,9 +22,13 @@ from ldaptasks.tasks import ( class LdapTaskTestCase(TestCase): + databases = ["default", "ldap"] + directory = { settings.DATABASES['ldap']['USER']: { - 'userPassword': [settings.DATABASES['ldap']['PASSWORD']] + 'objectClass': ['person'], + 'userPassword': [settings.DATABASES['ldap']['PASSWORD']], + 'sn': 'Admin', }, settings.GROUP_BASE_DN: { 'objectClass': ['top', 'organizationalUnit'], @@ -59,19 +60,23 @@ class LdapTaskTestCase(TestCase): @classmethod def setUpClass(cls): - cls.mockldap = MockLdap(cls.directory) + super(LdapTaskTestCase, cls).setUpClass() + cls.ldap_server = volatildap.LdapServer( + initial_data=cls.directory, + schemas=['core.schema', 'cosine.schema', 'inetorgperson.schema', + 'nis.schema'], + ) + settings.DATABASES['ldap']['USER'] = cls.ldap_server.rootdn + settings.DATABASES['ldap']['PASSWORD'] = cls.ldap_server.rootpw + settings.DATABASES['ldap']['NAME'] = cls.ldap_server.uri @classmethod def tearDownClass(cls): - del cls.mockldap + cls.ldap_server.stop() + super(LdapTaskTestCase, cls).tearDownClass() def setUp(self): - self.mockldap.start() - self.ldapobj = self.mockldap[settings.DATABASES['ldap']['NAME']] - - def tearDown(self): - self.mockldap.stop() - del self.ldapobj + self.ldap_server.start() def test_create_ldap_group(self): result = create_ldap_group('test', 5000, 'test group') @@ -79,9 +84,6 @@ class LdapTaskTestCase(TestCase): 'groupname': 'test', 'gid': 5000, 'description': 'test group', 'group_dn': 'cn=test,%s' % settings.GROUP_BASE_DN }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'add_s' - ]) def test_create_ldap_group_existing(self): result = create_ldap_group('existing', 4711, 'existing test group') @@ -90,10 +92,6 @@ class LdapTaskTestCase(TestCase): 'description': 'existing test group', 'group_dn': 'cn=existing,%s' % settings.GROUP_BASE_DN }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s' - ]) def test_create_ldap_group_existing_modify(self): result = create_ldap_group( @@ -103,10 +101,6 @@ class LdapTaskTestCase(TestCase): 'description': 'change existing test group', 'group_dn': 'cn=existing,%s' % settings.GROUP_BASE_DN }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'modify_s' - ]) def test_create_ldap_user(self): result = create_ldap_user( @@ -117,19 +111,12 @@ class LdapTaskTestCase(TestCase): 'homedir': '/home/test', 'shell': '/bin/bash', 'user_dn': 'uid=test,%s' % settings.USER_BASE_DN }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'add_s', 'search_s', 'search_s', 'modify_s' - ]) def test_create_ldap_user_invalid_group(self): with self.assertRaises(Reject): create_ldap_user( 'test', 5000, 5000, 'Test User', '/home/test', '/bin/bash', 'secret') - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s' - ]) def test_create_ldap_user_no_password(self): result = create_ldap_user( @@ -140,10 +127,6 @@ class LdapTaskTestCase(TestCase): 'homedir': '/home/test', 'shell': '/bin/bash', 'user_dn': 'uid=test,%s' % settings.USER_BASE_DN }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'add_s', 'search_s', 'search_s', 'modify_s' - ]) def test_create_ldap_user_existing(self): result = create_ldap_user( @@ -151,44 +134,29 @@ class LdapTaskTestCase(TestCase): '/bin/bash', 'secret' ) self.assertEqual({ - 'username': 'existing', 'uid': 815, 'gid': 4711, + 'username': 'existing', 'uid': 815, 'gid': 4711, 'gecos': 'existing test user', 'homedir': '/home/existing', 'shell': '/bin/bash', 'user_dn': u'uid=existing,%s' % settings.USER_BASE_DN }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'search_s', 'modify_s' - ]) def test_set_ldap_user_password_existing(self): result = set_ldap_user_password('existing', 'newpassword') self.assertEqual({ 'username': 'existing', 'password_set': True }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s', 'modify_s' - ]) def test_set_ldap_user_password_missing(self): result = set_ldap_user_password('missing', 'newpassword') self.assertEqual({ 'username': 'missing', 'password_set': False }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s' - ]) def test_add_ldap_user_to_group_existing(self): result = add_ldap_user_to_group('existing', 'existing') self.assertEqual({ 'username': 'existing', 'groupname': 'existing', 'added': True }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s' - ]) def test_add_ldap_user_to_group_new_user(self): create_ldap_group('test', 5000, 'test group') @@ -196,39 +164,24 @@ class LdapTaskTestCase(TestCase): self.assertEqual({ 'username': 'existing', 'groupname': 'test', 'added': True }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'add_s', 'search_s', - 'search_s', 'search_s', 'search_s', 'search_s', 'search_s', - 'modify_s' - ]) def test_add_ldap_user_to_group_no_group(self): result = add_ldap_user_to_group('existing', 'test') self.assertEqual({ 'username': 'existing', 'groupname': 'test', 'added': False }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s' - ]) def test_add_ldap_user_to_group_no_user(self): with self.assertRaises(LdapUser.DoesNotExist): add_ldap_user_to_group('test', 'existing') - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s' - ]) def test_remove_ldap_user_from_group_existing(self): result = remove_ldap_user_from_group('existing', 'existing') self.assertEqual({ 'username': 'existing', 'groupname': 'existing', 'removed': True }, result) - self.assertNotIn('memberUid', self.ldapobj.directory[ - 'cn=existing,' + settings.GROUP_BASE_DN]) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'search_s', 'modify_s' - ]) + self.assertNotIn('memberUid', self.ldap_server.get( + 'cn=existing,' + settings.GROUP_BASE_DN)) def test_remove_ldap_user_from_group_not_in_group(self): create_ldap_group('test', 5000, 'test group') @@ -236,123 +189,75 @@ class LdapTaskTestCase(TestCase): self.assertEqual({ 'username': 'existing', 'groupname': 'test', 'removed': False }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'add_s', 'search_s', - 'search_s', 'search_s', 'search_s' - ]) def test_remove_ldap_user_from_group_no_group(self): result = remove_ldap_user_from_group('existing', 'test') self.assertEqual({ 'username': 'existing', 'groupname': 'test', 'removed': False }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s' - ]) def test_remove_ldap_user_from_group_no_user(self): result = remove_ldap_user_from_group('test', 'existing') self.assertEqual({ 'username': 'test', 'groupname': 'existing', 'removed': False }, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s' - ]) def test_delete_ldap_user_existing(self): result = delete_ldap_user('existing') self.assertEqual({'username': 'existing', 'deleted': True}, result) - self.assertNotIn( - 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) - self.assertNotIn('memberUid', self.ldapobj.directory[ - 'cn=existing,' + settings.GROUP_BASE_DN]) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'search_s', 'modify_s', 'delete_s' - ]) + with self.assertRaises(KeyError): + self.ldap_server.get('uid=existing,' + settings.USER_BASE_DN) + self.assertNotIn('memberUid', self.ldap_server.get( + 'cn=existing,' + settings.GROUP_BASE_DN)) def test_delete_ldap_user_missing(self): result = delete_ldap_user('missing') self.assertEqual({'username': 'missing', 'deleted': False}, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s' - ]) def test_delete_ldap_user_no_group(self): - self.ldapobj.directory[ - 'uid=existing,' + settings.USER_BASE_DN]['gidNumber'] = ['5000'] + self.ldap_server.get('uid=existing,' + settings.USER_BASE_DN)[ + 'gidNumber'] = '5000' result = delete_ldap_user('existing') self.assertEqual({'username': 'existing', 'deleted': True}, result) - self.assertNotIn( - 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'delete_s' - ]) - - def test_delete_ldap_user_not_in_group(self): - del self.ldapobj.directory[ - 'cn=existing,' + settings.GROUP_BASE_DN]['memberUid'] - result = delete_ldap_user('existing') - self.assertEqual({'username': 'existing', 'deleted': True}, result) - self.assertNotIn( - 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s', 'delete_s' - ]) + with self.assertRaises(KeyError): + self.ldap_server.get('uid=existing,' + settings.USER_BASE_DN) def test_delete_ldap_user_chained_exsting(self): result = delete_ldap_user_chained({'username': 'existing'}) self.assertEqual({'username': 'existing', 'deleted': True}, result) - self.assertNotIn( - 'uid=existing,' + settings.USER_BASE_DN, self.ldapobj.directory) - self.assertNotIn('memberUid', self.ldapobj.directory[ - 'cn=existing,' + settings.GROUP_BASE_DN]) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'search_s', - 'search_s', 'search_s', 'search_s', 'modify_s', 'delete_s' - ]) + with self.assertRaises(KeyError): + self.ldap_server.get('uid=existing,' + settings.USER_BASE_DN) + group_object = self.ldap_server.get('cn=existing,' + settings.GROUP_BASE_DN) + self.assertNotIn('memberUid', group_object) def test_delete_ldap_group_if_empty_nonempty(self): result = delete_ldap_group_if_empty('existing') self.assertEqual({'groupname': 'existing', 'deleted': False}, result) - self.assertIn( - 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s' - ]) + ldap_object = self.ldap_server.get('cn=existing,' + settings.GROUP_BASE_DN) + self.assertIsNotNone(ldap_object) def test_delete_ldap_group_if_empty_missing(self): result = delete_ldap_group_if_empty('missing') self.assertEqual({'groupname': 'missing', 'deleted': False}, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s' - ]) def test_delete_ldap_group_if_empty_empty(self): - del self.ldapobj.directory[ - 'cn=existing,' + settings.GROUP_BASE_DN]['memberUid'] - result = delete_ldap_group_if_empty('existing') - self.assertEqual({'groupname': 'existing', 'deleted': True}, result) - self.assertNotIn( - 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'delete_s' - ]) + self.ldap_server.add({'cn=emptygroup,' + settings.GROUP_BASE_DN: { + 'objectClass': ['posixGroup'], + 'gidNumber': ['4712'], + 'cn': ['existing'], + 'description': ['existing test group'], + }}) + result = delete_ldap_group_if_empty('emptygroup') + self.assertEqual({'groupname': 'emptygroup', 'deleted': True}, result) + with self.assertRaises(KeyError): + self.ldap_server.get('cn=emptygroup,' + settings.GROUP_BASE_DN) def test_delete_ldap_group_existing(self): result = delete_ldap_group('existing') self.assertEqual({'groupname': 'existing', 'deleted': True}, result) - self.assertNotIn( - 'cn=existing,' + settings.GROUP_BASE_DN, self.ldapobj.directory) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s', 'search_s', 'delete_s' - ]) + with self.assertRaises(KeyError): + self.ldap_server.get('cn=existing,' + settings.GROUP_BASE_DN) def test_delete_ldap_group_missing(self): result = delete_ldap_group('missing') self.assertEqual({'groupname': 'missing', 'deleted': False}, result) - self.assertEqual(self.ldapobj.methods_called(), [ - 'initialize', 'simple_bind_s', 'search_s' - ]) diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py index a0b950b..632322d 100644 --- a/gvaldap/gvaldap/settings/base.py +++ b/gvaldap/gvaldap/settings/base.py @@ -160,7 +160,7 @@ TEMPLATES = [ # ######### MIDDLEWARE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( # Default Django middleware. 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -201,7 +201,7 @@ DJANGO_APPS = ( # Apps specific for this project go here. LOCAL_APPS = ( 'ldapentities', - 'ldaptasks', + 'gvaldap.ldaptasks', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps diff --git a/gvaldap/gvaldap/settings/local.py b/gvaldap/gvaldap/settings/local.py index 308158e..08e2b91 100644 --- a/gvaldap/gvaldap/settings/local.py +++ b/gvaldap/gvaldap/settings/local.py @@ -42,7 +42,7 @@ INSTALLED_APPS += ( 'debug_toolbar', ) -MIDDLEWARE_CLASSES += ( +MIDDLEWARE += ( 'debug_toolbar.middleware.DebugToolbarMiddleware', ) diff --git a/gvaldap/gvaldap/tests/test_celery.py b/gvaldap/gvaldap/tests/test_celery.py index a7437e8..b74f16d 100644 --- a/gvaldap/gvaldap/tests/test_celery.py +++ b/gvaldap/gvaldap/tests/test_celery.py @@ -2,8 +2,6 @@ This module implements tests for :py:mod:`gvaldap.celery`. """ -from __future__ import absolute_import - from unittest import TestCase from gvaldap.celery import get_installed_apps diff --git a/gvaldap/gvaldap/tests/test_wsgi.py b/gvaldap/gvaldap/tests/test_wsgi.py index 4c9775d..9042d6d 100644 --- a/gvaldap/gvaldap/tests/test_wsgi.py +++ b/gvaldap/gvaldap/tests/test_wsgi.py @@ -2,8 +2,6 @@ This module provides tests for :py:mod:`gvaldap.wsgi`. """ -from __future__ import absolute_import - from unittest import TestCase diff --git a/gvaldap/gvaldap/urls.py b/gvaldap/gvaldap/urls.py index 1ca71d4..6febbd9 100644 --- a/gvaldap/gvaldap/urls.py +++ b/gvaldap/gvaldap/urls.py @@ -3,14 +3,15 @@ This module defines the main URLConf for gvaldap. """ -from django.conf.urls import include, url from django.conf import settings - +from django.conf.urls import include, url from django.contrib import admin +from django.contrib.staticfiles.urls import staticfiles_urlpatterns + admin.autodiscover() urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), ] # Uncomment the next line to serve media files in dev. @@ -18,6 +19,11 @@ urlpatterns = [ if settings.DEBUG: # pragma: no cover import debug_toolbar - urlpatterns += [ - url(r'^__debug__/', include(debug_toolbar.urls)), - ] + + urlpatterns = ( + [ + url(r'^__debug__/', include(debug_toolbar.urls)), + ] + + staticfiles_urlpatterns() + + urlpatterns + ) diff --git a/gvaldap/ldapentities/admin.py b/gvaldap/ldapentities/admin.py index 6e5deb2..2ce5919 100644 --- a/gvaldap/ldapentities/admin.py +++ b/gvaldap/ldapentities/admin.py @@ -7,7 +7,7 @@ Admin classes for easy `django admin`_ based administration of LDAP entities. from django.contrib import admin -from .models import ( +from ldapentities.models import ( LdapGroup, LdapUser, ) diff --git a/gvaldap/ldapentities/models.py b/gvaldap/ldapentities/models.py index 7d0d609..d8b8796 100644 --- a/gvaldap/ldapentities/models.py +++ b/gvaldap/ldapentities/models.py @@ -9,7 +9,6 @@ The models are based on :py:class:`ldapmodels.Model` from `django-ldapdb`_. from __future__ import unicode_literals from django.conf import settings -from django.utils.encoding import python_2_unicode_compatible from ldapdb.models.fields import ( CharField, IntegerField, @@ -20,7 +19,6 @@ import ldapdb.models as ldapmodels from passlib.hash import ldap_salted_sha1 -@python_2_unicode_compatible class LdapGroup(ldapmodels.Model): """ Class for representing an LDAP group entity with objectClass `posixGroup`. @@ -39,16 +37,16 @@ class LdapGroup(ldapmodels.Model): # LDAP meta-data base_dn = settings.GROUP_BASE_DN #: list of object classes - object_classes = [b'posixGroup'] + object_classes = ['posixGroup'] # posixGroup attributes #: group id (`gidNumber`) - gid = IntegerField(db_column=b'gidNumber', unique=True) + gid = IntegerField(db_column='gidNumber', unique=True) #: group name (`cn`) - name = CharField(db_column=b'cn', max_length=200, primary_key=True) + name = CharField(db_column='cn', max_length=200, primary_key=True) #: group description (`description`) - description = CharField(db_column=b'description') - members = ListField(db_column=b'memberUid', blank=True) + description = CharField(db_column='description') + members = ListField(db_column='memberUid', blank=True) def __str__(self): """ @@ -57,7 +55,6 @@ class LdapGroup(ldapmodels.Model): return self.name -@python_2_unicode_compatible class LdapUser(ldapmodels.Model): """ Class for representing an LDAP user entity with objectClasses `account` and @@ -72,25 +69,25 @@ class LdapUser(ldapmodels.Model): """ base_dn = settings.USER_BASE_DN #: list of object classes - object_classes = [b'account', b'posixAccount'] + object_classes = ['account', 'posixAccount'] # posixAccount #: user id (`uidNumber`) - uid = IntegerField(db_column=b'uidNumber', unique=True) + uid = IntegerField(db_column='uidNumber', unique=True) #: group id (`gidNumber`) of the user's primary group - group = IntegerField(db_column=b'gidNumber') + group = IntegerField(db_column='gidNumber') #: GECOS field (`gecos`) - gecos = CharField(db_column=b'gecos') + gecos = CharField(db_column='gecos') #: home directory (`homeDirectory`) - home_directory = CharField(db_column=b'homeDirectory') + home_directory = CharField(db_column='homeDirectory') #: login shell (`loginShell`) - login_shell = CharField(db_column=b'loginShell', default='/bin/bash') + login_shell = CharField(db_column='loginShell', default='/bin/bash') #: user name (`uid`) - username = CharField(db_column=b'uid', primary_key=True) + username = CharField(db_column='uid', primary_key=True) #: password (`userPassword`) in an LDAP compatible format - password = CharField(db_column=b'userPassword') + password = CharField(db_column='userPassword') #: common name (`cn`) - common_name = CharField(db_column=b'cn') + common_name = CharField(db_column='cn') def __str__(self): """ diff --git a/gvaldap/ldapentities/tests/test_admin.py b/gvaldap/ldapentities/tests/test_admin.py index 3b48e9b..d9281c5 100644 --- a/gvaldap/ldapentities/tests/test_admin.py +++ b/gvaldap/ldapentities/tests/test_admin.py @@ -4,13 +4,11 @@ This module provides tests for :py:mod:`ldapentities.admin`. """ from __future__ import absolute_import +import volatildap from django.conf import settings -from django.core.urlresolvers import reverse from django.test import TestCase from django.contrib.auth import get_user_model - -from mockldap import MockLdap - +from django.urls import reverse User = get_user_model() @@ -18,38 +16,47 @@ TEST_USER = 'admin' TEST_EMAIL = 'admin@example.org' TEST_PASSWORD = 'secret' -admin = ( - settings.DATABASES['ldap']['USER'], { - 'userPassword': [settings.DATABASES['ldap']['PASSWORD']]}) -groups = ( - settings.GROUP_BASE_DN, { - 'objectClass': ['top', 'organizationalUnit'], 'ou': ['groups']}) +admin = (settings.DATABASES['ldap']['USER'], { + 'objectClass': ['person'], + 'userPassword': [ + settings.DATABASES['ldap'][ + 'PASSWORD']], + 'sn': 'Admin', +}) + +groups = (settings.GROUP_BASE_DN, { + 'objectClass': ['top', 'organizationalUnit'], 'ou': ['groups']}) users = ( settings.USER_BASE_DN, { 'objectClass': ['top', 'organizationalUnit'], 'ou': ['users']}) class LdapUserAdminTest(TestCase): + databases = ["default", "ldap"] directory = dict([admin, groups, users]) @classmethod def setUpClass(cls): - cls.mockldap = MockLdap(cls.directory) + super(LdapUserAdminTest, cls).setUpClass() + cls.ldap_server = volatildap.LdapServer( + initial_data=cls.directory, + schemas=['core.schema', 'cosine.schema', 'inetorgperson.schema', + 'nis.schema'], + ) + settings.DATABASES['ldap']['USER'] = cls.ldap_server.rootdn + settings.DATABASES['ldap']['PASSWORD'] = cls.ldap_server.rootpw + settings.DATABASES['ldap']['NAME'] = cls.ldap_server.uri @classmethod def tearDownClass(cls): - del cls.mockldap + cls.ldap_server.stop() + super(LdapUserAdminTest, cls).tearDownClass() def setUp(self): User.objects.create_superuser( TEST_USER, email=TEST_EMAIL, password=TEST_PASSWORD) self.client.login(username=TEST_USER, password=TEST_PASSWORD) - self.mockldap.start() - self.ldapobj = self.mockldap[settings.DATABASES['ldap']['NAME']] - - def tearDown(self): - self.mockldap.stop() - del self.ldapobj + self.ldap_server.start() def test_can_administer_groups(self): response = self.client.get(reverse( diff --git a/gvaldap/setup.cfg b/gvaldap/setup.cfg index f2bd595..3776715 100644 --- a/gvaldap/setup.cfg +++ b/gvaldap/setup.cfg @@ -5,7 +5,7 @@ exclude = migrations exclude = migrations [coverage:run] -source = gvaldap,ldapentities,ldaptasks +source = gvaldap,ldapentities,gvaldap.ldaptasks branch = True [coverage:report] From 34f788e099636e86fcbc2f83f9af5f632793392d Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 3 Mar 2020 12:20:13 +0100 Subject: [PATCH 24/29] Reorganize package structure This commit reorganizes the package structure. The gvaldap.settings modules have been merged. The gvaldap.ldaptasks module has been move up one level to have task names without the gvaldap prefix. isort control instructions have been added to setup.cfg. --- gvaldap/gvaldap/__init__.py | 4 + gvaldap/gvaldap/celery.py | 23 -- gvaldap/gvaldap/settings.py | 315 ++++++++++++++++++ gvaldap/gvaldap/settings/__init__.py | 3 - gvaldap/gvaldap/settings/base.py | 278 ---------------- gvaldap/gvaldap/settings/local.py | 64 ---- gvaldap/gvaldap/settings/production.py | 35 -- gvaldap/gvaldap/settings/test.py | 35 -- gvaldap/gvaldap/tests/test_celery.py | 14 - gvaldap/gvaldap/wsgi.py | 11 +- gvaldap/{gvaldap => }/ldaptasks/__init__.py | 0 gvaldap/ldaptasks/celery.py | 17 + gvaldap/{gvaldap => }/ldaptasks/tasks.py | 145 ++++---- .../{gvaldap => }/ldaptasks/tests/__init__.py | 0 .../ldaptasks/tests/test_tasks.py | 7 +- gvaldap/manage.py | 2 +- gvaldap/setup.cfg | 13 +- 17 files changed, 434 insertions(+), 532 deletions(-) delete mode 100644 gvaldap/gvaldap/celery.py create mode 100644 gvaldap/gvaldap/settings.py delete mode 100644 gvaldap/gvaldap/settings/__init__.py delete mode 100644 gvaldap/gvaldap/settings/base.py delete mode 100644 gvaldap/gvaldap/settings/local.py delete mode 100644 gvaldap/gvaldap/settings/production.py delete mode 100644 gvaldap/gvaldap/settings/test.py delete mode 100644 gvaldap/gvaldap/tests/test_celery.py rename gvaldap/{gvaldap => }/ldaptasks/__init__.py (100%) create mode 100644 gvaldap/ldaptasks/celery.py rename gvaldap/{gvaldap => }/ldaptasks/tasks.py (72%) rename gvaldap/{gvaldap => }/ldaptasks/tests/__init__.py (100%) rename gvaldap/{gvaldap => }/ldaptasks/tests/test_tasks.py (99%) diff --git a/gvaldap/gvaldap/__init__.py b/gvaldap/gvaldap/__init__.py index 613629e..1c758d0 100644 --- a/gvaldap/gvaldap/__init__.py +++ b/gvaldap/gvaldap/__init__.py @@ -2,3 +2,7 @@ This is the gvaldap project module. """ __version__ = "0.6.0.dev1" + +from ldaptasks.celery import app as celery_app + +__all__ = ("celery_app",) diff --git a/gvaldap/gvaldap/celery.py b/gvaldap/gvaldap/celery.py deleted file mode 100644 index 7544110..0000000 --- a/gvaldap/gvaldap/celery.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -This module defines the Celery_ app for gvaldap. - -.. _Celery: http://www.celeryproject.org/ - -""" -import os -from celery import Celery - -from django.conf import settings - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', - 'gvaldap.settings.production') - -app = Celery('gvaldap') - - -def get_installed_apps(): - return settings.INSTALLED_APPS - - -app.config_from_object('django.conf:settings') -app.autodiscover_tasks(get_installed_apps) diff --git a/gvaldap/gvaldap/settings.py b/gvaldap/gvaldap/settings.py new file mode 100644 index 0000000..648c190 --- /dev/null +++ b/gvaldap/gvaldap/settings.py @@ -0,0 +1,315 @@ +# -*- coding: utf-8 -*- +# pymode:lint_ignore=E501 +""" +Common settings and globals. + +""" + +from os.path import abspath, basename, dirname, join, normpath +from sys import path + +from gvacommon.settings_utils import get_env_variable + +# ######### PATH CONFIGURATION +# Absolute filesystem path to the Django project directory: +DJANGO_ROOT = dirname(dirname(abspath(__file__))) + +# Absolute filesystem path to the top-level project folder: +SITE_ROOT = dirname(DJANGO_ROOT) + +# Site name: +SITE_NAME = basename(DJANGO_ROOT) + +# Add our project to our pythonpath, this way we don't need to type our project +# name in our dotted import paths: +path.append(DJANGO_ROOT) +# ######### END PATH CONFIGURATION + + +# ######### DEBUG CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug +DEBUG = get_env_variable("GVALDAP_DEBUG", bool, False) + +# ######### MANAGER CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins +ADMINS = ( + (get_env_variable("GVALDAP_ADMIN_NAME"), get_env_variable("GVALDAP_ADMIN_EMAIL")), +) + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers +MANAGERS = ADMINS +# ######### END MANAGER CONFIGURATION + + +# ######### DATABASE CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": normpath(join(DJANGO_ROOT, "default.db")), + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", + }, + "ldap": { + "ENGINE": "ldapdb.backends.ldap", + "NAME": get_env_variable("GVALDAP_LDAP_URL"), + "USER": get_env_variable("GVALDAP_LDAP_USER"), + "PASSWORD": get_env_variable("GVALDAP_LDAP_PASSWORD"), + }, +} +DATABASE_ROUTERS = ["ldapdb.router.Router"] +# ######### END DATABASE CONFIGURATION + + +# ######### GENERAL CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#time-zone +TIME_ZONE = "Europe/Berlin" + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code +LANGUAGE_CODE = "en-us" + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id +SITE_ID = 1 + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n +USE_I18N = True + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n +USE_L10N = True + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz +USE_TZ = True +# ######### END GENERAL CONFIGURATION + + +# ######### MEDIA CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root +MEDIA_ROOT = normpath(join(SITE_ROOT, "media")) + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url +MEDIA_URL = "/media/" +# ######### END MEDIA CONFIGURATION + + +# ######### STATIC FILE CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url +STATIC_URL = "/static/" + +# See: +# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders # noqa +STATICFILES_FINDERS = ("django.contrib.staticfiles.finders.AppDirectoriesFinder",) +# ######### END STATIC FILE CONFIGURATION + + +# ######### SECRET CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key +# Note: This key should only be used for development and testing. +SECRET_KEY = get_env_variable("GVALDAP_SECRETKEY") +# ######### END SECRET CONFIGURATION + + +# ######### FIXTURE CONFIGURATION +# See: +# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS # noqa +FIXTURE_DIRS = (normpath(join(SITE_ROOT, "fixtures")),) +# ######### END FIXTURE CONFIGURATION + + +# ######### TEMPLATE CONFIGURATION +# See: https://docs.djangoproject.com/en/1.9/ref/settings/#std:setting-TEMPLATES # noqa +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [normpath(join(SITE_ROOT, "templates"))], + "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.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", + "django.template.context_processors.request", + ] + }, + } +] + +# ######### END TEMPLATE CONFIGURATION + + +# ######### MIDDLEWARE CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes +MIDDLEWARE = ( + # Default Django middleware. + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.locale.LocaleMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +) +# ######### END MIDDLEWARE CONFIGURATION + + +# ######### URL CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf +ROOT_URLCONF = "%s.urls" % SITE_NAME +# ######### END URL CONFIGURATION + + +# ######### TEST RUNNER CONFIGURATION +TEST_RUNNER = "django.test.runner.DiscoverRunner" +# ######### END TEST RUNNER CONFIGURATION + + +# ######### APP CONFIGURATION +DJANGO_APPS = ( + # Default Django apps: + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + # Admin panel and documentation: + "django.contrib.admin", +) + +# Apps specific for this project go here. +LOCAL_APPS = ("ldapentities", "ldaptasks") + +# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps +INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS +# ######### END APP CONFIGURATION + + +# ######### LOGGING CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging +# 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, + "formatters": { + "verbose": { + "format": "%(levelname)s %(asctime)s %(name)s " + "%(module)s:%(lineno)d %(process)d %(thread)d %(message)s" + }, + "simple": {"format": "%(levelname)s %(name)s:%(lineno)d %(message)s"}, + }, + "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, + } + }, +} +# ######### END LOGGING CONFIGURATION + + +# ######### WSGI CONFIGURATION +# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application +WSGI_APPLICATION = "%s.wsgi.application" % SITE_NAME +# ######### END WSGI CONFIGURATION + + +# ######### LDAP SETTINGS +GROUP_BASE_DN = get_env_variable("GVALDAP_BASEDN_GROUP") +USER_BASE_DN = get_env_variable("GVALDAP_BASEDN_USER") +# ######### END LDAP SETTINGS + + +# ######### CELERY CONFIGURATION +CELERY_BROKER_URL = get_env_variable("GVALDAP_BROKER_URL") +CELERY_RESULT_BACKEND = get_env_variable("GVALDAP_RESULTS_REDIS_URL") +CELERY_TASK_RESULT_EXPIRES = None +CELERY_ROUTES = ("gvacommon.celeryrouters.GvaRouter",) +CELERY_TIMEZONE = "Europe/Berlin" +CELERY_ENABLE_UTC = True +CELERY_ACCEPT_CONTENT = ["json"] +CELERY_TASK_SERIALIZER = "json" +CELERY_RESULT_SERIALIZER = "json" +# ######### END CELERY CONFIGURATION + +if DEBUG: + TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG + EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" + CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}} + INSTALLED_APPS += ("debug_toolbar",) + + MIDDLEWARE += ("debug_toolbar.middleware.DebugToolbarMiddleware",) + + LOGGING["handlers"].update( + { + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "simple", + } + } + ) + LOGGING["loggers"].update( + dict( + [ + (key, {"handlers": ["console"], "level": "DEBUG", "propagate": True}) + for key in ["ldapentities", "ldaptasks"] + ] + ) + ) + INTERNAL_IPS = get_env_variable("GVALDAP_INTERNAL_IPS", str, "127.0.0.1").split(",") +else: + ALLOWED_HOSTS = get_env_variable("GVALDAP_ALLOWED_HOSTS").split(",") + EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" + EMAIL_SUBJECT_PREFIX = "[%s] " % SITE_NAME + DEFAULT_FROM_EMAIL = get_env_variable("GVALDAP_ADMIN_EMAIL") + SERVER_EMAIL = get_env_variable("GVALDAP_SERVER_EMAIL") + +if get_env_variable("GVALDAP_TEST", bool, False): + PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",) + # ######### IN-MEMORY TEST DATABASE + DATABASES["default"] = { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", + } + + LOGGING["handlers"].update( + { + "console": { + "level": "ERROR", + "class": "logging.StreamHandler", + "formatter": "simple", + } + } + ) + LOGGING["loggers"].update( + dict( + [ + (key, {"handlers": ["console"], "level": "ERROR", "propagate": True}) + for key in ["ldapentities", "ldaptasks"] + ] + ) + ) + CELERY_BROKER_URL = CELERY_BROKER_URL + "_test" + CELERY_RESULT_PERSISTENT = False diff --git a/gvaldap/gvaldap/settings/__init__.py b/gvaldap/gvaldap/settings/__init__.py deleted file mode 100644 index 4f53a5e..0000000 --- a/gvaldap/gvaldap/settings/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -This module contains settings for various environments. -""" diff --git a/gvaldap/gvaldap/settings/base.py b/gvaldap/gvaldap/settings/base.py deleted file mode 100644 index 632322d..0000000 --- a/gvaldap/gvaldap/settings/base.py +++ /dev/null @@ -1,278 +0,0 @@ -# -*- coding: utf-8 -*- -# pymode:lint_ignore=E501 -""" -Common settings and globals. - -""" - -from os.path import abspath, basename, dirname, join, normpath -from sys import path - -from gvacommon.settings_utils import get_env_variable - - -# ######### PATH CONFIGURATION -# Absolute filesystem path to the Django project directory: -DJANGO_ROOT = dirname(dirname(abspath(__file__))) - -# Absolute filesystem path to the top-level project folder: -SITE_ROOT = dirname(DJANGO_ROOT) - -# Site name: -SITE_NAME = basename(DJANGO_ROOT) - -# Add our project to our pythonpath, this way we don't need to type our project -# name in our dotted import paths: -path.append(DJANGO_ROOT) -# ######### END PATH CONFIGURATION - - -# ######### DEBUG CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug -DEBUG = False - - -# ######### MANAGER CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins -ADMINS = ( - (get_env_variable('GVALDAP_ADMIN_NAME'), - get_env_variable('GVALDAP_ADMIN_EMAIL')), -) - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers -MANAGERS = ADMINS -# ######### END MANAGER CONFIGURATION - - -# ######### DATABASE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': normpath(join(DJANGO_ROOT, 'default.db')), - 'USER': '', - 'PASSWORD': '', - 'HOST': '', - 'PORT': '', - }, - 'ldap': { - 'ENGINE': 'ldapdb.backends.ldap', - 'NAME': get_env_variable('GVALDAP_LDAP_URL'), - 'USER': get_env_variable('GVALDAP_LDAP_USER'), - 'PASSWORD': get_env_variable('GVALDAP_LDAP_PASSWORD'), - } -} -DATABASE_ROUTERS = ['ldapdb.router.Router'] -# ######### END DATABASE CONFIGURATION - - -# ######### GENERAL CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#time-zone -TIME_ZONE = 'Europe/Berlin' - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code -LANGUAGE_CODE = 'en-us' - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id -SITE_ID = 1 - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n -USE_I18N = True - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n -USE_L10N = True - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz -USE_TZ = True -# ######### END GENERAL CONFIGURATION - - -# ######### MEDIA CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root -MEDIA_ROOT = normpath(join(SITE_ROOT, 'media')) - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url -MEDIA_URL = '/media/' -# ######### END MEDIA CONFIGURATION - - -# ######### STATIC FILE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url -STATIC_URL = '/static/' - -# See: -# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders # noqa -STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -) -# ######### END STATIC FILE CONFIGURATION - - -# ######### SECRET CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -# Note: This key should only be used for development and testing. -SECRET_KEY = get_env_variable('GVALDAP_SECRETKEY') -# ######### END SECRET CONFIGURATION - - -# ######### SITE CONFIGURATION -# Hosts/domain names that are valid for this site -# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts -ALLOWED_HOSTS = [] -# ######### END SITE CONFIGURATION - - -# ######### FIXTURE CONFIGURATION -# See: -# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS # noqa -FIXTURE_DIRS = ( - normpath(join(SITE_ROOT, 'fixtures')), -) -# ######### END FIXTURE CONFIGURATION - - -# ######### TEMPLATE CONFIGURATION -# See: https://docs.djangoproject.com/en/1.9/ref/settings/#std:setting-TEMPLATES # noqa -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [ - normpath(join(SITE_ROOT, 'templates')), - ], - '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.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', - 'django.template.context_processors.request', - ], - }, - }, -] - -# ######### END TEMPLATE CONFIGURATION - - -# ######### MIDDLEWARE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes -MIDDLEWARE = ( - # Default Django middleware. - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', -) -# ######### END MIDDLEWARE CONFIGURATION - - -# ######### URL CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf -ROOT_URLCONF = '%s.urls' % SITE_NAME -# ######### END URL CONFIGURATION - - -# ######### TEST RUNNER CONFIGURATION -TEST_RUNNER = 'django.test.runner.DiscoverRunner' -# ######### END TEST RUNNER CONFIGURATION - - -# ######### APP CONFIGURATION -DJANGO_APPS = ( - # Default Django apps: - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - - # Admin panel and documentation: - 'django.contrib.admin', -) - -# Apps specific for this project go here. -LOCAL_APPS = ( - 'ldapentities', - 'gvaldap.ldaptasks', -) - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps -INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS -# ######### END APP CONFIGURATION - - -# ######### LOGGING CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging -# 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, - 'formatters': { - 'verbose': { - 'format': '%(levelname)s %(asctime)s %(name)s ' - '%(module)s:%(lineno)d %(process)d %(thread)d %(message)s', - }, - 'simple': { - 'format': '%(levelname)s %(name)s:%(lineno)d %(message)s', - }, - }, - '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, - }, - } -} -# ######### END LOGGING CONFIGURATION - - -# ######### WSGI CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application -WSGI_APPLICATION = '%s.wsgi.application' % SITE_NAME -# ######### END WSGI CONFIGURATION - - -# ######### LDAP SETTINGS -GROUP_BASE_DN = get_env_variable('GVALDAP_BASEDN_GROUP') -USER_BASE_DN = get_env_variable('GVALDAP_BASEDN_USER') -# ######### END LDAP SETTINGS - - -# ######### CELERY CONFIGURATION -BROKER_URL = get_env_variable('GVALDAP_BROKER_URL') -CELERY_RESULT_BACKEND = get_env_variable('GVALDAP_RESULTS_REDIS_URL') -CELERY_TASK_RESULT_EXPIRES = None -CELERY_ROUTES = ( - 'gvacommon.celeryrouters.GvaRouter', -) -CELERY_TIMEZONE = 'Europe/Berlin' -CELERY_ENABLE_UTC = True -CELERY_ACCEPT_CONTENT = ['json'] -CELERY_TASK_SERIALIZER = 'json' -CELERY_RESULT_SERIALIZER = 'json' -# ######### END CELERY CONFIGURATION diff --git a/gvaldap/gvaldap/settings/local.py b/gvaldap/gvaldap/settings/local.py deleted file mode 100644 index 08e2b91..0000000 --- a/gvaldap/gvaldap/settings/local.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- python -*- -# pymode:lint_ignore=W0401,E501 -""" -Development settings and globals based on :py:mod:`gvaldap.settings.base`. - -""" - -from __future__ import absolute_import - -# use import * to import all settings from base -from .base import * # NOQA - - -# ######### DEBUG CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug -DEBUG = True - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug -TEMPLATES[0]['OPTIONS']['debug'] = DEBUG -# ######### END DEBUG CONFIGURATION - - -# ######### EMAIL CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-backend -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -# ######### END EMAIL CONFIGURATION - - -# ######### CACHE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#caches -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - } -} -# ######### END CACHE CONFIGURATION - - -# ######### TOOLBAR CONFIGURATION -# See: http://django-debug-toolbar.readthedocs.org/en/latest/installation.html#explicit-setup # noqa -INSTALLED_APPS += ( - 'debug_toolbar', -) - -MIDDLEWARE += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', -) - -LOGGING['handlers'].update({ - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'formatter': 'simple', - } -}) -LOGGING['loggers'].update(dict( - [(key, {'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }) - for key in ['ldapentities', 'ldaptasks']])) - -DEBUG_TOOLBAR_PATCH_SETTINGS = False - -# http://django-debug-toolbar.readthedocs.org/en/latest/installation.html -INTERNAL_IPS = ('127.0.0.1', '10.0.2.2') -# ######### END TOOLBAR CONFIGURATION diff --git a/gvaldap/gvaldap/settings/production.py b/gvaldap/gvaldap/settings/production.py deleted file mode 100644 index 03d35a2..0000000 --- a/gvaldap/gvaldap/settings/production.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- python -*- -# pymode:lint_ignore=W0401,E501 -""" -Production settings and globals based on :py:mod:`gvaldap.settings.base`. - -""" - -from __future__ import absolute_import - -# use import * to import all settings from base -from .base import * # NOQA - -# ######### HOST CONFIGURATION -# See: https://docs.djangoproject.com/en/1.5/releases/1.5/#allowed-hosts-required-in-production # noqa -ALLOWED_HOSTS = get_env_variable('GVALDAP_ALLOWED_HOSTS').split(',') -# ######### END HOST CONFIGURATION - -# ######### EMAIL CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-backend -EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix -EMAIL_SUBJECT_PREFIX = '[%s] ' % SITE_NAME - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email -DEFAULT_FROM_EMAIL = get_env_variable('GVALDAP_ADMIN_EMAIL') - -# See: https://docs.djangoproject.com/en/dev/ref/settings/#server-email -SERVER_EMAIL = get_env_variable('GVALDAP_SERVER_EMAIL') -# ######### END EMAIL CONFIGURATION - -# ######### CACHE CONFIGURATION -# See: https://docs.djangoproject.com/en/dev/ref/settings/#caches -# CACHES = {} -# ######### END CACHE CONFIGURATION diff --git a/gvaldap/gvaldap/settings/test.py b/gvaldap/gvaldap/settings/test.py deleted file mode 100644 index f52f224..0000000 --- a/gvaldap/gvaldap/settings/test.py +++ /dev/null @@ -1,35 +0,0 @@ -# pymode:lint_ignore=W0401 -""" -Test settings based on :py:mod:`gvaldap.settings.base`. - -""" -from __future__ import absolute_import - -# use import * to import all settings from base -from .base import * # NOQA - -PASSWORD_HASHERS = ( - 'django.contrib.auth.hashers.MD5PasswordHasher', -) -# ######### IN-MEMORY TEST DATABASE -DATABASES['default'] = { - "ENGINE": "django.db.backends.sqlite3", - "NAME": ":memory:", - "USER": "", - "PASSWORD": "", - "HOST": "", - "PORT": "", -} - -LOGGING['handlers'].update({ - 'console': { - 'level': 'ERROR', - 'class': 'logging.StreamHandler', - 'formatter': 'simple', - } -}) -LOGGING['loggers'].update(dict( - [(key, {'handlers': ['console'], 'level': 'ERROR', 'propagate': True, }) - for key in ['ldapentities', 'ldaptasks']])) -BROKER_URL = BROKER_URL + '_test' -CELERY_RESULT_PERSISTENT = False diff --git a/gvaldap/gvaldap/tests/test_celery.py b/gvaldap/gvaldap/tests/test_celery.py deleted file mode 100644 index b74f16d..0000000 --- a/gvaldap/gvaldap/tests/test_celery.py +++ /dev/null @@ -1,14 +0,0 @@ -""" -This module implements tests for :py:mod:`gvaldap.celery`. - -""" -from unittest import TestCase - -from gvaldap.celery import get_installed_apps -from django.conf import settings - - -class GetInstalledAppsTest(TestCase): - - def test_get_installed_apps(self): - self.assertEqual(get_installed_apps(), settings.INSTALLED_APPS) diff --git a/gvaldap/gvaldap/wsgi.py b/gvaldap/gvaldap/wsgi.py index b297d4d..a02e98b 100644 --- a/gvaldap/gvaldap/wsgi.py +++ b/gvaldap/gvaldap/wsgi.py @@ -17,6 +17,11 @@ import os from os.path import abspath, dirname from sys import path +# 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 # noqa + SITE_ROOT = dirname(dirname(abspath(__file__))) path.append(SITE_ROOT) @@ -24,12 +29,8 @@ path.append(SITE_ROOT) # if running multiple sites in the same mod_wsgi process. To fix this, use # mod_wsgi daemon mode with each site in its own daemon process, or use # os.environ["DJANGO_SETTINGS_MODULE"] = "jajaja.settings" -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gvaldap.settings.production") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gvaldap.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 # noqa application = get_wsgi_application() # Apply WSGI middleware here. diff --git a/gvaldap/gvaldap/ldaptasks/__init__.py b/gvaldap/ldaptasks/__init__.py similarity index 100% rename from gvaldap/gvaldap/ldaptasks/__init__.py rename to gvaldap/ldaptasks/__init__.py diff --git a/gvaldap/ldaptasks/celery.py b/gvaldap/ldaptasks/celery.py new file mode 100644 index 0000000..437b4e8 --- /dev/null +++ b/gvaldap/ldaptasks/celery.py @@ -0,0 +1,17 @@ +""" +This module defines the Celery_ app for gvaldap. + +.. _Celery: http://www.celeryproject.org/ + +""" +import os + +from celery import Celery + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gvaldap.settings") + +app = Celery("ldaptasks") + +app.config_from_object("django.conf:settings", namespace="CELERY") + +app.autodiscover_tasks() diff --git a/gvaldap/gvaldap/ldaptasks/tasks.py b/gvaldap/ldaptasks/tasks.py similarity index 72% rename from gvaldap/gvaldap/ldaptasks/tasks.py rename to gvaldap/ldaptasks/tasks.py index 50c0324..db41f0f 100644 --- a/gvaldap/gvaldap/ldaptasks/tasks.py +++ b/gvaldap/ldaptasks/tasks.py @@ -8,16 +8,14 @@ This module defines `Celery`_ tasks to manage LDAP entities. from __future__ import absolute_import from copy import deepcopy -from django.core.exceptions import ObjectDoesNotExist + from celery import shared_task -from celery.utils.log import get_task_logger from celery.exceptions import Reject +from celery.utils.log import get_task_logger -from ldapentities.models import ( - LdapGroup, - LdapUser, -) +from django.core.exceptions import ObjectDoesNotExist +from ldapentities.models import LdapGroup, LdapUser _LOGGER = get_task_logger(__name__) @@ -43,20 +41,20 @@ def create_ldap_group(groupname, gid, description): try: ldapgroup = LdapGroup.objects.get(name=groupname) _LOGGER.info( - 'LDAP group %s with groupname %s already exists', - ldapgroup.dn, groupname) + "LDAP group %s with groupname %s already exists", ldapgroup.dn, groupname + ) ldapgroup.gid = gid except LdapGroup.DoesNotExist: ldapgroup = LdapGroup(gid=gid, name=groupname) - _LOGGER.info('created LDAP group %s', ldapgroup.dn) + _LOGGER.info("created LDAP group %s", ldapgroup.dn) ldapgroup.description = description ldapgroup.save() - _LOGGER.info('set description of LDAP group %s', ldapgroup.dn) + _LOGGER.info("set description of LDAP group %s", ldapgroup.dn) return { - 'groupname': groupname, - 'gid': gid, - 'description': description, - 'group_dn': ldapgroup.dn, + "groupname": groupname, + "gid": gid, + "description": description, + "group_dn": ldapgroup.dn, } @@ -89,14 +87,14 @@ def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): try: ldapuser = LdapUser.objects.get(username=username) _LOGGER.info( - 'LDAP user %s with username %s already exists', - ldapuser.dn, username) + "LDAP user %s with username %s already exists", ldapuser.dn, username + ) except LdapUser.DoesNotExist: ldapuser = LdapUser(username=username) try: ldapgroup = LdapGroup.objects.get(gid=gid) except ObjectDoesNotExist as exc: - _LOGGER.error('LDAP group with gid %d does not exist', gid) + _LOGGER.error("LDAP group with gid %d does not exist", gid) raise Reject(exc, requeue=False) ldapuser.uid = uid ldapuser.group = gid @@ -107,27 +105,27 @@ def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): ldapuser.common_name = username if password is not None: ldapuser.set_password(password) - _LOGGER.info('set password for LDAP user %s', ldapuser.dn) + _LOGGER.info("set password for LDAP user %s", ldapuser.dn) ldapuser.save() - _LOGGER.info('LDAP user %s created', ldapuser.dn) + _LOGGER.info("LDAP user %s created", ldapuser.dn) if ldapuser.username in ldapgroup.members: _LOGGER.info( - 'LDAP user %s is already member of LDAP group %s', - ldapuser.dn, ldapgroup.dn) + "LDAP user %s is already member of LDAP group %s", ldapuser.dn, ldapgroup.dn + ) else: ldapgroup.members.append(ldapuser.username) ldapgroup.save() _LOGGER.info( - 'LDAP user %s has been added to LDAP group %s', - ldapuser.dn, ldapgroup.dn) + "LDAP user %s has been added to LDAP group %s", ldapuser.dn, ldapgroup.dn + ) return { - 'username': username, - 'uid': uid, - 'gid': gid, - 'gecos': gecos, - 'homedir': homedir, - 'shell': shell, - 'user_dn': ldapuser.dn, + "username": username, + "uid": uid, + "gid": gid, + "gecos": gecos, + "homedir": homedir, + "shell": shell, + "user_dn": ldapuser.dn, } @@ -145,16 +143,16 @@ def set_ldap_user_password(username, password): :rtype: dict """ - retval = {'username': username, 'password_set': False} + retval = {"username": username, "password_set": False} try: ldapuser = LdapUser.objects.get(username=username) except LdapUser.DoesNotExist: - _LOGGER.info('there is no LDAP user with username %s', username) + _LOGGER.info("there is no LDAP user with username %s", username) return retval ldapuser.set_password(password) ldapuser.save() _LOGGER.info("set new password for LDAP user %s", ldapuser.dn) - retval['password_set'] = True + retval["password_set"] = True return retval @@ -175,27 +173,31 @@ def add_ldap_user_to_group(self, username, groupname): :rtype: dict """ - retval = {'username': username, 'groupname': groupname, 'added': False} + retval = {"username": username, "groupname": groupname, "added": False} try: ldapgroup = LdapGroup.objects.get(name=groupname) ldapuser = LdapUser.objects.get(username=username) except LdapGroup.DoesNotExist: - _LOGGER.error('LDAP group with groupname %s does not exist', groupname) + _LOGGER.error("LDAP group with groupname %s does not exist", groupname) except LdapUser.DoesNotExist as exc: - _LOGGER.error('LDAP user with username %s does not exist', username) + _LOGGER.error("LDAP user with username %s does not exist", username) self.retry(exc=exc, time_limit=5) else: if ldapuser.username not in ldapgroup.members: ldapgroup.members.append(ldapuser.username) ldapgroup.save() _LOGGER.info( - 'LDAP user %s has been added to LDAP group %s', - ldapuser.username, ldapgroup.dn) + "LDAP user %s has been added to LDAP group %s", + ldapuser.username, + ldapgroup.dn, + ) else: _LOGGER.info( - 'LDAP user %s is already in LDAP group %s', - ldapuser.username, ldapgroup.dn) - retval['added'] = True + "LDAP user %s is already in LDAP group %s", + ldapuser.username, + ldapgroup.dn, + ) + retval["added"] = True return retval @@ -212,26 +214,28 @@ def remove_ldap_user_from_group(username, groupname): :rtype: dict """ - retval = {'username': username, 'groupname': groupname, 'removed': False} + retval = {"username": username, "groupname": groupname, "removed": False} try: ldapgroup = LdapGroup.objects.get(name=groupname) ldapuser = LdapUser.objects.get(username=username) except LdapGroup.DoesNotExist: - _LOGGER.error('LDAP group with groupname %s does not exist', groupname) + _LOGGER.error("LDAP group with groupname %s does not exist", groupname) except LdapUser.DoesNotExist: - _LOGGER.error('LDAP user with username %s does not exist', username) + _LOGGER.error("LDAP user with username %s does not exist", username) else: if ldapuser.username in ldapgroup.members: ldapgroup.members.remove(ldapuser.username) _LOGGER.info( - 'removed LDAP user %s from LDAP group %s', - ldapuser.dn, ldapgroup.dn) + "removed LDAP user %s from LDAP group %s", ldapuser.dn, ldapgroup.dn + ) ldapgroup.save() - retval['removed'] = True + retval["removed"] = True else: _LOGGER.info( - 'LDAP user %s is not a member of LDAP group %s', - ldapuser.dn, ldapgroup.dn) + "LDAP user %s is not a member of LDAP group %s", + ldapuser.dn, + ldapgroup.dn, + ) return retval @@ -255,29 +259,31 @@ def delete_ldap_user(username, *args, **kwargs): positions in the task chain """ - retval = {'username': username, 'deleted': False} + retval = {"username": username, "deleted": False} try: ldapuser = LdapUser.objects.get(username=username) except LdapUser.DoesNotExist: - _LOGGER.info('there is no LDAP user with username %s', username) + _LOGGER.info("there is no LDAP user with username %s", username) else: try: ldapgroup = LdapGroup.objects.get(gid=ldapuser.group) except LdapGroup.DoesNotExist: _LOGGER.info( - 'LDAP group %s of LDAP user %s does not exist', - ldapuser.group, ldapuser.dn) + "LDAP group %s of LDAP user %s does not exist", + ldapuser.group, + ldapuser.dn, + ) else: if ldapuser.username in ldapgroup.members: ldapgroup.members.remove(ldapuser.username) ldapgroup.save() _LOGGER.info( - 'removed LDAP user %s from LDAP group %s', - ldapuser.dn, ldapgroup.dn) + "removed LDAP user %s from LDAP group %s", ldapuser.dn, ldapgroup.dn + ) userdn = ldapuser.dn ldapuser.delete() - _LOGGER.info('deleted LDAP user %s', userdn) - retval['deleted'] = True + _LOGGER.info("deleted LDAP user %s", userdn) + retval["deleted"] = True return retval @@ -295,7 +301,7 @@ def delete_ldap_user_chained(previous_result, *args, **kwargs): :rtype: dict """ - username = previous_result['username'] + username = previous_result["username"] retval = deepcopy(previous_result) retval.update(delete_ldap_user(username)) return retval @@ -313,22 +319,23 @@ def delete_ldap_group_if_empty(groupname): :rtype: dict """ - retval = {'groupname': groupname, 'deleted': False} + retval = {"groupname": groupname, "deleted": False} try: ldapgroup = LdapGroup.objects.get(name=groupname) except LdapGroup.DoesNotExist: - _LOGGER.info('LDAP group with groupname %s does not exist', groupname) + _LOGGER.info("LDAP group with groupname %s does not exist", groupname) else: if len(ldapgroup.members) == 0: groupdn = ldapgroup.dn ldapgroup.delete() - _LOGGER.info( - 'deleted LDAP group %s', groupdn) - retval['deleted'] = True + _LOGGER.info("deleted LDAP group %s", groupdn) + retval["deleted"] = True else: _LOGGER.info( - 'LDAP group %s has not been deleted. It still has %d members', - ldapgroup.dn, len(ldapgroup.members)) + "LDAP group %s has not been deleted. It still has %d members", + ldapgroup.dn, + len(ldapgroup.members), + ) return retval @@ -344,14 +351,14 @@ def delete_ldap_group(groupname): :rtype: dict """ - retval = {'groupname': groupname, 'deleted': False} + retval = {"groupname": groupname, "deleted": False} try: ldapgroup = LdapGroup.objects.get(name=groupname) except LdapGroup.DoesNotExist: - _LOGGER.info('LDAP group with name %s does not exist', groupname) + _LOGGER.info("LDAP group with name %s does not exist", groupname) else: groupdn = ldapgroup.dn ldapgroup.delete() - _LOGGER.info('deleted LDAP group %s', groupdn) - retval['deleted'] = True + _LOGGER.info("deleted LDAP group %s", groupdn) + retval["deleted"] = True return retval diff --git a/gvaldap/gvaldap/ldaptasks/tests/__init__.py b/gvaldap/ldaptasks/tests/__init__.py similarity index 100% rename from gvaldap/gvaldap/ldaptasks/tests/__init__.py rename to gvaldap/ldaptasks/tests/__init__.py diff --git a/gvaldap/gvaldap/ldaptasks/tests/test_tasks.py b/gvaldap/ldaptasks/tests/test_tasks.py similarity index 99% rename from gvaldap/gvaldap/ldaptasks/tests/test_tasks.py rename to gvaldap/ldaptasks/tests/test_tasks.py index b0c1ce8..42d2a48 100644 --- a/gvaldap/gvaldap/ldaptasks/tests/test_tasks.py +++ b/gvaldap/ldaptasks/tests/test_tasks.py @@ -3,12 +3,13 @@ This module provides tests for :py:mod:`ldaptasks.tasks`. """ import volatildap -from django.conf import settings -from django.test import TestCase from celery.exceptions import Reject +from django.conf import settings +from django.test import TestCase + from ldapentities.models import LdapUser -from gvaldap.ldaptasks.tasks import ( +from ldaptasks.tasks import ( add_ldap_user_to_group, create_ldap_group, create_ldap_user, diff --git a/gvaldap/manage.py b/gvaldap/manage.py index c9b1eb2..e271baa 100644 --- a/gvaldap/manage.py +++ b/gvaldap/manage.py @@ -3,7 +3,7 @@ import os import sys if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gvaldap.settings.local") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gvaldap.settings") from django.core.management import execute_from_command_line diff --git a/gvaldap/setup.cfg b/gvaldap/setup.cfg index 3776715..e41483d 100644 --- a/gvaldap/setup.cfg +++ b/gvaldap/setup.cfg @@ -5,12 +5,21 @@ exclude = migrations exclude = migrations [coverage:run] -source = gvaldap,ldapentities,gvaldap.ldaptasks +source = gvaldap,ldapentities,ldaptasks branch = True +omit = */migrations/*,*/tests/*.py,*/tests.py,gvaldap.py +relative_files = True [coverage:report] -omit = */migrations/*,*/tests/*.py,*/tests.py,gvaldap/settings/local.py,gvaldap/settings/production.py show_missing = True [coverage:html] directory = ../coverage-report + +[isort] +multi_line_output = 3 +line_length = 88 +known_django = django +known_third_party = celery,volatildap +include_trailing_comma = True +sections = FUTURE,STDLIB,THIRDPARTY,DJANGO,FIRSTPARTY,LOCALFOLDER From 628d6ee550412565893c24d9860140bb651d6e47 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 3 Mar 2020 12:22:45 +0100 Subject: [PATCH 25/29] Add Dockerfile and entrypoint script --- Dockerfile | 45 +++++++++++++++++++++++++++++++++++++++++++++ gvaldap.sh | 7 +++++++ 2 files changed, 52 insertions(+) create mode 100644 Dockerfile create mode 100755 gvaldap.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4d8108a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +ARG DEBIAN_RELEASE=buster +FROM debian:$DEBIAN_RELEASE +LABEL maintainer="Jan Dittberner " + +ARG GVALDAPGID=2000 +ARG GVALDAPUID=2000 + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + dumb-init \ + gettext \ + git \ + libldap2-dev \ + libsasl2-dev \ + python3-dev \ + python3-pip \ + python3-setuptools \ + python3-virtualenv \ + python3-wheel \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/*.* + +WORKDIR /srv/gvaldap + +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +RUN python3 -m pip install --prefix=/usr/local pipenv + +COPY Pipfile Pipfile.lock /srv/gvaldap/ + +RUN addgroup --gid $GVALDAPGID gvaldap ; \ + adduser --home /home/gvaldap --shell /bin/bash --uid $GVALDAPUID --gid $GVALDAPGID --disabled-password --gecos "Gnuviechadmin LDAP user" gvaldap + +USER gvaldap +RUN python3 -m virtualenv --python=python3 /home/gvaldap/gvaldap-venv ; \ + /home/gvaldap/gvaldap-venv/bin/python3 -m pip install -U pip ; \ + VIRTUAL_ENV=/home/gvaldap/gvaldap-venv pipenv install --deploy --ignore-pipfile --dev + +VOLUME /srv/gvaldap + +COPY gvaldap.sh /srv/ + +ENTRYPOINT ["dumb-init", "/srv/gvaldap.sh"] \ No newline at end of file diff --git a/gvaldap.sh b/gvaldap.sh new file mode 100755 index 0000000..73eab77 --- /dev/null +++ b/gvaldap.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +. /home/gvaldap/gvaldap-venv/bin/activate +cd /srv/gvaldap/gvaldap +celery -A ldaptasks worker -Q ldap -l info From bdcd16b7e7933b26baf1c17d3b5ab9eaafcd6a33 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 3 Mar 2020 13:12:41 +0100 Subject: [PATCH 26/29] Unify docker setup with gvaweb and gva --- Dockerfile | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4d8108a..ca70fd3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ ARG DEBIAN_RELEASE=buster FROM debian:$DEBIAN_RELEASE LABEL maintainer="Jan Dittberner " -ARG GVALDAPGID=2000 -ARG GVALDAPUID=2000 +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ @@ -11,8 +11,6 @@ RUN apt-get update \ dumb-init \ gettext \ git \ - libldap2-dev \ - libsasl2-dev \ python3-dev \ python3-pip \ python3-setuptools \ @@ -21,25 +19,34 @@ RUN apt-get update \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*.* -WORKDIR /srv/gvaldap - -ENV LC_ALL=C.UTF-8 -ENV LANG=C.UTF-8 - RUN python3 -m pip install --prefix=/usr/local pipenv -COPY Pipfile Pipfile.lock /srv/gvaldap/ +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libldap2-dev \ + libsasl2-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/*.* -RUN addgroup --gid $GVALDAPGID gvaldap ; \ - adduser --home /home/gvaldap --shell /bin/bash --uid $GVALDAPUID --gid $GVALDAPGID --disabled-password --gecos "Gnuviechadmin LDAP user" gvaldap +ARG GVAGID=2000 +ARG GVAUID=2000 -USER gvaldap -RUN python3 -m virtualenv --python=python3 /home/gvaldap/gvaldap-venv ; \ - /home/gvaldap/gvaldap-venv/bin/python3 -m pip install -U pip ; \ - VIRTUAL_ENV=/home/gvaldap/gvaldap-venv pipenv install --deploy --ignore-pipfile --dev +ARG GVAAPP=gvaldap -VOLUME /srv/gvaldap +WORKDIR /srv/$GVAAPP + +COPY Pipfile Pipfile.lock /srv/$GVAAPP/ + +RUN addgroup --gid $GVAGID $GVAAPP ; \ + adduser --home /home/$GVAAPP --shell /bin/bash --uid $GVAUID --gid $GVAGID --disabled-password --gecos "User for gnuviechadmin component $GVAAPP" $GVAAPP + +USER $GVAAPP +RUN python3 -m virtualenv --python=python3 /home/$GVAAPP/$GVAAPP-venv ; \ + /home/$GVAAPP/$GVAAPP-venv/bin/python3 -m pip install -U pip ; \ + VIRTUAL_ENV=/home/$GVAAPP/$GVAAPP-venv pipenv install --deploy --ignore-pipfile --dev + +VOLUME /srv/$GVAAPP COPY gvaldap.sh /srv/ -ENTRYPOINT ["dumb-init", "/srv/gvaldap.sh"] \ No newline at end of file +ENTRYPOINT ["dumb-init", "/srv/gvaldap.sh"] From 99c80f5759d9d14eb954033ed1c548868335ba49 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 3 Mar 2020 14:50:03 +0100 Subject: [PATCH 27/29] Implement automatic retry for LDAP errors --- gvaldap/ldaptasks/tasks.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/gvaldap/ldaptasks/tasks.py b/gvaldap/ldaptasks/tasks.py index db41f0f..4ac5906 100644 --- a/gvaldap/ldaptasks/tasks.py +++ b/gvaldap/ldaptasks/tasks.py @@ -14,13 +14,14 @@ from celery.exceptions import Reject from celery.utils.log import get_task_logger from django.core.exceptions import ObjectDoesNotExist +from django.db.utils import Error as DjangoDBUtilsError from ldapentities.models import LdapGroup, LdapUser _LOGGER = get_task_logger(__name__) -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def create_ldap_group(groupname, gid, description): """ This task creates an :py:class:`LDAP group ` @@ -58,7 +59,7 @@ def create_ldap_group(groupname, gid, description): } -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): """ This task creates an :py:class:`LDAP user ` @@ -129,7 +130,7 @@ def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): } -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def set_ldap_user_password(username, password): """ This task sets the password of an existing :py:class:`LDAP user @@ -156,7 +157,7 @@ def set_ldap_user_password(username, password): return retval -@shared_task(bind=True) +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def add_ldap_user_to_group(self, username, groupname): """ This task adds the specified user to the given group. @@ -201,7 +202,7 @@ def add_ldap_user_to_group(self, username, groupname): return retval -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def remove_ldap_user_from_group(username, groupname): """ This task removes the given user from the given group. @@ -239,7 +240,7 @@ def remove_ldap_user_from_group(username, groupname): return retval -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def delete_ldap_user(username, *args, **kwargs): """ This task deletes the given user. @@ -287,7 +288,7 @@ def delete_ldap_user(username, *args, **kwargs): return retval -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def delete_ldap_user_chained(previous_result, *args, **kwargs): """ This task deletes the given user. @@ -307,7 +308,7 @@ def delete_ldap_user_chained(previous_result, *args, **kwargs): return retval -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def delete_ldap_group_if_empty(groupname): """ This task deletes the given group if it is empty. @@ -339,7 +340,7 @@ def delete_ldap_group_if_empty(groupname): return retval -@shared_task +@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def delete_ldap_group(groupname): """ This task deletes the given group. From 8875765018e4e9d40aad46e02b0e3f9c446a07f4 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 3 Mar 2020 14:54:16 +0100 Subject: [PATCH 28/29] Fix missing bind=True --- gvaldap/ldaptasks/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gvaldap/ldaptasks/tasks.py b/gvaldap/ldaptasks/tasks.py index 4ac5906..338c726 100644 --- a/gvaldap/ldaptasks/tasks.py +++ b/gvaldap/ldaptasks/tasks.py @@ -157,7 +157,7 @@ def set_ldap_user_password(username, password): return retval -@shared_task(autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) +@shared_task(bind=True, autoretry_for=(DjangoDBUtilsError,), default_retry_delay=10) def add_ldap_user_to_group(self, username, groupname): """ This task adds the specified user to the given group. From 2297c82cf2e0b413efdc67b037211e8d5ff35991 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Tue, 3 Mar 2020 15:04:34 +0100 Subject: [PATCH 29/29] Release preparation for 0.6.0 - Bump copyright years - Bump version number - Update changelog - Update documentation --- LICENSE.txt | 2 +- README.rst | 2 +- docs/changelog.rst | 6 ++++ docs/code.rst | 35 +++++---------------- docs/conf.py | 3 +- docs/deploy.rst | 2 +- docs/install.rst | 62 +++++-------------------------------- gvaldap/gvaldap/__init__.py | 2 +- 8 files changed, 26 insertions(+), 88 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 96e8baa..ec337c9 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2014, 2015 Jan Dittberner +Copyright (c) 2014-2020 Jan Dittberner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/README.rst b/README.rst index 8bf40ed..a11832f 100644 --- a/README.rst +++ b/README.rst @@ -10,4 +10,4 @@ customer management at `Jan Dittberner IT-Consulting & -Solutions Read the :doc:`Installation instructions ` to get started locally. -The project page for gvaldap is at http://dev.gnuviech-server.de/gvaldap. +The project page for gvaldap is at http://git.dittberner.info/gnuviech/gvaldap. diff --git a/docs/changelog.rst b/docs/changelog.rst index 5e48338..fe55a8d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,12 @@ Changelog ========= +* :release:`0.6.0 <2020-03-03>` +* :support:`-` add Python 3 support +* :support:`-` upgrade to Django 2.2.10 +* :support:`-` use Pipenv for dependency management +* :feature:`-` properly handle unavailable LDAP server + * :release:`0.5.2 <2015-01-29>` * :bug:`-` fix minor log message issue diff --git a/docs/code.rst b/docs/code.rst index 7b85d45..18e2bfe 100644 --- a/docs/code.rst +++ b/docs/code.rst @@ -16,13 +16,6 @@ The project module :py:mod:`gvaldap` .. automodule:: gvaldap -:py:mod:`celery ` ---------------------------------- - -.. automodule:: gvaldap.celery - :members: - - :py:mod:`urls ` ----------------------------- @@ -41,27 +34,6 @@ The project module :py:mod:`gvaldap` .. automodule:: gvaldap.settings -:py:mod:`base ` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: gvaldap.settings.base - :members: - -:py:mod:`local ` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: gvaldap.settings.local - -:py:mod:`production ` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: gvaldap.settings.production - -:py:mod:`test ` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: gvaldap.settings.test - :py:mod:`ldapentities` app ========================== @@ -89,6 +61,13 @@ The project module :py:mod:`gvaldap` .. automodule:: ldaptasks +:py:mod:`celery ` +----------------------------------- + +.. automodule:: ldaptasks.celery + :members: + + :py:mod:`tasks ` --------------------------------- diff --git a/docs/conf.py b/docs/conf.py index 1553fb0..96bfdb0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,6 +21,7 @@ import django # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath(os.path.join('..', 'gvaldap'))) +os.environ['DJANGO_SETTINGS_MODULE'] = 'gvaldap.settings' os.environ['GVALDAP_ALLOWED_HOSTS'] = 'localhost' os.environ['GVALDAP_SERVER_EMAIL'] = 'root@localhost' @@ -53,7 +54,7 @@ master_doc = 'index' # General information about the project. project = u'gvaldap' -copyright = u'2014, 2015, 2016 Jan Dittberner' +copyright = u'2014-2020 Jan Dittberner' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/deploy.rst b/docs/deploy.rst index 9fd944b..7ebc0af 100644 --- a/docs/deploy.rst +++ b/docs/deploy.rst @@ -7,4 +7,4 @@ of the following steps: * installation of native dependencies * setup of a virtualenv * installation of gvaldap production dependencies inside the virtualenv -* setup of celery worker under control of supervisord +* setup of celery worker under control of systemd diff --git a/docs/install.rst b/docs/install.rst index 23a17ee..ca615c7 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -7,65 +7,17 @@ Install Working Environment =================== -You have several options in setting up your working environment. We recommend -using virtualenv to separate the dependencies of your project from your -system's python environment. If on Linux or Mac OS X, you can also use -virtualenvwrapper to help manage multiple virtualenvs across different -projects. +To get a running work environment use `pipenv`_. -.. index:: virtualenv +.. _pipenv: https://pipenv.kennethreitz.org/en/latest/ -Virtualenv Only ---------------- - -First, make sure you are using `virtualenv`_. Once that's installed, create -your virtualenv: +To get started install `pip` and `pipenv` and use `pipenv install --dev`: .. code-block:: sh - $ virtualenv --distribute gvaldap - -.. _virtualenv: https://virtualenv.pypa.io/en/latest/ - -You will also need to ensure that the virtualenv has the project directory -added to the path. Adding the project directory will allow `django-admin.py` to -be able to change settings using the `--settings` flag. - -.. index:: virtualenvwrapper - -Virtualenv with virtualenvwrapper ------------------------------------- - -In Linux and Mac OSX, you can install `virtualenvwrapper -`_, which will take care -of managing your virtual environments and adding the project path to the -`site-directory` for you: - -.. code-block:: sh - - $ mkdir gvaldap - $ mkvirtualenv -a gvaldap gvaldap-dev - $ cd gvaldap && add2virtualenv `pwd` - - -.. index:: pip, requirements, dependencies - -Installation of Dependencies -============================= - -Depending on where you are installing dependencies: - -In development: - -.. code-block:: sh - - $ pip install -r requirements/local.txt - -For production: - -.. code-block:: sh - - $ pip install -r requirements.txt + $ apt install python3-pip + $ python3 -m pip install --user -U pipenv + $ pipenv install --dev .. index:: celery, worker, ldap queue @@ -79,6 +31,6 @@ into the gvaldap directory and run the celery worker with: .. code-block:: sh $ cd gvaldap - $ celery -A gvaldap worker -Q ldap -l info + $ pipenv run celery -A ldaptasks worker -Q web -l info .. _Celery: http://www.celeryproject.org/ diff --git a/gvaldap/gvaldap/__init__.py b/gvaldap/gvaldap/__init__.py index 1c758d0..3204c6a 100644 --- a/gvaldap/gvaldap/__init__.py +++ b/gvaldap/gvaldap/__init__.py @@ -1,7 +1,7 @@ """ This is the gvaldap project module. """ -__version__ = "0.6.0.dev1" +__version__ = "0.6.0" from ldaptasks.celery import app as celery_app