diff options
-rw-r--r-- | Modulefile | 2 | ||||
-rw-r--r-- | lib/facter/pip_version.rb | 19 | ||||
-rw-r--r-- | lib/facter/python_version.rb | 28 | ||||
-rw-r--r-- | lib/facter/virtualenv_version.rb | 19 | ||||
-rw-r--r-- | manifests/config.pp | 16 | ||||
-rw-r--r-- | manifests/gunicorn.pp | 4 | ||||
-rw-r--r-- | manifests/init.pp | 20 | ||||
-rw-r--r-- | manifests/install.pp | 42 | ||||
-rw-r--r-- | manifests/pip.pp | 30 | ||||
-rw-r--r-- | manifests/requirements.pp | 14 | ||||
-rw-r--r-- | manifests/virtualenv.pp | 39 | ||||
-rw-r--r-- | templates/gunicorn.erb | 32 |
12 files changed, 207 insertions, 58 deletions
@@ -1,5 +1,5 @@ name 'stankevich-python' -version '1.3.0' +version '1.6.0' author 'Sergey Stankevich' license 'Apache License, Version 2.0' diff --git a/lib/facter/pip_version.rb b/lib/facter/pip_version.rb new file mode 100644 index 0000000..131d1f9 --- /dev/null +++ b/lib/facter/pip_version.rb @@ -0,0 +1,19 @@ +# Make pip version available as a fact +# Works with pip loaded and without, pip installed using pip and package installed +require 'puppet' +pkg = Puppet::Type.type(:package).new(:name => "python-pip") +Facter.add("pip_version") do + has_weight 100 + setcode do + /^pip (\d+\.\d+\.?\d*).*$/.match(Facter::Util::Resolution.exec('pip --version'))[1] + end +end + +Facter.add("pip_version") do + has_weight 50 + setcode do + if pkg.retrieve[pkg.property(:ensure)] != 'purged' + /^.*(\d+\.\d+\.\d+).*$/.match(pkg.retrieve[pkg.property(:ensure)])[1] + end + end +end diff --git a/lib/facter/python_version.rb b/lib/facter/python_version.rb new file mode 100644 index 0000000..a2bdb26 --- /dev/null +++ b/lib/facter/python_version.rb @@ -0,0 +1,28 @@ +# Make python versions available as facts +# In lists default python and system python versions +require 'puppet' +pkg = Puppet::Type.type(:package).new(:name => "python") + +Facter.add("system_python_version") do + setcode do + if pkg.retrieve[pkg.property(:ensure)] != 'purged' + /^(\d+\.\d+\.\d+).*$/.match(pkg.retrieve[pkg.property(:ensure)])[1] + end + end +end + +Facter.add("python_version") do + has_weight 100 + setcode do + /^.*(\d+\.\d+\.\d+)$/.match(Facter::Util::Resolution.exec('python -V'))[1] + end +end + +Facter.add("python_version") do + has_weight 50 + setcode do + if pkg.retrieve[pkg.property(:ensure)] != 'purged' + /^.*(\d+\.\d+\.\d+).*$/.match(pkg.retrieve[pkg.property(:ensure)])[1] + end + end +end diff --git a/lib/facter/virtualenv_version.rb b/lib/facter/virtualenv_version.rb new file mode 100644 index 0000000..c923b09 --- /dev/null +++ b/lib/facter/virtualenv_version.rb @@ -0,0 +1,19 @@ +# Make virtualenv version available as a fact +# Works with virualenv loaded and without, pip installed and package installed +require 'puppet' +pkg = Puppet::Type.type(:package).new(:name => "virtualenv") +Facter.add("virtualenv_version") do + has_weight 100 + setcode do + Facter::Util::Resolution.exec('virtualenv --version') + end +end + +Facter.add("virtualenv_version") do + has_weight 50 + setcode do + if pkg.retrieve[pkg.property(:ensure)] != 'purged' + /^.*(\d+\.\d+\.\d+).*$/.match(pkg.retrieve[pkg.property(:ensure)])[1] + end + end +end diff --git a/manifests/config.pp b/manifests/config.pp index fdd808f..c7196f2 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -1,3 +1,18 @@ +# == Define: python::config +# +# Optionally installs the gunicorn service +# +# === Examples +# +# include python::config +# +# === Authors +# +# Sergey Stankevich +# Ashley Penney +# Fotis Gimian +# + class python::config { Class['python::install'] -> Python::Pip <| |> @@ -21,4 +36,5 @@ class python::config { } } } + } diff --git a/manifests/gunicorn.pp b/manifests/gunicorn.pp index 13f4872..159afa3 100644 --- a/manifests/gunicorn.pp +++ b/manifests/gunicorn.pp @@ -37,6 +37,8 @@ # dir => '/var/www/project1/current', # bind => 'unix:/tmp/gunicorn.socket', # environment => 'prod', +# owner => 'www-data', +# group => 'www-data', # template => 'python/gunicorn.erb', # } # @@ -53,6 +55,8 @@ define python::gunicorn ( $dir = false, $bind = false, $environment = false, + $owner = 'www-data', + $group = 'www-data', $template = 'python/gunicorn.erb', ) { diff --git a/manifests/init.pp b/manifests/init.pp index 74244e1..4797b11 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -14,7 +14,8 @@ # Install python-dev. Default: false # # [*virtualenv*] -# Install python-virtualenv. Default: false +# Install python-virtualenv. Default: false, also accepts 'pip' which will +# install latest virtualenv from pip rather than package manager # # [*gunicorn*] # Install Gunicorn. Default: false @@ -37,17 +38,18 @@ # Sergey Stankevich # class python ( - $version = 'system', - $pip = false, - $dev = false, - $virtualenv = false, - $gunicorn = false, - $manage_gunicorn = true + $version = 'system', + $pip = false, + $dev = false, + $virtualenv = false, + $gunicorn = false, + $manage_gunicorn = true, + $provider = undef ) { # Module compatibility check - $compatible = [ 'Debian', 'Ubuntu', 'CentOS', 'RedHat', 'Scientific' ] - if ! ($::operatingsystem in $compatible) { + $compatible = [ 'Debian', 'RedHat'] + if ! ($::osfamily in $compatible) { fail("Module is not compatible with ${::operatingsystem}") } diff --git a/manifests/install.pp b/manifests/install.pp index caead49..c4914f7 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -1,3 +1,18 @@ +# == Define: python::install +# +# Installs core python packages +# +# === Examples +# +# include python::install +# +# === Authors +# +# Sergey Stankevich +# Ashley Penney +# Fotis Gimian +# + class python::install { $python = $python::version ? { @@ -5,13 +20,11 @@ class python::install { default => "python${python::version}", } - $pythondev = $::operatingsystem ? { - /(?i:RedHat|CentOS|Fedora|Scientific)/ => "${python}-devel", - /(?i:Debian|Ubuntu)/ => "${python}-dev" + $pythondev = $::osfamily ? { + RedHat => "${python}-devel", + Debian => "${python}-dev" } - package { $python: ensure => present } - $dev_ensure = $python::dev ? { true => present, default => absent, @@ -22,15 +35,26 @@ class python::install { default => absent, } - package { $pythondev: ensure => $dev_ensure } - package { 'python-pip': ensure => $pip_ensure } - $venv_ensure = $python::virtualenv ? { true => present, default => absent, } - package { 'python-virtualenv': ensure => $venv_ensure } + # Install latest from pip if pip is the provider + case $python::provider { + pip: { + package { 'virtualenv': ensure => latest, provider => pip } + package { 'pip': ensure => latest, provider => pip } + package { $pythondev: ensure => latest } + package { "python==${python::version}": ensure => latest, provider => pip } + } + default: { + package { 'python-virtualenv': ensure => $venv_ensure } + package { 'python-pip': ensure => $pip_ensure } + package { $pythondev: ensure => $dev_ensure } + package { $python: ensure => present } + } + } if $python::manage_gunicorn { $gunicorn_ensure = $python::gunicorn ? { diff --git a/manifests/pip.pp b/manifests/pip.pp index 7b51439..fb73ae7 100644 --- a/manifests/pip.pp +++ b/manifests/pip.pp @@ -57,7 +57,7 @@ define python::pip ( $cwd = $virtualenv ? { 'system' => '/', - default => "${virtualenv}", + default => $virtualenv, } $pip_env = $virtualenv ? { @@ -85,19 +85,36 @@ define python::pip ( default => "${url}#egg=${egg_name}", } + # Python 2.6 and older does not support setuptools/distribute > 0.8 which + # is required for pip wheel support, pip therefor requires --no-use-wheel flag + # if the # pip version is more recent than 1.4.1 but using an old python or + # setuputils/distribute version + # To check for this we test for wheel parameter using help and then using + # version, this makes sure we only use wheels if they are supported + case $ensure { present: { exec { "pip_install_${name}": - command => "$pip_env --log ${cwd}/pip.log install $install_args ${proxy_flag} ${source}", - unless => "$pip_env freeze | grep -i -e ${grep_regex}", + command => "${pip_env} wheel --help > /dev/null 2>&1 && { ${pip_env} wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; ${pip_env} --log ${cwd}/pip.log install ${install_args} \$wheel_support_flag ${proxy_flag} ${source}", + unless => "${pip_env} freeze | grep -i -e ${grep_regex}", + user => $owner, + environment => $environment, + path => ['/usr/local/bin','/usr/bin','/bin', '/usr/sbin'], + } + } + + latest: { + exec { "pip_install_${name}": + command => "${pip_env} wheel --help > /dev/null 2>&1 && { ${pip_env} wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; ${pip_env} --log ${cwd}/pip.log install --upgrade \$wheel_support_flag ${proxy_flag} ${source}", user => $owner, environment => $environment, + path => ['/usr/local/bin','/usr/bin','/bin', '/usr/sbin'], } } latest: { exec { "pip_install_${name}": - command => "$pip_env --log ${cwd}/pip.log install -U $install_args ${proxy_flag} ${source}", + command => "${pip_env} wheel --help > /dev/null 2>&1 && { ${pip_env} wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; ${pip_env} --log ${cwd}/pip.log install -U ${install_args} \$wheel_support_flag ${proxy_flag} ${source}", user => $owner, environment => $environment, } @@ -105,10 +122,11 @@ define python::pip ( default: { exec { "pip_uninstall_${name}": - command => "echo y | $pip_env uninstall $uninstall_args ${proxy_flag} ${name}", - onlyif => "$pip_env freeze | grep -i -e ${grep_regex}", + command => "echo y | ${pip_env} uninstall ${uninstall_args} ${proxy_flag} ${name}", + onlyif => "${pip_env} freeze | grep -i -e ${grep_regex}", user => $owner, environment => $environment, + path => ['/usr/local/bin','/usr/bin','/bin', '/usr/sbin'], } } } diff --git a/manifests/requirements.pp b/manifests/requirements.pp index 60c5b6c..5fa6eb9 100644 --- a/manifests/requirements.pp +++ b/manifests/requirements.pp @@ -27,6 +27,11 @@ # [*environment*] # Additional environment variables required to install the packages. Default: none # +# [*forceupdate*] +# Run a pip install requirements even if we don't receive an event from the +# requirements file - Useful for when the requirements file is written as part of a +# resource other than file (E.g vcsrepo) +# # === Examples # # python::requirements { '/var/www/project1/requirements.txt': @@ -47,7 +52,8 @@ define python::requirements ( $group = 'root', $proxy = false, $src = false, - $environment = [] + $environment = [], + $forceupdate = false, ) { if $virtualenv == 'system' and ($owner != 'root' or $group != 'root') { @@ -56,7 +62,7 @@ define python::requirements ( $cwd = $virtualenv ? { 'system' => '/', - default => "${virtualenv}", + default => $virtualenv, } $pip_env = $virtualenv ? { @@ -90,8 +96,8 @@ define python::requirements ( exec { "python_requirements${name}": provider => shell, - command => "${pip_env} --log-file ${cwd}/pip.log install ${proxy_flag} ${src_flag} -r ${requirements}", - refreshonly => true, + command => "${pip_env} --log ${cwd}/pip.log install ${proxy_flag} ${src_flag} -r ${requirements}", + refreshonly => !$forceupdate, timeout => 1800, user => $owner, subscribe => File[$requirements], diff --git a/manifests/virtualenv.pp b/manifests/virtualenv.pp index 8486183..7f7fbb4 100644 --- a/manifests/virtualenv.pp +++ b/manifests/virtualenv.pp @@ -15,6 +15,8 @@ # # [*systempkgs*] # Copy system site-packages into virtualenv. Default: don't +# If virtualenv version < 1.7 this flag has no effect since +# the system packages were not supported # # [*distribute*] # Include distribute in the virtualenv. Default: true @@ -72,7 +74,7 @@ define python::virtualenv ( $group = 'root', $proxy = false, $environment = [], - $path = [ '/bin', '/usr/bin', '/usr/sbin' ], + $path = [ '/bin', '/usr/bin', '/usr/sbin','/usr/local/bin' ], $cwd = undef, $timeout = 1800 ) { @@ -96,9 +98,16 @@ define python::virtualenv ( default => "&& export http_proxy=${proxy}", } - $system_pkgs_flag = $systempkgs ? { - false => '', - default => '--system-site-packages', + # Virtualenv versions prior to 1.7 do not support the + # --system-site-packages flag, default off for prior versions + # Prior to version 1.7 the default was equal to --system-site-packages + # and the flag --no-site-packages had to be passed to do the opposite + if (( versioncmp($::virtualenv_version,'1.7') > 0 ) and ( $systempkgs == true )) { + $system_pkgs_flag = '--system-site-packages' + } elsif (( versioncmp($::virtualenv_version,'1.7') < 0 ) and ( $systempkgs == false )) { + $system_pkgs_flag = '--no-site-packages' + } else { + $system_pkgs_flag = '' } $distribute_pkg = $distribute ? { @@ -110,18 +119,25 @@ define python::virtualenv ( default => "-i ${index}", } + # Python 2.6 and older does not support setuptools/distribute > 0.8 which + # is required for pip wheel support, pip therefor requires --no-use-wheel flag + # if the # pip version is more recent than 1.4.1 but using an old python or + # setuputils/distribute version + # To check for this we test for wheel parameter using help and then using + # version, this makes sure we only use wheels if they are supported + exec { "python_virtualenv_${venv_dir}": - command => "mkdir -p ${venv_dir} ${proxy_command} && virtualenv ${system_pkgs_flag} -p ${python} ${venv_dir} && ${venv_dir}/bin/pip --log-file ${venv_dir}/pip.log install ${pypi_index} ${proxy_flag} --upgrade pip ${distribute_pkg}", - user => $owner, - creates => "${venv_dir}/bin/activate", - path => $path, - cwd => "/tmp", + command => "mkdir -p ${venv_dir} ${proxy_command} && virtualenv ${system_pkgs_flag} -p ${python} ${venv_dir} && ${venv_dir}/bin/pip wheel --help > /dev/null 2>&1 && { ${venv_dir}/bin/pip wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; ${venv_dir}/bin/pip --log ${venv_dir}/pip.log install ${pypi_index} ${proxy_flag} \$wheel_support_flag --upgrade pip ${distribute_pkg}", + user => $owner, + path => $path, + cwd => $venv_dir, environment => $environment, + unless => "grep '^[\\t ]*VIRTUAL_ENV=[\\\\'\\\"]*${venv_dir}[\\\"\\\\'][\\t ]*$' ${venv_dir}/bin/activate", #Unless activate exists and VIRTUAL_ENV is correct we re-create the virtualenv } if $requirements { exec { "python_requirements_initial_install_${requirements}_${venv_dir}": - command => "${venv_dir}/bin/pip --log-file ${venv_dir}/pip.log install ${pypi_index} ${proxy_flag} -r ${requirements}", + command => "${venv_dir}/bin/pip wheel --help > /dev/null 2>&1 && { ${venv_dir}/bin/pip wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; ${venv_dir}/bin/pip --log ${venv_dir}/pip.log install ${pypi_index} ${proxy_flag} \$wheel_support_flag -r ${requirements}", refreshonly => true, timeout => $timeout, user => $owner, @@ -139,7 +155,6 @@ define python::virtualenv ( require => Exec["python_virtualenv_${venv_dir}"], } } - } elsif $ensure == 'absent' { file { $venv_dir: @@ -148,7 +163,5 @@ define python::virtualenv ( recurse => true, purge => true, } - } - } diff --git a/templates/gunicorn.erb b/templates/gunicorn.erb index 1a96531..10f81fa 100644 --- a/templates/gunicorn.erb +++ b/templates/gunicorn.erb @@ -1,36 +1,36 @@ CONFIG = { -<% if mode == 'django' -%> +<% if @mode == 'django' -%> 'mode': 'django', <% else -%> 'mode': 'wsgi', <% end -%> -<% if virtualenv -%> +<% if @virtualenv -%> 'environment': { -<% if environment -%> - 'ENVIRONMENT': '<%= environment %>', +<% if @environment -%> + 'ENVIRONMENT': '<%= @environment %>', <% end -%> - 'PYTHONPATH': '<%= virtualenv %>' + 'PYTHONPATH': '<%= @virtualenv %>' }, <% end -%> - 'working_dir': '<%= dir %>', - 'user': 'www-data', - 'group': 'www-data', -<% if virtualenv -%> - 'python': '<%= virtualenv %>/bin/python', + 'working_dir': '<%= @dir %>', + 'user': '<%= @owner %>', + 'group': '<%= @group %>', +<% if @virtualenv -%> + 'python': '<%= @virtualenv %>/bin/python', <% else -%> 'python': '/usr/bin/python', <% end -%> 'args': ( -<% if !virtualenv and !bind -%> - '--bind=unix:/tmp/gunicorn-<%= name %>.socket', -<% elsif virtualenv and !bind -%> - '--bind=unix:<%= virtualenv %>/<%= name %>.socket', +<% if !@virtualenv and !@bind -%> + '--bind=unix:/tmp/gunicorn-<%= @name %>.socket', +<% elsif @virtualenv and !@bind -%> + '--bind=unix:<%= @virtualenv %>/<%= @name %>.socket', <% else -%> - '--bind=<%= bind %>', + '--bind=<%= @bind %>', <% end -%> '--workers=<%= @processorcount.to_i*2 %>', '--timeout=30', -<% if mode != 'django' -%> +<% if @mode != 'django' -%> 'app:app', <% end -%> ), |