From ed137893babebabdfdb5adf44d1a52272093ce8b Mon Sep 17 00:00:00 2001 From: Sergey Stankevich Date: Sun, 9 Sep 2012 18:36:30 -0400 Subject: Initial import --- manifests/config.pp | 24 ++++++++++++++ manifests/gunicorn.pp | 65 +++++++++++++++++++++++++++++++++++++ manifests/init.pp | 50 +++++++++++++++++++++++++++++ manifests/install.pp | 31 ++++++++++++++++++ manifests/pip.pp | 64 ++++++++++++++++++++++++++++++++++++ manifests/requirements.pp | 68 +++++++++++++++++++++++++++++++++++++++ manifests/virtualenv.pp | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 384 insertions(+) create mode 100644 manifests/config.pp create mode 100644 manifests/gunicorn.pp create mode 100644 manifests/init.pp create mode 100644 manifests/install.pp create mode 100644 manifests/pip.pp create mode 100644 manifests/requirements.pp create mode 100644 manifests/virtualenv.pp (limited to 'manifests') diff --git a/manifests/config.pp b/manifests/config.pp new file mode 100644 index 0000000..43da22e --- /dev/null +++ b/manifests/config.pp @@ -0,0 +1,24 @@ +class python::config { + + Class['python::install'] -> Python::Pip <| |> + Class['python::install'] -> Python::Requirements <| |> + Class['python::install'] -> Python::Virtualenv <| |> + + Python::Virtualenv <| |> -> Python::Pip <| |> + Python::Virtualenv <| |> -> Python::Requirements <| |> + + if $python::gunicorn { + Class['python::install'] -> Python::Gunicorn <| |> + + Python::Gunicorn <| |> ~> Service['gunicorn'] + + service { 'gunicorn': + ensure => running, + enable => true, + hasrestart => true, + hasstatus => false, + pattern => '/usr/bin/gunicorn', + } + } + +} diff --git a/manifests/gunicorn.pp b/manifests/gunicorn.pp new file mode 100644 index 0000000..d328d75 --- /dev/null +++ b/manifests/gunicorn.pp @@ -0,0 +1,65 @@ +# == Define: python::gunicorn +# +# Manages Gunicorn virtual hosts. +# +# === Parameters +# +# [*ensure*] +# present|absent. Default: present +# +# [*virtualenv*] +# Run in virtualenv, specify directory. Default: disabled +# +# [*mode*] +# Gunicorn mode. +# wsgi|django. Default: wsgi +# +# [*dir*] +# Application directory. +# +# [*bind*] +# Bind on: 'HOST', 'HOST:PORT', 'unix:PATH'. +# Default: system-wide: unix:/tmp/gunicorn-$name.socket +# virtualenv: unix:${virtualenv}/${name}.socket +# +# [*environment*] +# Set ENVIRONMENT variable. Default: none +# +# === Examples +# +# python::gunicorn { 'vhost': +# ensure => present, +# virtualenv => '/var/www/project1', +# mode => 'wsgi', +# dir => '/var/www/project1/current', +# bind => 'unix:/tmp/gunicorn.socket', +# environment => 'prod', +# } +# +# === Authors +# +# Sergey Stankevich +# +define python::gunicorn ( + $ensure = present, + $virtualenv = false, + $mode = 'wsgi', + $dir = false, + $bind = false, + $environment = false +) { + + # Parameter validation + if ! $dir { + fail('python::gunicorn: dir parameter must not be empty') + } + + file { "/etc/gunicorn.d/${name}": + ensure => $ensure, + mode => '0644', + owner => 'root', + group => 'root', + content => template('python/gunicorn.erb'), + } + +} diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 0000000..c7ab10f --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,50 @@ +# == Class: python +# +# Installs and manages python, python-dev, python-virtualenv and Gunicorn. +# +# === Parameters +# +# [*version*] +# Python version to install. Default: system default +# +# [*dev*] +# Install python-dev. Default: false +# +# [*virtualenv*] +# Install python-virtualenv. Default: false +# +# [*gunicorn*] +# Install Gunicorn. Default: false +# +# === Examples +# +# class { 'python': +# version => 'system', +# dev => true, +# virtualenv => true, +# gunicorn => true, +# } +# +# === Authors +# +# Sergey Stankevich +# +class python ( + $version = 'system', + $dev = false, + $virtualenv = false, + $gunicorn = false +) { + + # Module compatibility check + $compatible = [ 'Debian', 'Ubuntu' ] + if ! ($::operatingsystem in $compatible) { + fail("Module is not compatible with ${::operatingsystem}") + } + + Class['python::install'] -> Class['python::config'] + + include python::install + include python::config + +} diff --git a/manifests/install.pp b/manifests/install.pp new file mode 100644 index 0000000..dec99b8 --- /dev/null +++ b/manifests/install.pp @@ -0,0 +1,31 @@ +class python::install { + + $python = $python::version ? { + 'system' => 'python', + default => "python${python::version}", + } + + package { $python: ensure => present } + + $dev_ensure = $python::dev ? { + true => present, + default => absent, + } + + package { "${python}-dev": ensure => $dev_ensure } + + $venv_ensure = $python::virtualenv ? { + true => present, + default => absent, + } + + package { 'python-virtualenv': ensure => $venv_ensure } + + $gunicorn_ensure = $python::gunicorn ? { + true => present, + default => absent, + } + + package { 'gunicorn': ensure => $gunicorn_ensure } + +} diff --git a/manifests/pip.pp b/manifests/pip.pp new file mode 100644 index 0000000..9762c10 --- /dev/null +++ b/manifests/pip.pp @@ -0,0 +1,64 @@ +# == Define: python::pip +# +# Installs and manages packages from pip. +# +# === Parameters +# +# [*ensure*] +# present|absent. Default: present +# +# [*virtualenv*] +# virtualenv to run pip in. +# +# [*proxy*] +# Proxy server to use for outbound connections. Default: none +# +# === Examples +# +# python::pip { 'flask': +# virtualenv => '/var/www/project1', +# proxy => 'http://proxy.domain.com:3128', +# } +# +# === Authors +# +# Sergey Stankevich +# +define python::pip ( + $virtualenv, + $ensure = present, + $proxy = false +) { + + # Parameter validation + if ! $virtualenv { + fail('python::pip: virtualenv parameter must not be empty') + } + + $proxy_flag = $proxy ? { + false => '', + default => "--proxy=${proxy}", + } + + $grep_regex = $name ? { + /==/ => "^${name}\$", + default => "^${name}==", + } + + case $ensure { + present: { + exec { "pip_install_${name}": + command => "${virtualenv}/bin/pip install ${proxy_flag} ${name}", + unless => "${virtualenv}/bin/pip freeze | grep -i -e ${grep_regex}", + } + } + + default: { + exec { "pip_uninstall_${name}": + command => "echo y | ${virtualenv}/bin/pip uninstall ${proxy_flag} ${name}", + onlyif => "${virtualenv}/bin/pip freeze | grep -i -e ${grep_regex}", + } + } + } + +} diff --git a/manifests/requirements.pp b/manifests/requirements.pp new file mode 100644 index 0000000..e49c86c --- /dev/null +++ b/manifests/requirements.pp @@ -0,0 +1,68 @@ +# == Define: python::requirements +# +# Installs and manages Python packages from requirements file. +# +# === Parameters +# +# [*virtualenv*] +# virtualenv to run pip in. Default: system-wide +# +# [*proxy*] +# Proxy server to use for outbound connections. Default: none +# +# === Examples +# +# python::requirements { '/var/www/project1/requirements.txt': +# virtualenv => '/var/www/project1', +# proxy => 'http://proxy.domain.com:3128', +# } +# +# === Authors +# +# Sergey Stankevich +# +define python::requirements ( + $virtualenv = 'system', + $proxy = false +) { + + $requirements = $name + + $pip_env = $virtualenv ? { + 'system' => '`which pip`', + default => "${virtualenv}/bin/pip", + } + + $proxy_flag = $proxy ? { + false => '', + default => "--proxy=${proxy}", + } + + $req_dir = inline_template('<%= requirements.match(%r!(.+)/.+!)[1] %>') + $req_crc = "${req_dir}/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', + } + + # SHA1 checksum to detect changes + exec { "python_requirements_check_${name}": + command => "sha1sum ${requirements} > ${req_crc}", + unless => "sha1sum -c ${req_crc}", + require => File[$requirements], + } + + exec { "python_requirements_update_${name}": + command => "${pip_env} install ${proxy_flag} -Ur ${requirements}", + cwd => $virtualenv, + refreshonly => true, + timeout => 1800, + subscribe => Exec["python_requirements_check_${name}"], + } + +} diff --git a/manifests/virtualenv.pp b/manifests/virtualenv.pp new file mode 100644 index 0000000..a5cf12b --- /dev/null +++ b/manifests/virtualenv.pp @@ -0,0 +1,82 @@ +# == Define: python::virtualenv +# +# Creates Python virtualenv. +# +# === Parameters +# +# [*ensure*] +# present|absent. Default: present +# +# [*version*] +# Python version to use. Default: system default +# +# [*requirements*] +# Path to pip requirements.txt file. Default: none +# +# [*proxy*] +# Proxy server to use for outbound connections. Default: none +# +# === Examples +# +# python::virtualenv { '/var/www/project1': +# ensure => present, +# version => 'system', +# requirements => '/var/www/project1/requirements.txt', +# proxy => 'http://proxy.domain.com:3128', +# } +# +# === Authors +# +# Sergey Stankevich +# +define python::virtualenv ( + $ensure = present, + $version = 'system', + $requirements = false, + $proxy = false +) { + + $venv_dir = $name + + if $ensure == 'present' { + + $python = $version ? { + 'system' => 'python', + default => "python${version}", + } + + $proxy_flag = $proxy ? { + false => '', + default => "--proxy=${proxy}", + } + + exec { "python_virtualenv_${venv_dir}": + command => "mkdir -p ${venv_dir} \ + && export http_proxy=${proxy} \ + && virtualenv -p `which ${python}` ${venv_dir} \ + && ${venv_dir}/bin/pip install ${proxy_flag} --upgrade distribute pip", + creates => $venv_dir, + } + + if $requirements { + Exec["python_virtualenv_${venv_dir}"] + -> Python::Requirements[$requirements] + + python::requirements { $requirements: + virtualenv => $venv_dir, + proxy => $proxy, + } + } + + } elsif $ensure == 'absent' { + + file { $venv_dir: + ensure => absent, + force => true, + recurse => true, + purge => true, + } + + } + +} -- cgit v1.2.3