diff --git a/README.md b/README.md index a7b00d5d..aafff6a8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [puppet-python](https://github.com/stankevich/puppet-python) ====== -Puppet module for installing and managing python, pip, virtualenv, Gunicorn virtual hosts +Puppet module for installing and managing python, pip, virtualenvs and Gunicorn virtual hosts. ## Usage @@ -32,6 +32,8 @@ Installs and manages packages from pip. **virtualenv** — virtualenv to run pip in. +**url** — URL to install from. Default: none + **proxy** — Proxy server to use for outbound connections. Default: none python::pip { 'flask': @@ -64,11 +66,17 @@ Creates Python virtualenv. **proxy** — Proxy server to use for outbound connections. Default: none +**systempkgs** — Copy system site-packages into virtualenv. Default: don't + +**distribute** — Include distribute in the virtualenv. Default: true + python::virtualenv { '/var/www/project1': ensure => present, version => 'system', requirements => '/var/www/project1/requirements.txt', proxy => 'http://proxy.domain.com:3128', + systempkgs => true, + distribute => false, } ### python::gunicorn @@ -87,6 +95,8 @@ Manages Gunicorn virtual hosts. **environment** — Set ENVIRONMENT variable. Default: none +**template** — Which ERB template to use. Default: python/gunicorn.erb + python::gunicorn { 'vhost': ensure => present, virtualenv => '/var/www/project1', @@ -94,8 +104,11 @@ Manages Gunicorn virtual hosts. dir => '/var/www/project1/current', bind => 'unix:/tmp/gunicorn.socket', environment => 'prod', + template => 'python/gunicorn.erb', } ## Authors [Sergey Stankevich](https://github.com/stankevich) +[Ashley Penney](https://github.com/apenney) +[Marc Fournier](https://github.com/mfournier) diff --git a/manifests/config.pp b/manifests/config.pp index 43da22e4..49e52307 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -5,7 +5,6 @@ Class['python::install'] -> Python::Virtualenv <| |> Python::Virtualenv <| |> -> Python::Pip <| |> - Python::Virtualenv <| |> -> Python::Requirements <| |> if $python::gunicorn { Class['python::install'] -> Python::Gunicorn <| |> diff --git a/manifests/gunicorn.pp b/manifests/gunicorn.pp index 2548e95d..13f48720 100644 --- a/manifests/gunicorn.pp +++ b/manifests/gunicorn.pp @@ -25,6 +25,9 @@ # [*environment*] # Set ENVIRONMENT variable. Default: none # +# [*template*] +# Which ERB template to use. Default: python/gunicorn.erb +# # === Examples # # python::gunicorn { 'vhost': @@ -34,11 +37,14 @@ # dir => '/var/www/project1/current', # bind => 'unix:/tmp/gunicorn.socket', # environment => 'prod', +# template => 'python/gunicorn.erb', # } # # === Authors # # Sergey Stankevich +# Ashley Penney +# Marc Fournier # define python::gunicorn ( $ensure = present, @@ -46,8 +52,8 @@ $mode = 'wsgi', $dir = false, $bind = false, - $app_interface = 'wsgi', $environment = false, + $template = 'python/gunicorn.erb', ) { # Parameter validation @@ -60,7 +66,7 @@ mode => '0644', owner => 'root', group => 'root', - content => template('python/gunicorn.erb'), + content => template($template), } } diff --git a/manifests/init.pp b/manifests/init.pp index c7ab10f2..8e8de9e2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -37,7 +37,7 @@ ) { # Module compatibility check - $compatible = [ 'Debian', 'Ubuntu' ] + $compatible = [ 'Debian', 'Ubuntu', 'CentOS', 'RedHat' ] if ! ($::operatingsystem in $compatible) { fail("Module is not compatible with ${::operatingsystem}") } diff --git a/manifests/install.pp b/manifests/install.pp index dec99b8a..cf0a13e0 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -5,6 +5,11 @@ default => "python${python::version}", } + $pythondev = $::operatingsystem ? { + /(?i:RedHat|CentOS|Fedora)/ => "$python-devel", + /(?i:Debian|Ubuntu)/ => "$python-dev" + } + package { $python: ensure => present } $dev_ensure = $python::dev ? { @@ -12,7 +17,7 @@ default => absent, } - package { "${python}-dev": ensure => $dev_ensure } + package { [ $pythondev, 'python-pip' ]: ensure => $dev_ensure } $venv_ensure = $python::virtualenv ? { true => present, diff --git a/manifests/pip.pp b/manifests/pip.pp index 9762c103..3a8ec1b2 100644 --- a/manifests/pip.pp +++ b/manifests/pip.pp @@ -10,6 +10,9 @@ # [*virtualenv*] # virtualenv to run pip in. # +# [*url*] +# URL to install from. Default: none +# # [*proxy*] # Proxy server to use for outbound connections. Default: none # @@ -27,6 +30,7 @@ define python::pip ( $virtualenv, $ensure = present, + $url = false, $proxy = false ) { @@ -45,10 +49,15 @@ default => "^${name}==", } + $source = $url ? { + false => $name, + default => "${url}#egg=${name}", + } + case $ensure { present: { exec { "pip_install_${name}": - command => "${virtualenv}/bin/pip install ${proxy_flag} ${name}", + command => "${virtualenv}/bin/pip install ${proxy_flag} ${source}", unless => "${virtualenv}/bin/pip freeze | grep -i -e ${grep_regex}", } } diff --git a/manifests/requirements.pp b/manifests/requirements.pp index b6c9b346..3a32b0ff 100644 --- a/manifests/requirements.pp +++ b/manifests/requirements.pp @@ -4,6 +4,9 @@ # # === Parameters # +# [*requirements*] +# Path to the requirements file. Defaults to the resource name +# # [*virtualenv*] # virtualenv to run pip in. Default: system-wide # @@ -20,13 +23,20 @@ # === Authors # # Sergey Stankevich +# Ashley Penney # define python::requirements ( - $virtualenv = 'system', - $proxy = false + $requirements = $name, + $virtualenv = 'system', + $proxy = false, + $owner = 'root', + $group = 'root' ) { - $requirements = $name + $cwd = $virtualenv ? { + 'system' => '/', + default => "${virtualenv}/bin/", + } $pip_env = $virtualenv ? { 'system' => '`which pip`', @@ -38,30 +48,36 @@ default => "--proxy=${proxy}", } - $req_dir = inline_template('<%= requirements.match(%r!(.+)/.+!)[1] %>') $req_crc = "${requirements}.sha1" - file { $requirements: - ensure => present, - mode => '0644', - owner => 'root', - group => 'root', - replace => false, - content => '# Puppet will install and/or update pip packages listed here', + # This will ensure multiple python::virtualenv definitions can share the + # the same requirements file. + if !defined(File[$requirements]) { + file { $requirements: + ensure => present, + mode => '0644', + owner => $owner, + group => $group, + replace => false, + content => '# Puppet will install and/or update pip packages listed here', + } } # SHA1 checksum to detect changes exec { "python_requirements_check_${name}": command => "sha1sum ${requirements} > ${req_crc}", unless => "sha1sum -c ${req_crc}", + user => $owner, require => File[$requirements], } exec { "python_requirements_update_${name}": + provider => shell, command => "${pip_env} install ${proxy_flag} -Ur ${requirements}", - cwd => $virtualenv, + cwd => $cwd, refreshonly => true, timeout => 1800, + user => $owner, subscribe => Exec["python_requirements_check_${name}"], } diff --git a/manifests/virtualenv.pp b/manifests/virtualenv.pp index f22f4e14..9888cd2b 100644 --- a/manifests/virtualenv.pp +++ b/manifests/virtualenv.pp @@ -16,6 +16,12 @@ # [*proxy*] # Proxy server to use for outbound connections. Default: none # +# [*systempkgs*] +# Copy system site-packages into virtualenv. Default: don't +# +# [*distribute*] +# Include distribute in the virtualenv. Default: true +# # === Examples # # python::virtualenv { '/var/www/project1': @@ -23,17 +29,26 @@ # version => 'system', # requirements => '/var/www/project1/requirements.txt', # proxy => 'http://proxy.domain.com:3128', +# systempkgs => true, +# index => 'http://www.example.com/simple/' # } # # === Authors # # Sergey Stankevich +# Ashley Penney +# Marc Fournier # define python::virtualenv ( $ensure = present, $version = 'system', $requirements = false, - $proxy = false + $proxy = false, + $systempkgs = false, + $distribute = true, + $owner = 'root', + $group = 'root' + $index = false, ) { $venv_dir = $name @@ -55,21 +70,55 @@ default => "&& export http_proxy=${proxy}", } + $system_pkgs_flag = $systempkgs ? { + false => '', + default => '--system-site-packages', + } + + $distribute_pkg = $distribute ? { + true => 'distribute', + default => '', + } + $pypi_index = $index ? { + false => '', + default => "-i ${index}", + } + + exec { "python_virtualenv_${venv_dir}": command => "mkdir -p ${venv_dir} \ ${proxy_command} \ - && virtualenv -p `which ${python}` ${venv_dir} \ - && ${venv_dir}/bin/pip install ${proxy_flag} --upgrade distribute pip", + && virtualenv -p `which ${python}` ${system_pkgs_flag} ${venv_dir} \ + && ${venv_dir}/bin/pip install ${pypi_index} ${proxy_flag} --upgrade ${distribute_pkg} pip", + user => $owner, creates => $venv_dir, + path => [ '/bin', '/usr/bin', '/usr/sbin' ], + } + + file{$venv_dir: + ensure => directory, + owner => $owner, + group => $group, + recurse => true, + require => Exec["python_virtualenv_${venv_dir}"], } if $requirements { - Exec["python_virtualenv_${venv_dir}"] - -> Python::Requirements[$requirements] + exec { "python_requirements_initial_install_${requirements}_${venv_dir}": + command => "${venv_dir}/bin/pip install ${pypi_index} ${proxy_flag} --requirement ${requirements}", + refreshonly => true, + timeout => 1800, + user => $owner, + subscribe => Exec["python_virtualenv_${venv_dir}"], + } - python::requirements { $requirements: - virtualenv => $venv_dir, - proxy => $proxy, + python::requirements { "${requirements}_${venv_dir}": + requirements => $requirements, + virtualenv => $venv_dir, + proxy => $proxy, + owner => $owner, + group => $group, + require => Exec["python_virtualenv_${venv_dir}"], } } diff --git a/templates/gunicorn.erb b/templates/gunicorn.erb index 2cf3eedd..1a965315 100644 --- a/templates/gunicorn.erb +++ b/templates/gunicorn.erb @@ -30,6 +30,8 @@ CONFIG = { <% end -%> '--workers=<%= @processorcount.to_i*2 %>', '--timeout=30', +<% if mode != 'django' -%> 'app:app', +<% end -%> ), } diff --git a/tests/gunicorn.pp b/tests/gunicorn.pp index c081fd64..c32ea1a2 100644 --- a/tests/gunicorn.pp +++ b/tests/gunicorn.pp @@ -11,4 +11,5 @@ dir => '/var/www/project1/current', bind => 'unix:/tmp/gunicorn.socket', environment => 'prod', + template => 'python/gunicorn.erb', } diff --git a/tests/requirements.pp b/tests/requirements.pp index a57093f0..9a954fa2 100644 --- a/tests/requirements.pp +++ b/tests/requirements.pp @@ -8,3 +8,8 @@ virtualenv => '/var/www/project1', proxy => 'http://proxy.domain.com:3128', } + +python::requirements { '/var/www/project1/requirements.txt': + virtualenv => 'system', + proxy => 'http://proxy.domain.com:3128', +} diff --git a/tests/virtualenv.pp b/tests/virtualenv.pp index 190492c7..da5ab57c 100644 --- a/tests/virtualenv.pp +++ b/tests/virtualenv.pp @@ -9,4 +9,5 @@ version => 'system', requirements => '/var/www/project1/requirements.txt', proxy => 'http://proxy.domain.com:3128', + systempkgs => true, }