example code: python2 and python3 install modules, script generators and ctf vulnerability/challenge module wrappers

This commit is contained in:
ts
2018-08-03 15:32:13 +01:00
parent 990d15a4c9
commit a6ff9c508b
79 changed files with 3796 additions and 2 deletions

View File

@@ -0,0 +1,38 @@
source ENV['GEM_SOURCE'] || "https://rubygems.org"
group :system_tests do
gem 'serverspec', :require => false
gem 'beaker', :require => false
gem 'beaker-rspec', :require => false
end
if puppetversion = ENV['PUPPET_GEM_VERSION']
gem 'puppet', puppetversion, :require => false
else
gem 'puppet', :require => false
end
if facterversion = ENV['FACTER_GEM_VERSION']
gem 'facter', facterversion, :require => false
else
gem 'facter', :require => false
end
gem 'rspec-puppet', '~> 2.0', :require => false
gem 'puppet-lint', '~> 2.0', :require => false
gem 'simplecov', :require => false
gem 'rspec', '~> 2.0', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
gem 'rake', '~> 10.0', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
gem 'rake', '<= 12.2.1', :require => false if RUBY_VERSION >= '1.9' && RUBY_VERSION < '2.0.0'
gem 'json', '<= 1.8', :require => false if RUBY_VERSION < '2.0.0'
gem 'json_pure', '<= 2.0.1', :require => false if RUBY_VERSION < '2.0.0'
gem 'metadata-json-lint', '0.0.11' if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
gem 'metadata-json-lint', '1.0.0' if RUBY_VERSION >= '1.9' && RUBY_VERSION < '2.0'
gem 'metadata-json-lint' if RUBY_VERSION >= '2.0'
gem 'puppetlabs_spec_helper', '2.0.2', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
gem 'puppetlabs_spec_helper', '>= 2.0.0', :require => false if RUBY_VERSION >= '1.9'
gem 'parallel_tests', '<= 2.9.0', :require => false if RUBY_VERSION < '2.0.0'
# vim:ft=ruby

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright © [2012-2014] [Sergey Stankevich]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,344 @@
# puppet-python [![Build Status](https://travis-ci.org/stankevich/puppet-python.svg?branch=master)](https://travis-ci.org/stankevich/puppet-python)
Puppet module for installing and managing python, pip, virtualenvs and Gunicorn virtual hosts.
===
# Compatibility #
See `.travis.yml` for compatibility matrix.
* Puppet v3 (with the future parser)
* Puppet v4
## Ruby versions
* 1.8.7 - Puppet 3
* 1.9.3 - Puppet 3
* 2.0.0 - Puppet 3
* 2.1.9 - Puppet 3 & 4
## OS Distributions ##
This module has been tested to work on the following systems.
* Debian 6
* Debian 7
* Debian 8
* Debian 9
* EL 5
* EL 6
* EL 7
* Gentoo (and Sabayon)
* Suse 11
* Ubuntu 10.04
* Ubuntu 12.04
* Ubuntu 14.04
* Ubuntu 16.04
===
## Installation
```shell
git submodule add https://github.com/stankevich/puppet-python.git /path/to/python
```
OR
``` shell
puppet module install stankevich-python
```
## Usage
### python
Installs and manages python, python-pip, python-dev, python-virtualenv and Gunicorn.
**ensure** - Desired installation state for the Python package. Options are absent, present and latest. Default: present
**version** - Python version to install. Default: system
**pip** - Desired installation state for the python-pip package. Options are absent, present and latest. Default: present
**dev** - Desired installation state for the python-dev package. Options are absent, present and latest. Default: absent
**virtualenv** - Desired installation state for the virtualenv package. Options are absent, present and latest. Default: absent
**gunicorn** - Desired installation state for Gunicorn. Options are absent, present and latest. Default: absent
**manage_gunicorn** - Allow Installation / Removal of Gunicorn. Default: true
**use_epel** - Boolean to determine if the epel class is used. Default: true on RHEL like systems, false otherwise
```puppet
class { 'python' :
version => 'system',
pip => 'present',
dev => 'absent',
virtualenv => 'absent',
gunicorn => 'absent',
}
```
### python::pip
Installs and manages packages from pip.
**pkgname** - the name of the package to install. Required.
**ensure** - present/latest/absent. You can also specify the version. Default: present
**virtualenv** - virtualenv to run pip in. Default: system (no virtualenv)
**url** - URL to install from. Default: none
**owner** - The owner of the virtualenv to ensure that packages are installed with the correct permissions (must be specified). Default: root
**proxy** - Proxy server to use for outbound connections. Default: none
**environment** - Additional environment variables required to install the packages. Default: none
**egg** - The egg name to use. Default: `$name` of the class, e.g. cx_Oracle
**install_args** - String of additional flags to pass to pip during installaton. Default: none
**uninstall_args** - String of additional flags to pass to pip during uninstall. Default: none
**timeout** - Timeout for the pip install command. Defaults to 1800.
```puppet
python::pip { 'cx_Oracle' :
pkgname => 'cx_Oracle',
ensure => '5.1.2',
virtualenv => '/var/www/project1',
owner => 'appuser',
proxy => 'http://proxy.domain.com:3128',
environment => 'ORACLE_HOME=/usr/lib/oracle/11.2/client64',
install_args => '-e',
timeout => 1800,
}
```
### python::requirements
Installs and manages Python packages from requirements file.
**virtualenv** - virtualenv to run pip in. Default: system-wide
**proxy** - Proxy server to use for outbound connections. Default: none
**owner** - The owner of the virtualenv to ensure that packages are installed with the correct permissions (must be specified). Default: root
**src** - The `--src` parameter to `pip`, used to specify where to install `--editable` resources; by default no `--src` parameter is passed to `pip`.
**group** - The group that was used to create the virtualenv. This is used to create the requirements file with correct permissions if it's not present already.
**manage_requirements** - Create the requirements file if it doesn't exist. Default: true
```puppet
python::requirements { '/var/www/project1/requirements.txt' :
virtualenv => '/var/www/project1',
proxy => 'http://proxy.domain.com:3128',
owner => 'appuser',
group => 'apps',
}
```
### python::virtualenv
Creates Python virtualenv.
**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
**systempkgs** - Copy system site-packages into virtualenv. Default: don't
**distribute** - Include distribute in the virtualenv. Default: true
**venv_dir** - The location of the virtualenv if resource path not specified. Must be absolute path. Default: resource name
**owner** - Specify the owner of this virtualenv
**group** - Specify the group for this virtualenv
**index** - Base URL of Python package index. Default: none
**cwd** - The directory from which to run the "pip install" command. Default: undef
**timeout** - The maximum time in seconds the "pip install" command should take. Default: 1800
```puppet
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,
venv_dir => '/home/appuser/virtualenvs',
owner => 'appuser',
group => 'apps',
cwd => '/var/www/project1',
timeout => 0,
}
```
### python::pyvenv
Creates Python3 virtualenv.
**ensure** - present/absent. Default: present
**version** - Python version to use. Default: system default
**systempkgs** - Copy system site-packages into virtualenv. Default: don't
**venv_dir** - The location of the virtualenv if resource path not specified. Must be absolute path. Default: resource name
**owner** - Specify the owner of this virtualenv
**group** - Specify the group for this virtualenv
**path** - Specifies the PATH variable that contains `pyvenv` executable. Default: [ '/bin', '/usr/bin', '/usr/sbin' ]
**environment** - Specify any environment variables to use when creating pyvenv
```puppet
python::pyvenv { '/var/www/project1' :
ensure => present,
version => 'system',
systempkgs => true,
venv_dir => '/home/appuser/virtualenvs',
owner => 'appuser',
group => 'apps',
}
```
### python::gunicorn
Manages Gunicorn virtual hosts.
**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: `unix:/tmp/gunicorn-$name.socket` or `unix:${virtualenv}/${name}.socket`
**environment** - Set ENVIRONMENT variable. Default: none
**appmodule** - Set the application module name for gunicorn to load when not using Django. Default: `app:app`
**osenv** - Allows setting environment variables for the gunicorn service. Accepts a hash of 'key': 'value' pairs. Default: false
**timeout** - Allows setting the gunicorn idle worker process time before being killed. The unit of time is seconds. Default: 30
**template** - Which ERB template to use. Default: python/gunicorn.erb
```puppet
python::gunicorn { 'vhost' :
ensure => present,
virtualenv => '/var/www/project1',
mode => 'wsgi',
dir => '/var/www/project1/current',
bind => 'unix:/tmp/gunicorn.socket',
environment => 'prod',
appmodule => 'app:app',
osenv => { 'DBHOST' => 'dbserver.example.com' },
timeout => 30,
template => 'python/gunicorn.erb',
}
```
### python::dotfile
Manages arbitrary python dotiles with a simple config hash.
**ensure** - present/absent. Default: present
**filename** - Default: $title
**mode** - Default: 0644
**owner** - Default: root
**group** - Default: root
**config** Config hash. This will be expanded to an ini-file. Default: {}
```puppet
python::dotfile { '/var/lib/jenkins/.pip/pip.conf':
ensure => present,
owner => 'jenkins',
group => 'jenkins',
config => {
'global' => {
'index-url => 'https://mypypi.acme.com/simple/'
'extra-index-url => https://pypi.risedev.at/simple/
}
}
}
```
### hiera configuration
This module supports configuration through hiera. The following example
creates two python3 virtualenvs. The configuration also pip installs a
package into each environment.
```yaml
python::python_pyvenvs:
"/opt/env1":
version: "system"
"/opt/env2":
version: "system"
python::python_pips:
"nose":
virtualenv: "/opt/env1"
"coverage":
virtualenv: "/opt/env2"
python::python_dotfiles:
"/var/lib/jenkins/.pip/pip.conf":
config:
global:
index-url: "https://mypypi.acme.com/simple/"
extra-index-url: "https://pypi.risedev.at/simple/"
```
### Using SCL packages from RedHat or CentOS
To use this module with Linux distributions in the Red Hat family and python distributions
from softwarecollections.org, set python::provider to 'rhscl' and python::version to the name
of the collection you want to use (e.g., 'python27', 'python33', or 'rh-python34').
## Release Notes
**Version 1.9.8 Notes**
The `pip`, `virtualenv` and `gunicorn` parameters of `Class['python']` have changed. These parameters now accept `absent`, `present` and `latest` rather than `true` and `false`. The boolean values are still supported and are equivalent to `present` and `absent` respectively. Support for these boolean parameters is deprecated and will be removed in a later release.
**Version 1.7.10 Notes**
Installation of python-pip previously defaulted to `false` and was not installed. This default is now `true` and python-pip is installed. To prevent the installation of python-pip specify `pip => false` as a parameter when instantiating the `python` puppet class.
**Version 1.1.x Notes**
Version `1.1.x` makes several fundamental changes to the core of this module, adding some additional features, improving performance and making operations more robust in general.
Please note that several changes have been made in `v1.1.x` which make manifests incompatible with the previous version. However, modifying your manifests to suit is trivial. Please see the notes below.
Currently, the changes you need to make are as follows:
* All pip definitions MUST include the owner field which specifies which user owns the virtualenv that packages will be installed in. Adding this greatly improves performance and efficiency of this module.
* You must explicitly specify pip => true in the python class if you want pip installed. As such, the pip package is now independent of the dev package and so one can exist without the other.
## Authors
[Sergey Stankevich](https://github.com/stankevich) | [Shiva Poudel](https://github.com/shivapoudel) | [Peter Souter](https://github.com/petems) | [Garrett Honeycutt](http://learnpuppet.com)

View File

@@ -0,0 +1,46 @@
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-lint/tasks/puppet-lint'
require 'puppet-syntax/tasks/puppet-syntax'
# These two gems aren't always present, for instance
# on Travis with --without development
begin
require 'puppet_blacksmith/rake_tasks'
rescue LoadError
end
PuppetLint.configuration.fail_on_warnings
PuppetLint.configuration.send('relative')
PuppetLint.configuration.send('disable_80chars')
PuppetLint.configuration.send('disable_140chars')
PuppetLint.configuration.send('disable_class_inherits_from_params_class')
PuppetLint.configuration.send('disable_class_parameter_defaults')
PuppetLint.configuration.send('disable_documentation')
PuppetLint.configuration.send('disable_single_quote_string_with_variables')
exclude_paths = [
"pkg/**/*",
"vendor/**/*",
"spec/**/*",
]
PuppetLint.configuration.ignore_paths = exclude_paths
PuppetSyntax.exclude_paths = exclude_paths
desc 'Validate manifests, templates, ruby files and shell scripts'
task :validate do
Dir['spec/**/*.rb'].each do |ruby_file|
sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/
end
end
desc "Run acceptance tests"
RSpec::Core::RakeTask.new(:acceptance) do |t|
t.pattern = 'spec/acceptance'
end
desc "Run syntax, lint, and spec tests."
task :test => [
:syntax,
:lint,
:spec,
]

View File

@@ -0,0 +1,53 @@
{
"Gemfile": "c8ff2188da4e5252935d5c3935d480d3",
"LICENSE": "cf2903831f7e18e82a84cce52f44e4a8",
"README.md": "d76d14082c4c2e4a857168218b3adaea",
"Rakefile": "1e5f007de3d45235639cf0ac971250c6",
"lib/facter/pip_version.rb": "94fb2b635dbe71abe0891ba3c1262acf",
"lib/facter/python_release.rb": "f1f7a52cb7981fa67ea07b3d39e088e2",
"lib/facter/python_version.rb": "03f933f329dd8ca388962d5c72048391",
"lib/facter/virtualenv_version.rb": "09837fdf91dfc4daff395874ab63b992",
"manifests/config.pp": "e96cbfc9b920703d3ba91111226de7f5",
"manifests/dotfile.pp": "f6196d257b1c9e8ffde00eef603f4863",
"manifests/gunicorn.pp": "63fe13138fbdde5e14aa43729158f44c",
"manifests/init.pp": "57cfc54ae0af76635df71983e9870234",
"manifests/install.pp": "25f6368563a9aad67fb6e5e43b5dd824",
"manifests/params.pp": "2367376030fad24ba7e4f131d6a87351",
"manifests/pip.pp": "f19814df7ed8151e3aa8f2419e65bd01",
"manifests/pyvenv.pp": "fe680b2c5abc2ac569ff63229f174403",
"manifests/requirements.pp": "866cb2d0ecc5a6415b64b8501c6ca779",
"manifests/virtualenv.pp": "660f1d394d85eff1b4e84ad9210da423",
"metadata.json": "1ecf9220777a1338584728d4994e898f",
"spec/acceptance/class_spec.rb": "784a085709ec2d998961bd6fe45452a6",
"spec/acceptance/facts_test_spec.rb": "c1b5485528b0b1163947e134cea7ce2a",
"spec/acceptance/nodesets/centos-59-x64.yml": "57eb3e471b9042a8ea40978c467f8151",
"spec/acceptance/nodesets/centos-64-x64-pe.yml": "ec075d95760df3d4702abea1ce0a829b",
"spec/acceptance/nodesets/centos-65-x64.yml": "3e5c36e6aa5a690229e720f4048bb8af",
"spec/acceptance/nodesets/debian-70rc1-x64.yml": "715f798e696d3582c66d13f0e8e5f009",
"spec/acceptance/nodesets/debian-73-x64.yml": "b44b7146a828c37482c06879862fb5d9",
"spec/acceptance/nodesets/default.yml": "e27bb4d7526ad3c7a1c4aeb87decec15",
"spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297",
"spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269",
"spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0",
"spec/acceptance/virtualenv_spec.rb": "4494eaf3b0de430fac9df01504c93d2d",
"spec/classes/python_spec.rb": "77af2a49ac7a674661d32633d1245ce7",
"spec/defines/gunicorn_spec.rb": "de12b6b712b04f1175b33cdc6c92b041",
"spec/defines/pip_spec.rb": "c0f0044d49b241370363683331570838",
"spec/defines/pyvenv_spec.rb": "010c4568f19e22603ad712c189192ab8",
"spec/defines/requirements_spec.rb": "9591058f9b823ffc7db27a9d30a10177",
"spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
"spec/spec_helper.rb": "74509bb112ac200b2860e116b601fac4",
"spec/spec_helper_acceptance.rb": "59044ad83a006591c63dab149b43afad",
"spec/unit/facter/pip_version_spec.rb": "bc1e73c99891f780d5f6ca60258e8097",
"spec/unit/facter/python_release_spec.rb": "db51f418cc5ad314494a6c3fddc003a6",
"spec/unit/facter/python_version_spec.rb": "be3b595c06e94867efea854b2796d617",
"spec/unit/facter/virtualenv_version_spec.rb": "abb87062002bec85ef1b5b28eeda4101",
"templates/gunicorn.erb": "7d1a6b3340dbdad069e0bdfb14255271",
"templates/inifile.erb": "ce9b0646bd1bcf91a2be0997d44c917f",
"tests/gunicorn.pp": "ac09401c1e329008fef8e9ad6e6971bd",
"tests/init.pp": "251c210b05aab1f84c49a38f7fe48bbe",
"tests/pip.pp": "e3a793d4c714c39df31f3f79f0d7629c",
"tests/pyvenv.pp": "d4c050a2b358d4516d613869fab23113",
"tests/requirements.pp": "4a5e714fbbd623e519f0c07914367730",
"tests/virtualenv.pp": "698f811b9110cbc5d9262f0500bd7ee4"
}

View File

@@ -0,0 +1,9 @@
# Make pip version available as a fact
Facter.add("pip_version") do
setcode do
if Facter::Util::Resolution.which('pip')
Facter::Util::Resolution.exec('pip --version 2>&1').match(/^pip (\d+\.\d+\.?\d*).*$/)[1]
end
end
end

View File

@@ -0,0 +1,33 @@
# Make python release available as facts
def get_python_release(executable)
if Facter::Util::Resolution.which(executable)
results = Facter::Util::Resolution.exec("#{executable} -V 2>&1").match(/^.*(\d+\.\d+)\.\d+\+?$/)
if results
results[1]
end
end
end
Facter.add("python_release") do
setcode do
get_python_release 'python'
end
end
Facter.add("python2_release") do
setcode do
default_release = get_python_release 'python'
if default_release.nil? or !default_release.start_with?('2')
get_python_release 'python2'
else
default_release
end
end
end
Facter.add("python3_release") do
setcode do
get_python_release 'python3'
end
end

View File

@@ -0,0 +1,33 @@
# Make python versions available as facts
def get_python_version(executable)
if Facter::Util::Resolution.which(executable)
results = Facter::Util::Resolution.exec("#{executable} -V 2>&1").match(/^.*(\d+\.\d+\.\d+\+?)$/)
if results
results[1]
end
end
end
Facter.add("python_version") do
setcode do
get_python_version 'python'
end
end
Facter.add("python2_version") do
setcode do
default_version = get_python_version 'python'
if default_version.nil? or !default_version.start_with?('2')
get_python_version 'python2'
else
default_version
end
end
end
Facter.add("python3_version") do
setcode do
get_python_version 'python3'
end
end

View File

@@ -0,0 +1,9 @@
# Make virtualenv version available as a fact
Facter.add("virtualenv_version") do
setcode do
if Facter::Util::Resolution.which('virtualenv')
Facter::Util::Resolution.exec('virtualenv --version 2>&1').match(/^(\d+\.\d+\.?\d*).*$/)[0]
end
end
end

View File

@@ -0,0 +1,40 @@
# == 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 <| |>
Class['python::install'] -> Python::Requirements <| |>
Class['python::install'] -> Python::Virtualenv <| |>
Python::Virtualenv <| |> -> Python::Pip <| |>
if $python::manage_gunicorn {
if $python::gunicorn != 'absent' {
Class['python::install'] -> Python::Gunicorn <| |>
Python::Gunicorn <| |> ~> Service['gunicorn']
service { 'gunicorn':
ensure => running,
enable => true,
hasrestart => true,
hasstatus => false,
pattern => '/usr/bin/gunicorn',
}
}
}
}

View File

@@ -0,0 +1,62 @@
# == Define: python::dotfile
#
# Manages any python dotfiles with a simple config hash.
#
# === Parameters
#
# [*ensure*]
# present|absent. Default: present
#
# [*filename*]
# Filename. Default: $title
#
# [*mode*]
# File mode. Default: 0644
#
# [*owner*]
# [*group*]
# Owner/group. Default: `root`/`root`
#
# [*config*]
# Config hash. This will be expanded to an ini-file. Default: {}
#
# === Examples
#
# python::dotfile { '/var/lib/jenkins/.pip/pip.conf':
# ensure => present,
# owner => 'jenkins',
# group => 'jenkins',
# config => {
# 'global' => {
# 'index-url => 'https://mypypi.acme.com/simple/'
# 'extra-index-url => https://pypi.risedev.at/simple/
# }
# }
# }
#
#
define python::dotfile (
$ensure = 'present',
$filename = $title,
$owner = 'root',
$group = 'root',
$mode = '0644',
$config = {},
) {
$parent_dir = dirname($filename)
exec { "create ${title}'s parent dir":
command => "install -o ${owner} -g ${group} -d ${parent_dir}",
path => [ '/usr/bin', '/bin', '/usr/local/bin', ],
creates => $parent_dir,
}
file { $filename:
ensure => $ensure,
owner => $owner,
group => $group,
mode => $mode,
content => template("${module_name}/inifile.erb"),
require => Exec["create ${title}'s parent dir"],
}
}

View File

@@ -0,0 +1,132 @@
# == Define: python::gunicorn
#
# Manages Gunicorn virtual hosts.
#
# === Parameters
#
# [*ensure*]
# present|absent. Default: present
#
# [*config_dir*]
# Configure the gunicorn config directory path. Default: /etc/gunicorn.d
#
# [*manage_config_dir*]
# Set if the gunicorn config directory should be created. Default: false
#
# [*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
#
# [*appmodule*]
# Set the application module name for gunicorn to load when not using Django.
# Default: app:app
#
# [*osenv*]
# Allows setting environment variables for the gunicorn service. Accepts a
# hash of 'key': 'value' pairs.
# Default: false
#
# [*timeout*]
# Allows setting the gunicorn idle worker process time before being killed.
# The unit of time is seconds.
# Default: 30
#
# [*template*]
# Which ERB template to use. Default: python/gunicorn.erb
#
# [*args*]
# Custom arguments to add in gunicorn config file. Default: []
#
# === Examples
#
# python::gunicorn { 'vhost':
# ensure => present,
# virtualenv => '/var/www/project1',
# mode => 'wsgi',
# dir => '/var/www/project1/current',
# bind => 'unix:/tmp/gunicorn.socket',
# environment => 'prod',
# owner => 'www-data',
# group => 'www-data',
# appmodule => 'app:app',
# osenv => { 'DBHOST' => 'dbserver.example.com' },
# timeout => 30,
# template => 'python/gunicorn.erb',
# }
#
# === Authors
#
# Sergey Stankevich
# Ashley Penney
# Marc Fournier
#
define python::gunicorn (
$ensure = present,
$config_dir = '/etc/gunicorn.d',
$manage_config_dir = false,
$virtualenv = false,
$mode = 'wsgi',
$dir = false,
$bind = false,
$environment = false,
$owner = 'www-data',
$group = 'www-data',
$appmodule = 'app:app',
$osenv = false,
$timeout = 30,
$workers = false,
$access_log_format = false,
$accesslog = false,
$errorlog = false,
$log_level = 'error',
$template = 'python/gunicorn.erb',
$args = [],
) {
# Parameter validation
if ! $dir {
fail('python::gunicorn: dir parameter must not be empty')
}
validate_re($log_level, 'debug|info|warning|error|critical', "Invalid \$log_level value ${log_level}")
if $manage_config_dir {
file { $config_dir:
ensure => directory,
mode => '0755',
owner => 'root',
group => 'root',
}
file { "${config_dir}/${name}":
ensure => $ensure,
mode => '0644',
owner => 'root',
group => 'root',
content => template($template),
require => File[$config_dir],
}
} else {
file { "${config_dir}/${name}":
ensure => $ensure,
mode => '0644',
owner => 'root',
group => 'root',
content => template($template),
}
}
}

View File

@@ -0,0 +1,150 @@
# == Class: python
#
# Installs and manages python, python-dev, python-virtualenv and Gunicorn.
#
# === Parameters
#
# [*ensure*]
# Desired installation state for the Python package. Valid options are absent,
# present and latest. Default: present
#
# [*version*]
# Python version to install. Beware that valid values for this differ a) by
# the provider you choose and b) by the osfamily/operatingsystem you are using.
# Default: system default
# Allowed values:
# - provider == pip: everything pip allows as a version after the 'python=='
# - else: 'system', 'pypy', 3/3.3/...
# - Be aware that 'system' usually means python 2.X.
# - 'pypy' actually lets us use pypy as python.
# - 3/3.3/... means you are going to install the python3/python3.3/...
# package, if available on your osfamily.
#
# [*pip*]
# Desired installation state for python-pip. Boolean values are deprecated.
# Default: present
# Allowed values: 'absent', 'present', 'latest'
#
# [*dev*]
# Desired installation state for python-dev. Boolean values are deprecated.
# Default: absent
# Allowed values: 'absent', 'present', 'latest'
#
# [*virtualenv*]
# Desired installation state for python-virtualenv. Boolean values are
# deprecated. Default: absent
# Allowed values: 'absent', 'present', 'latest
#
# [*gunicorn*]
# Desired installation state for Gunicorn. Boolean values are deprecated.
# Default: absent
# Allowed values: 'absent', 'present', 'latest'
#
# [*manage_gunicorn*]
# Allow Installation / Removal of Gunicorn. Default: true
#
# [*provider*]
# What provider to use for installation of the packages, except gunicorn and
# Python itself. Default: system default provider
# Allowed values: 'pip'
#
# [*use_epel*]
# Boolean to determine if the epel class is used. Default: true
#
# === Examples
#
# class { 'python':
# version => 'system',
# pip => 'present',
# dev => 'present',
# virtualenv => 'present',
# gunicorn => 'present',
# }
#
# === Authors
#
# Sergey Stankevich
# Garrett Honeycutt <code@garretthoneycutt.com>
#
class python (
$ensure = $python::params::ensure,
$version = $python::params::version,
$pip = $python::params::pip,
$dev = $python::params::dev,
$virtualenv = $python::params::virtualenv,
$gunicorn = $python::params::gunicorn,
$manage_gunicorn = $python::params::manage_gunicorn,
$gunicorn_package_name = $python::params::gunicorn_package_name,
$provider = $python::params::provider,
$valid_versions = $python::params::valid_versions,
$python_pips = { },
$python_virtualenvs = { },
$python_pyvenvs = { },
$python_requirements = { },
$python_dotfiles = { },
$use_epel = $python::params::use_epel,
$rhscl_use_public_repository = $python::params::rhscl_use_public_repository,
) inherits python::params{
if $provider != undef and $provider != '' {
validate_re($provider, ['^(pip|scl|rhscl)$'],
"Only 'pip', 'rhscl' and 'scl' are valid providers besides the system default. Detected provider is <${provider}>.")
}
$exec_prefix = $provider ? {
'scl' => "/usr/bin/scl enable ${version} -- ",
'rhscl' => "/usr/bin/scl enable ${version} -- ",
default => '',
}
validate_re($ensure, ['^(absent|present|latest)$'])
validate_re($version, concat(['system', 'pypy'], $valid_versions))
if $pip == false or $pip == true {
warning('Use of boolean values for the $pip parameter is deprecated')
} else {
validate_re($pip, ['^(absent|present|latest)$'])
}
if $virtualenv == false or $virtualenv == true {
warning('Use of boolean values for the $virtualenv parameter is deprecated')
} else {
validate_re($virtualenv, ['^(absent|present|latest)$'])
}
if $virtualenv == false or $virtualenv == true {
warning('Use of boolean values for the $virtualenv parameter is deprecated')
} else {
validate_re($virtualenv, ['^(absent|present|latest)$'])
}
if $gunicorn == false or $gunicorn == true {
warning('Use of boolean values for the $gunicorn parameter is deprecated')
} else {
validate_re($gunicorn, ['^(absent|present|latest)$'])
}
validate_hash($python_dotfiles)
validate_bool($manage_gunicorn)
validate_bool($use_epel)
# Module compatibility check
$compatible = [ 'Debian', 'RedHat', 'Suse', 'Gentoo' ]
if ! ($::osfamily in $compatible) {
fail("Module is not compatible with ${::operatingsystem}")
}
# Anchor pattern to contain dependencies
anchor { 'python::begin': }
-> class { 'python::install': }
-> class { 'python::config': }
-> anchor { 'python::end': }
# Allow hiera configuration of python resources
create_resources('python::pip', $python_pips)
create_resources('python::pyvenv', $python_pyvenvs)
create_resources('python::virtualenv', $python_virtualenvs)
create_resources('python::requirements', $python_requirements)
create_resources('python::dotfile', $python_dotfiles)
}

View File

@@ -0,0 +1,255 @@
# == Class: python::install
#
# Installs core python packages,
#
# === Examples
#
# include python::install
#
# === Authors
#
# Sergey Stankevich
# Ashley Penney
# Fotis Gimian
# Garrett Honeycutt <code@garretthoneycutt.com>
#
class python::install {
$python = $::python::version ? {
'system' => 'python',
'pypy' => 'pypy',
default => "${python::version}", # lint:ignore:only_variable_string
}
$pythondev = $::osfamily ? {
'RedHat' => "${python}-devel",
'Debian' => "${python}-dev",
'Suse' => "${python}-devel",
'Gentoo' => undef,
}
$dev_ensure = $python::dev ? {
true => 'present',
false => 'absent',
default => $python::dev,
}
$pip_ensure = $python::pip ? {
true => 'present',
false => 'absent',
default => $python::pip,
}
$venv_ensure = $python::virtualenv ? {
true => 'present',
false => 'absent',
default => $python::virtualenv,
}
package { 'python':
ensure => $python::ensure,
name => $python,
}
package { 'virtualenv':
ensure => $venv_ensure,
require => Package['python'],
}
case $python::provider {
pip: {
package { 'pip':
ensure => $pip_ensure,
require => Package['python'],
}
if $pythondev {
package { 'python-dev':
ensure => $dev_ensure,
name => $pythondev,
}
}
# Install pip without pip, see https://pip.pypa.io/en/stable/installing/.
exec { 'bootstrap pip':
command => '/usr/bin/curl https://bootstrap.pypa.io/get-pip.py | python',
unless => 'which pip',
path => [ '/bin', '/usr/bin', '/usr/local/bin' ],
require => Package['python'],
}
# Puppet is opinionated about the pip command name
file { 'pip-python':
ensure => link,
path => '/usr/bin/pip-python',
target => '/usr/bin/pip',
require => Exec['bootstrap pip'],
}
Exec['bootstrap pip'] -> File['pip-python'] -> Package <| provider == pip |>
Package <| title == 'pip' |> {
name => 'pip',
provider => 'pip',
}
Package <| title == 'virtualenv' |> {
name => 'virtualenv',
provider => 'pip',
}
}
scl: {
# SCL is only valid in the RedHat family. If RHEL, package must be
# enabled using the subscription manager outside of puppet. If CentOS,
# the centos-release-SCL will install the repository.
$install_scl_repo_package = $::operatingsystem ? {
'CentOS' => 'present',
default => 'absent',
}
package { 'centos-release-scl':
ensure => $install_scl_repo_package,
before => Package['scl-utils'],
}
package { 'scl-utils':
ensure => 'latest',
before => Package['python'],
}
# This gets installed as a dependency anyway
# package { "${python::version}-python-virtualenv":
# ensure => $venv_ensure,
# require => Package['scl-utils'],
# }
package { "${python}-scldevel":
ensure => $dev_ensure,
require => Package['scl-utils'],
}
if $pip_ensure != 'absent' {
exec { 'python-scl-pip-install':
command => "${python::exec_prefix}easy_install pip",
path => ['/usr/bin', '/bin'],
creates => "/opt/rh/${python::version}/root/usr/bin/pip",
require => Package['scl-utils'],
}
}
}
rhscl: {
# rhscl is RedHat SCLs from softwarecollections.org
if $::python::rhscl_use_public_repository {
$scl_package = "rhscl-${::python::version}-epel-${::operatingsystemmajrelease}-${::architecture}"
package { $scl_package:
source => "https://www.softwarecollections.org/en/scls/rhscl/${::python::version}/epel-${::operatingsystemmajrelease}-${::architecture}/download/${scl_package}.noarch.rpm",
provider => 'rpm',
tag => 'python-scl-repo',
}
}
Package <| title == 'python' |> {
tag => 'python-scl-package',
}
Package <| title == 'virtualenv' |> {
name => "${python}-python-virtualenv",
}
package { "${python}-scldevel":
ensure => $dev_ensure,
tag => 'python-scl-package',
}
package { "${python}-python-pip":
ensure => $pip_ensure,
tag => 'python-pip-package',
}
if $::python::rhscl_use_public_repository {
Package <| tag == 'python-scl-repo' |>
-> Package <| tag == 'python-scl-package' |>
}
Package <| tag == 'python-scl-package' |>
-> Package <| tag == 'python-pip-package' |>
}
default: {
package { 'pip':
ensure => $pip_ensure,
require => Package['python'],
}
if $pythondev {
package { 'python-dev':
ensure => $dev_ensure,
name => $pythondev,
alias => $pythondev,
}
}
if $::osfamily == 'RedHat' {
if $pip_ensure != 'absent' {
if $python::use_epel == true {
include 'epel'
Class['epel'] -> Package['pip']
}
}
if ($venv_ensure != 'absent') and ($::operatingsystemrelease =~ /^6/) {
if $python::use_epel == true {
include 'epel'
Class['epel'] -> Package['virtualenv']
}
}
$virtualenv_package = "${python}-virtualenv"
} else {
if $::lsbdistcodename == 'jessie' {
$virtualenv_package = 'virtualenv'
} elsif $::lsbdistcodename == 'stretch' {
$virtualenv_package = 'virtualenv'
} elsif $::lsbdistcodename == 'xenial' {
$virtualenv_package = 'virtualenv'
} elsif $::osfamily == 'Gentoo' {
$virtualenv_package = 'virtualenv'
} else {
$virtualenv_package = 'python-virtualenv'
}
}
if "${::python::version}" =~ /^3/ { #lint:ignore:only_variable_string
$pip_category = undef
$pip_package = 'python3-pip'
} elsif ($::osfamily == 'RedHat') and (versioncmp($::operatingsystemmajrelease, '7') >= 0) {
$pip_category = undef
$pip_package = 'python2-pip'
} elsif $::osfamily == 'Gentoo' {
$pip_category = 'dev-python'
$pip_package = 'pip'
} else {
$pip_category = undef
$pip_package = 'python-pip'
}
Package <| title == 'pip' |> {
name => $pip_package,
category => $pip_category,
}
Package <| title == 'virtualenv' |> {
name => $virtualenv_package,
}
}
}
if $python::manage_gunicorn {
$gunicorn_ensure = $python::gunicorn ? {
true => 'present',
false => 'absent',
default => $python::gunicorn,
}
package { 'gunicorn':
ensure => $gunicorn_ensure,
name => $python::gunicorn_package_name,
}
}
}

View File

@@ -0,0 +1,38 @@
# == Class: python::params
#
# The python Module default configuration settings.
#
class python::params {
$ensure = 'present'
$version = 'system'
$pip = 'present'
$dev = 'absent'
$virtualenv = 'absent'
$gunicorn = 'absent'
$manage_gunicorn = true
$provider = undef
$valid_versions = $::osfamily ? {
'RedHat' => ['3','27','33'],
'Debian' => ['3', '3.3', '2.7'],
'Suse' => [],
'Gentoo' => ['2.7', '3.3', '3.4', '3.5']
}
if $::osfamily == 'RedHat' {
if $::operatingsystem != 'Fedora' {
$use_epel = true
} else {
$use_epel = false
}
} else {
$use_epel = false
}
$gunicorn_package_name = $::osfamily ? {
'RedHat' => 'python-gunicorn',
default => 'gunicorn',
}
$rhscl_use_public_repository = true
}

View File

@@ -0,0 +1,275 @@
# == Define: python::pip
#
# Installs and manages packages from pip.
#
# === Parameters
#
# [*name]
# must be unique
#
# [*pkgname]
# name of the package. If pkgname is not specified, use name (title) instead.
#
# [*ensure*]
# present|absent. Default: present
#
# [*virtualenv*]
# virtualenv to run pip in.
#
# [*url*]
# URL to install from. Default: none
#
# [*owner*]
# The owner of the virtualenv being manipulated. Default: root
#
# [*group*]
# The group of the virtualenv being manipulated. Default: root
#
# [*index*]
# Base URL of Python package index. Default: none (http://pypi.python.org/simple/)
#
# [*proxy*]
# Proxy server to use for outbound connections. Default: none
#
# [*editable*]
# Boolean. If true the package is installed as an editable resource.
#
# [*environment*]
# Additional environment variables required to install the packages. Default: none
#
# [*timeout*]
# The maximum time in seconds the "pip install" command should take. Default: 1800
#
# [*install_args*]
# String. Any additional installation arguments that will be supplied
# when running pip install.
#
# [*uninstall_args*]
# String. Any additional arguments that will be supplied when running
# pip uninstall.
#
# [*log_dir*]
# String. Log directory.
#
# === Examples
#
# python::pip { 'flask':
# virtualenv => '/var/www/project1',
# proxy => 'http://proxy.domain.com:3128',
# index => 'http://www.example.com/simple/',
# }
#
# === Authors
#
# Sergey Stankevich
# Fotis Gimian
#
define python::pip (
$pkgname = $name,
$ensure = present,
$virtualenv = 'system',
$url = false,
$owner = 'root',
$group = 'root',
$index = false,
$proxy = false,
$egg = false,
$editable = false,
$environment = [],
$install_args = '',
$uninstall_args = '',
$timeout = 1800,
$log_dir = '/tmp',
$path = ['/usr/local/bin','/usr/bin','/bin', '/usr/sbin'],
) {
$python_provider = getparam(Class['python'], 'provider')
$python_version = getparam(Class['python'], 'version')
# Get SCL exec prefix
# NB: this will not work if you are running puppet from scl enabled shell
$exec_prefix = $python_provider ? {
'scl' => "scl enable ${python_version} -- ",
'rhscl' => "scl enable ${python_version} -- ",
default => '',
}
# Parameter validation
if ! $virtualenv {
fail('python::pip: virtualenv parameter must not be empty')
}
if $virtualenv == 'system' and $owner != 'root' {
fail('python::pip: root user must be used when virtualenv is system')
}
$cwd = $virtualenv ? {
'system' => '/',
default => $virtualenv,
}
validate_absolute_path($cwd)
$log = $virtualenv ? {
'system' => $log_dir,
default => $virtualenv,
}
$pip_env = $virtualenv ? {
'system' => "${exec_prefix}pip",
default => "${exec_prefix}${virtualenv}/bin/pip",
}
$pypi_index = $index ? {
false => '',
default => "--index-url=${index}",
}
$pypi_search_index = $index ? {
false => '',
default => "--index=${index}",
}
$proxy_flag = $proxy ? {
false => '',
default => "--proxy=${proxy}",
}
if $editable == true {
$install_editable = ' -e '
}
else {
$install_editable = ''
}
#TODO: Do more robust argument checking, but below is a start
if ($ensure == absent) and ($install_args != '') {
fail('python::pip cannot provide install_args with ensure => absent')
}
if ($ensure == present) and ($uninstall_args != '') {
fail('python::pip cannot provide uninstall_args with ensure => present')
}
# Check if searching by explicit version.
if $ensure =~ /^((19|20)[0-9][0-9]-(0[1-9]|1[1-2])-([0-2][1-9]|3[0-1])|[0-9]+\.\w+\+?\w*(\.\w+)*)$/ {
$grep_regex = "^${pkgname}==${ensure}\$"
} else {
$grep_regex = $pkgname ? {
/==/ => "^${pkgname}\$",
default => "^${pkgname}==",
}
}
$egg_name = $egg ? {
false => $pkgname,
default => $egg
}
$source = $url ? {
false => $pkgname,
/^(\/|[a-zA-Z]\:)/ => $url,
/^(git\+|hg\+|bzr\+|svn\+)(http|https|ssh|svn|sftp|ftp|lp)(:\/\/).+$/ => $url,
default => "${url}#egg=${egg_name}",
}
# We need to jump through hoops to make sure we issue the correct pip command
# depending on wheel support and versions.
#
# Pip does not support wheels prior to version 1.4.0
# Pip wheels require setuptools/distribute > 0.8
# Python 2.6 and older does not support setuptools/distribute > 0.8
# Pip >= 1.5 tries to use wheels by default, even if wheel package is not
# installed, in this case the --no-use-wheel flag needs to be passed
# Versions prior to 1.5 don't support the --no-use-wheel flag
#
# 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 and
# installed
# Explicit version out of VCS when PIP supported URL is provided
if $source =~ /^(git\+|hg\+|bzr\+|svn\+)(http|https|ssh|svn|sftp|ftp|lp)(:\/\/).+$/ {
if $ensure != present and $ensure != 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 ${log}/pip.log install ${install_args} \$wheel_support_flag ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source}@${ensure}#egg=${egg_name} || ${pip_env} --log ${log}/pip.log install ${install_args} ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source}@${ensure}#egg=${egg_name} ;}",
unless => "${pip_env} freeze | grep -i -e ${grep_regex}",
user => $owner,
group => $group,
cwd => $cwd,
environment => $environment,
timeout => $timeout,
path => $path,
}
} else {
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 ${log}/pip.log install ${install_args} \$wheel_support_flag ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source} || ${pip_env} --log ${log}/pip.log install ${install_args} ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source} ;}",
unless => "${pip_env} freeze | grep -i -e ${grep_regex}",
user => $owner,
group => $group,
cwd => $cwd,
environment => $environment,
timeout => $timeout,
path => $path,
}
}
} else {
case $ensure {
/^((19|20)[0-9][0-9]-(0[1-9]|1[1-2])-([0-2][1-9]|3[0-1])|[0-9]+\.\w+\+?\w*(\.\w+)*)$/: {
# Version formats as per http://guide.python-distribute.org/specification.html#standard-versioning-schemes
# Explicit version.
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 ${log}/pip.log install ${install_args} \$wheel_support_flag ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source}==${ensure} || ${pip_env} --log ${log}/pip.log install ${install_args} ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source}==${ensure} ;}",
unless => "${pip_env} freeze | grep -i -e ${grep_regex} || ${pip_env} list | sed -e 's/[ ]\\+/==/' -e 's/[()]//g' | grep -i -e ${grep_regex}",
user => $owner,
group => $group,
cwd => $cwd,
environment => $environment,
timeout => $timeout,
path => $path,
}
}
#
present: {
# Whatever version is available.
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 ${log}/pip.log install \$wheel_support_flag ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source} || ${pip_env} --log ${log}/pip.log install ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source} ;}",
unless => "${pip_env} freeze | grep -i -e ${grep_regex} || ${pip_env} list | sed -e 's/[ ]\\+/==/' -e 's/[()]//g' | grep -i -e ${grep_regex}",
user => $owner,
group => $group,
cwd => $cwd,
environment => $environment,
timeout => $timeout,
path => $path,
}
}
latest: {
# Latest version.
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 ${log}/pip.log install --upgrade \$wheel_support_flag ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source} || ${pip_env} --log ${log}/pip.log install --upgrade ${pypi_index} ${proxy_flag} ${install_args} ${install_editable} ${source} ;}",
unless => "${pip_env} search ${pypi_search_index} ${proxy_flag} ${source} | grep -i INSTALLED.*latest",
user => $owner,
group => $group,
cwd => $cwd,
environment => $environment,
timeout => $timeout,
path => $path,
}
}
default: {
# Anti-action, uninstall.
exec { "pip_uninstall_${name}":
command => "echo y | ${pip_env} uninstall ${uninstall_args} ${proxy_flag} ${name}",
onlyif => "${pip_env} freeze | grep -i -e ${grep_regex}",
user => $owner,
group => $group,
cwd => $cwd,
environment => $environment,
timeout => $timeout,
path => $path,
}
}
}
}
}

View File

@@ -0,0 +1,104 @@
# == Define: python::pyvenv
#
# Create a Python3 virtualenv using pyvenv.
#
# === Parameters
#
# [*ensure*]
# present|absent. Default: present
#
# [*version*]
# Python version to use. Default: system default
#
# [*systempkgs*]
# Copy system site-packages into virtualenv. Default: don't
#
# [*venv_dir*]
# Directory to install virtualenv to. Default: $name
#
# [*owner*]
# The owner of the virtualenv being manipulated. Default: root
#
# [*group*]
# The group relating to the virtualenv being manipulated. Default: root
#
# [*mode*]
# Optionally specify directory mode. Default: 0755
#
# [*path*]
# Specifies the PATH variable. Default: [ '/bin', '/usr/bin', '/usr/sbin' ]
# [*environment*]
# Optionally specify environment variables for pyvenv
#
# === Examples
#
# python::venv { '/var/www/project1':
# ensure => present,
# version => 'system',
# systempkgs => true,
# }
#
# === Authors
#
# Sergey Stankevich
# Ashley Penney
# Marc Fournier
# Fotis Gimian
# Seth Cleveland
#
define python::pyvenv (
$ensure = present,
$version = 'system',
$systempkgs = false,
$venv_dir = $name,
$owner = 'root',
$group = 'root',
$mode = '0755',
$path = [ '/bin', '/usr/bin', '/usr/sbin', '/usr/local/bin' ],
$environment = [],
) {
include ::python
if $ensure == 'present' {
$virtualenv_cmd = $version ? {
'system' => "${python::exec_prefix}pyvenv",
default => "${python::exec_prefix}pyvenv-${version}",
}
if ( $systempkgs == true ) {
$system_pkgs_flag = '--system-site-packages'
} else {
$system_pkgs_flag = ''
}
file { $venv_dir:
ensure => directory,
owner => $owner,
group => $group,
mode => $mode
}
exec { "python_virtualenv_${venv_dir}":
command => "${virtualenv_cmd} --clear ${system_pkgs_flag} ${venv_dir}",
user => $owner,
creates => "${venv_dir}/bin/activate",
path => $path,
cwd => '/tmp',
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
require => File[$venv_dir],
}
} elsif $ensure == 'absent' {
file { $venv_dir:
ensure => absent,
force => true,
recurse => true,
purge => true,
}
} else {
fail( "Illegal ensure value: ${ensure}. Expected (present or absent)")
}
}

View File

@@ -0,0 +1,141 @@
# == Define: python::requirements
#
# Installs and manages Python packages from requirements file.
#
# === Parameters
#
# [*requirements*]
# Path to the requirements file. Defaults to the resource name
#
# [*virtualenv*]
# virtualenv to run pip in. Default: system-wide
#
# [*owner*]
# The owner of the virtualenv being manipulated. Default: root
#
# [*group*]
# The group relating to the virtualenv being manipulated. Default: root
#
# [*proxy*]
# Proxy server to use for outbound connections. Default: none
#
# [*src*]
# Pip --src parameter; if the requirements file contains --editable resources,
# this parameter specifies where they will be installed. See the pip
# documentation for more. Default: none (i.e. use the pip default).
#
# [*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)
#
# [*cwd*]
# The directory from which to run the "pip install" command. Default: undef
#
# [*extra_pip_args*]
# Extra arguments to pass to pip after the requirements file
#
# [*manage_requirements*]
# Create the requirements file if it doesn't exist. Default: true
#
# [*fix_requirements_owner*]
# Change owner and group of requirements file. Default: true
#
# [*log_dir*]
# String. Log directory.
#
# [*timeout*]
# The maximum time in seconds the "pip install" command should take. Default: 1800
#
# === Examples
#
# python::requirements { '/var/www/project1/requirements.txt':
# virtualenv => '/var/www/project1',
# proxy => 'http://proxy.domain.com:3128',
# }
#
# === Authors
#
# Sergey Stankevich
# Ashley Penney
# Fotis Gimian
#
define python::requirements (
$requirements = $name,
$virtualenv = 'system',
$owner = 'root',
$group = 'root',
$proxy = false,
$src = false,
$environment = [],
$forceupdate = false,
$cwd = undef,
$extra_pip_args = '',
$manage_requirements = true,
$fix_requirements_owner = true,
$log_dir = '/tmp',
$timeout = 1800,
) {
include ::python
if $virtualenv == 'system' and ($owner != 'root' or $group != 'root') {
fail('python::pip: root user must be used when virtualenv is system')
}
if $fix_requirements_owner {
$owner_real = $owner
$group_real = $group
} else {
$owner_real = undef
$group_real = undef
}
$log = $virtualenv ? {
'system' => $log_dir,
default => $virtualenv,
}
$pip_env = $virtualenv ? {
'system' => "${::python::exec_prefix} pip",
default => "${::python::exec_prefix} ${virtualenv}/bin/pip",
}
$proxy_flag = $proxy ? {
false => '',
default => "--proxy=${proxy}",
}
$src_flag = $src ? {
false => '',
default => "--src=${src}",
}
# This will ensure multiple python::virtualenv definitions can share the
# the same requirements file.
if !defined(File[$requirements]) and $manage_requirements == true {
file { $requirements:
ensure => present,
mode => '0644',
owner => $owner_real,
group => $group_real,
audit => content,
replace => false,
content => '# Puppet will install and/or update pip packages listed here',
}
}
exec { "python_requirements${name}":
provider => shell,
command => "${pip_env} --log ${log}/pip.log install ${proxy_flag} ${src_flag} -r ${requirements} ${extra_pip_args}",
refreshonly => !$forceupdate,
timeout => $timeout,
cwd => $cwd,
user => $owner,
subscribe => File[$requirements],
environment => $environment,
}
}

View File

@@ -0,0 +1,208 @@
# == 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
#
# [*systempkgs*]
# Copy system site-packages into virtualenv. Default: don't
# If virtualenv version < 1.7 this flag has no effect since
# [*venv_dir*]
# Directory to install virtualenv to. Default: $name
#
# [*distribute*]
# Include distribute in the virtualenv. Default: true
#
# [*index*]
# Base URL of Python package index. Default: none (http://pypi.python.org/simple/)
#
# [*owner*]
# The owner of the virtualenv being manipulated. Default: root
#
# [*group*]
# The group relating to the virtualenv being manipulated. Default: root
#
# [*mode*]
# Optionally specify directory mode. Default: 0755
#
# [*proxy*]
# Proxy server to use for outbound connections. Default: none
#
# [*environment*]
# Additional environment variables required to install the packages. Default: none
#
# [*path*]
# Specifies the PATH variable. Default: [ '/bin', '/usr/bin', '/usr/sbin' ]
#
# [*cwd*]
# The directory from which to run the "pip install" command. Default: undef
#
# [*timeout*]
# The maximum time in seconds the "pip install" command should take. Default: 1800
#
# [*pip_args*]
# Arguments to pass to pip during initialization. Default: blank
#
# [*extra_pip_args*]
# Extra arguments to pass to pip after requirements file. Default: blank
#
# === Examples
#
# python::virtualenv { '/var/www/project1':
# ensure => present,
# 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
# Shiva Poudel
#
define python::virtualenv (
$ensure = present,
$version = 'system',
$requirements = false,
$systempkgs = false,
$venv_dir = $name,
$distribute = true,
$index = false,
$owner = 'root',
$group = 'root',
$mode = '0755',
$proxy = false,
$environment = [],
$path = [ '/bin', '/usr/bin', '/usr/sbin', '/usr/local/bin' ],
$cwd = undef,
$timeout = 1800,
$pip_args = '',
$extra_pip_args = '',
$virtualenv = undef
) {
include ::python
if $ensure == 'present' {
$python = $version ? {
'system' => 'python',
'pypy' => 'pypy',
default => "python${version}",
}
if $virtualenv == undef {
$used_virtualenv = 'virtualenv'
} else {
$used_virtualenv = $virtualenv
}
$proxy_flag = $proxy ? {
false => '',
default => "--proxy=${proxy}",
}
$proxy_command = $proxy ? {
false => '',
default => "&& export http_proxy=${proxy}",
}
# 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
$_virtualenv_version = getvar('virtualenv_version') ? {
/.*/ => getvar('virtualenv_version'),
default => '',
}
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 = $systempkgs ? {
true => '--system-site-packages',
false => '--no-site-packages',
default => fail('Invalid value for systempkgs. Boolean value is expected')
}
}
$distribute_pkg = $distribute ? {
true => 'distribute',
default => 'setuptools',
}
$pypi_index = $index ? {
false => '',
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
file { $venv_dir:
ensure => directory,
owner => $owner,
group => $group,
mode => $mode
}
$virtualenv_cmd = "${python::exec_prefix}${used_virtualenv}"
$pip_cmd = "${python::exec_prefix}${venv_dir}/bin/pip"
$pip_flags = "${pypi_index} ${proxy_flag} ${pip_args}"
exec { "python_virtualenv_${venv_dir}":
command => "true ${proxy_command} && ${virtualenv_cmd} ${system_pkgs_flag} -p ${python} ${venv_dir} && ${pip_cmd} --log ${venv_dir}/pip.log install ${pip_flags} --upgrade pip && ${pip_cmd} install ${pip_flags} --upgrade ${distribute_pkg}",
user => $owner,
creates => "${venv_dir}/bin/activate",
path => $path,
cwd => '/tmp',
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
require => File[$venv_dir],
}
if $requirements {
exec { "python_requirements_initial_install_${requirements}_${venv_dir}":
command => "${pip_cmd} --log ${venv_dir}/pip.log install ${pypi_index} ${proxy_flag} --no-binary :all: -r ${requirements} ${extra_pip_args}",
refreshonly => true,
timeout => $timeout,
user => $owner,
subscribe => Exec["python_virtualenv_${venv_dir}"],
environment => $environment,
cwd => $cwd
}
python::requirements { "${requirements}_${venv_dir}":
requirements => $requirements,
virtualenv => $venv_dir,
proxy => $proxy,
owner => $owner,
group => $group,
cwd => $cwd,
require => Exec["python_virtualenv_${venv_dir}"],
extra_pip_args => $extra_pip_args,
}
}
} elsif $ensure == 'absent' {
file { $venv_dir:
ensure => absent,
force => true,
recurse => true,
purge => true,
}
}
}

View File

@@ -0,0 +1,71 @@
{
"name": "stankevich-python",
"version": "1.19.0",
"author": "stankevich",
"summary": "Python Module",
"license": "Apache-2.0",
"source": "git://github.com/stankevich/puppet-python.git",
"project_page": "https://github.com/stankevich/puppet-python",
"issues_url": "https://github.com/stankevich/puppet-python/issues",
"dependencies": [
{
"name": "puppetlabs/stdlib",
"version_requirement": ">= 4.6.0 < 6.0.0"
},
{
"name": "stahnma/epel",
"version_requirement": ">= 1.2.2 < 2.0.0"
}
],
"data_provider": null,
"description": "Puppet module for Python",
"tags": [
"python",
"pip",
"virtualenv",
"gunicorn"
],
"operatingsystem_support": [
{
"operatingsystem": "CentOS",
"operatingsystemrelease": [
"5",
"6",
"7"
]
},
{
"operatingsystem": "Debian",
"operatingsystemrelease": [
"6",
"7",
"8",
"9"
]
},
{
"operatingsystem": "Gentoo"
},
{
"operatingsystem": "Ubuntu",
"operatingsystemrelease": [
"10.04",
"12.04",
"14.04",
"16.04"
]
},
{
"operatingsystem": "SLES",
"operatingsystemrelease": [
"11.3"
]
}
],
"requirements": [
{
"name": "puppet",
"version_requirement": ">=3.0.0 < 5.0.0"
}
]
}

View File

@@ -0,0 +1,7 @@
class { 'python':
version => 'system',
pip => 'present',
dev => 'absent',
virtualenv => 'absent',
gunicorn => 'absent',
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<utility xmlns="http://www.github/cliffe/SecGen/utility"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
<name>Python 2 programming language</name>
<author>Thomas Shaw</author>
<author>stankevich</author>
<module_license>Apache v2</module_license>
<description>An installation of Python</description>
<type>language</type>
<type>python</type>
<platform>linux</platform>
<!--optional details-->
<reference>https://forge.puppet.com/stankevich/python</reference>
<software_name>ruby</software_name>
<software_license>Apache v2</software_license>
<requires>
<type>update</type>
</requires>
</utility>

View File

@@ -0,0 +1,17 @@
require 'spec_helper_acceptance'
describe 'python class' do
context 'default parameters' do
# Using puppet_apply as a helper
it 'should work with no errors' do
pp = <<-EOS
class { 'python': }
EOS
# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
end
end

View File

@@ -0,0 +1,43 @@
require 'spec_helper_acceptance'
describe 'python class' do
context 'facts' do
install_python = <<-EOS
class { 'python' :
version => 'system',
pip => 'present',
virtualenv => 'present',
}
EOS
fact_notices = <<-EOS
notify{"pip_version: ${::pip_version}":}
notify{"system_python_version: ${::system_python_version}":}
notify{"python_version: ${::python_version}":}
notify{"virtualenv_version: ${::virtualenv_version}":}
EOS
it 'should output python facts when not installed' do
apply_manifest(fact_notices, :catch_failures => true) do |r|
expect(r.stdout).to match(/python_version: \S+/)
expect(r.stdout).to match(/pip_version: \S+/)
expect(r.stdout).to match(/virtualenv_version: \S+/)
expect(r.stdout).to match(/system_python_version: \S+/)
end
end
it 'sets up python' do
apply_manifest(install_python, :catch_failures => true)
end
it 'should output python facts when installed' do
apply_manifest(fact_notices, :catch_failures => true) do |r|
expect(r.stdout).to match(/python_version: \S+/)
expect(r.stdout).to match(/pip_version: \S+/)
expect(r.stdout).to match(/virtualenv_version: \S+/)
expect(r.stdout).to match(/system_python_version: \S+/)
end
end
end
end

View File

@@ -0,0 +1,10 @@
HOSTS:
centos-59-x64:
roles:
- master
platform: el-5-x86_64
box : centos-59-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@@ -0,0 +1,12 @@
HOSTS:
centos-64-x64:
roles:
- master
- database
- dashboard
platform: el-6-x86_64
box : centos-64-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: pe

View File

@@ -0,0 +1,10 @@
HOSTS:
centos-65-x64:
roles:
- master
platform: el-6-x86_64
box : centos-65-x64-vbox436-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@@ -0,0 +1,10 @@
HOSTS:
debian-70rc1-x64:
roles:
- master
platform: debian-70rc1-x64
box : debian-70rc1-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@@ -0,0 +1,11 @@
HOSTS:
debian-73-x64:
roles:
- master
platform: debian-7-amd64
box : debian-73-x64-virtualbox-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box
hypervisor : vagrant
CONFIG:
log_level: debug
type: git

View File

@@ -0,0 +1,11 @@
HOSTS:
ubuntu-server-12042-x64:
roles:
- master
platform: ubuntu-server-12.04-amd64
box : ubuntu-server-12042-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: foss
vagrant_ssh_port_random: true

View File

@@ -0,0 +1,10 @@
HOSTS:
ubuntu-server-10044-x64:
roles:
- master
platform: ubuntu-10.04-amd64
box : ubuntu-server-10044-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@@ -0,0 +1,10 @@
HOSTS:
ubuntu-server-12042-x64:
roles:
- master
platform: ubuntu-12.04-amd64
box : ubuntu-server-12042-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@@ -0,0 +1,11 @@
HOSTS:
ubuntu-server-1404-x64:
roles:
- master
platform: ubuntu-14.04-amd64
box : puppetlabs/ubuntu-14.04-64-nocm
box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
hypervisor : vagrant
CONFIG:
log_level : debug
type: git

View File

@@ -0,0 +1,34 @@
require 'spec_helper_acceptance'
describe 'python class' do
context 'default parameters' do
# Using puppet_apply as a helper
it 'should work with no errors' do
pp = <<-EOS
class { 'python' :
version => 'system',
pip => 'present',
virtualenv => 'present',
}
->
python::virtualenv { 'venv' :
ensure => 'present',
systempkgs => false,
venv_dir => '/opt/venv',
owner => 'root',
group => 'root',
}
->
python::pip { 'rpyc' :
ensure => '3.2.3',
virtualenv => '/opt/venv',
}
EOS
# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
end
end

View File

@@ -0,0 +1,423 @@
require 'spec_helper'
describe 'python', :type => :class do
context "on Debian OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:lsbdistcodename => 'squeeze',
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemrelease => '6',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
:concat_basedir => '/dne',
}
end
it { is_expected.to contain_class("python::install") }
# Base debian packages.
it { is_expected.to contain_package("python") }
it { is_expected.to contain_package("python-dev") }
it { is_expected.to contain_package("pip") }
# Basic python packages (from pip)
it { is_expected.to contain_package("virtualenv")}
describe "with python::dev" do
context "true" do
let (:params) {{ :dev => 'present' }}
it { is_expected.to contain_package("python-dev").with_ensure('present') }
end
context "empty/default" do
it { is_expected.to contain_package("python-dev").with_ensure('absent') }
end
end
describe "with manage_gunicorn" do
context "true" do
let (:params) {{ :manage_gunicorn => true }}
it { is_expected.to contain_package("gunicorn") }
end
context "empty args" do
#let (:params) {{ :manage_gunicorn => '' }}
it { is_expected.to contain_package("gunicorn") }
end
context "false" do
let (:params) {{ :manage_gunicorn => false }}
it {is_expected.not_to contain_package("gunicorn")}
end
end
describe "with python::provider" do
context "pip" do
let (:params) {{ :provider => 'pip' }}
it { is_expected.to contain_package("virtualenv").with(
'provider' => 'pip'
)}
it { is_expected.to contain_package("pip").with(
'provider' => 'pip'
)}
end
# python::provider
context "default" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv")}
it { is_expected.to contain_package("pip")}
describe "with python::virtualenv" do
context "true" do
let (:params) {{ :provider => '', :virtualenv => true }}
it { is_expected.to contain_package("virtualenv").with_ensure('present') }
end
end
describe "without python::virtualenv" do
context "default/empty" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv").with_ensure('absent') }
end
end
end
end
describe "with python::dev" do
context "true" do
let (:params) {{ :dev => 'present' }}
it { is_expected.to contain_package("python-dev").with_ensure('present') }
end
context "default/empty" do
it { is_expected.to contain_package("python-dev").with_ensure('absent') }
end
end
describe "EPEL does not exist for Debian" do
context "default/empty" do
it { should_not contain_class('epel') }
end
end
end
context "on a Fedora 22 OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:osfamily => 'RedHat',
:operatingsystem => 'Fedora',
:operatingsystemrelease => '22',
:concat_basedir => '/dne',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
}
end
describe "EPEL does not exist for Fedora" do
context "default/empty" do
it { should_not contain_class('epel') }
end
end
end
context "on a Redhat 5 OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:osfamily => 'RedHat',
:operatingsystem => 'RedHat',
:operatingsystemrelease => '5',
:concat_basedir => '/dne',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
}
end
it { is_expected.to contain_class("python::install") }
# Base debian packages.
it { is_expected.to contain_package("python") }
it { is_expected.to contain_package("python-dev").with_name("python-devel") }
it { is_expected.to contain_package("python-dev").with_alias("python-devel") }
it { is_expected.to contain_package("pip") }
it { is_expected.to contain_package("pip").with_name('python-pip') }
# Basic python packages (from pip)
it { is_expected.to contain_package("virtualenv")}
describe "EPEL may be needed on EL" do
context "default/empty" do
it { should contain_class('epel') }
end
end
describe "with python::dev" do
context "true" do
let (:params) {{ :dev => 'present' }}
it { is_expected.to contain_package("python-dev").with_ensure('present') }
end
context "empty/default" do
it { is_expected.to contain_package("python-dev").with_ensure('absent') }
end
end
describe "with manage_gunicorn" do
context "true" do
let (:params) {{ :manage_gunicorn => true }}
it { is_expected.to contain_package("gunicorn") }
end
context "empty args" do
#let (:params) {{ :manage_gunicorn => '' }}
it { is_expected.to contain_package("gunicorn") }
end
context "false" do
let (:params) {{ :manage_gunicorn => false }}
it {is_expected.not_to contain_package("gunicorn")}
end
end
describe "with python::provider" do
context "pip" do
let (:params) {{ :provider => 'pip' }}
it { is_expected.to contain_package("virtualenv").with(
'provider' => 'pip'
)}
it { is_expected.to contain_package("pip").with(
'provider' => 'pip'
)}
end
# python::provider
context "default" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv")}
it { is_expected.to contain_package("pip")}
describe "with python::virtualenv" do
context "true" do
let (:params) {{ :provider => '', :virtualenv => 'present' }}
it { is_expected.to contain_package("virtualenv").with_ensure('present') }
end
end
describe "with python::virtualenv" do
context "default/empty" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv").with_ensure('absent') }
end
end
end
end
describe "with python::dev" do
context "true" do
let (:params) {{ :dev => 'present' }}
it { is_expected.to contain_package("python-dev").with_ensure('present') }
end
context "default/empty" do
it { is_expected.to contain_package("python-dev").with_ensure('absent') }
end
end
end
context "on a Redhat 6 OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:osfamily => 'RedHat',
:operatingsystem => 'RedHat',
:operatingsystemmajrelease => '6',
:concat_basedir => '/dne',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
}
end
it { is_expected.to contain_class("python::install") }
it { is_expected.to contain_package("pip").with_name('python-pip') }
end
context "on a Redhat 7 OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:osfamily => 'RedHat',
:operatingsystem => 'RedHat',
:operatingsystemmajrelease => '7',
:concat_basedir => '/dne',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
}
end
it { is_expected.to contain_class("python::install") }
it { is_expected.to contain_package("pip").with_name('python2-pip') }
end
context "on a SLES 11 SP3" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:lsbdistcodename => nil,
:osfamily => 'Suse',
:operatingsystem => 'SLES',
:operatingsystemrelease => '11.3',
:concat_basedir => '/dne',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
}
end
it { is_expected.to contain_class("python::install") }
# Base Suse packages.
it { is_expected.to contain_package("python") }
it { is_expected.to contain_package("python-dev").with_name("python-devel") }
it { is_expected.to contain_package("python-dev").with_alias("python-devel") }
it { is_expected.to contain_package("pip") }
# Basic python packages (from pip)
it { is_expected.to contain_package("virtualenv")}
describe "with python::dev" do
context "true" do
let (:params) {{ :dev => 'present' }}
it { is_expected.to contain_package("python-dev").with_ensure('present') }
end
context "empty/default" do
it { is_expected.to contain_package("python-dev").with_ensure('absent') }
end
end
describe "with manage_gunicorn" do
context "true" do
let (:params) {{ :manage_gunicorn => true }}
it { is_expected.to contain_package("gunicorn") }
end
context "empty args" do
#let (:params) {{ :manage_gunicorn => '' }}
it { is_expected.to contain_package("gunicorn") }
end
context "false" do
let (:params) {{ :manage_gunicorn => false }}
it {is_expected.not_to contain_package("gunicorn")}
end
end
describe "with python::provider" do
context "pip" do
let (:params) {{ :provider => 'pip' }}
it { is_expected.to contain_package("virtualenv").with(
'provider' => 'pip'
)}
it { is_expected.to contain_package("pip").with(
'provider' => 'pip'
)}
end
# python::provider
context "default" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv")}
it { is_expected.to contain_package("pip")}
describe "with python::virtualenv" do
context "true" do
let (:params) {{ :provider => '', :virtualenv => 'present' }}
it { is_expected.to contain_package("virtualenv").with_ensure('present') }
end
end
describe "with python::virtualenv" do
context "default/empty" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv").with_ensure('absent') }
end
end
end
end
describe "with python::dev" do
context "true" do
let (:params) {{ :dev => 'present' }}
it { is_expected.to contain_package("python-dev").with_ensure('present') }
end
context "default/empty" do
it { is_expected.to contain_package("python-dev").with_ensure('absent') }
end
end
describe "EPEL does not exist on Suse" do
context "default/empty" do
it { should_not contain_class('epel') }
end
end
end
context "on a Gentoo OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:lsbdistcodename => 'n/a',
:osfamily => 'Gentoo',
:operatingsystem => 'Gentoo',
:concat_basedir => '/dne',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
}
end
it { is_expected.to contain_class("python::install") }
# Base debian packages.
it { is_expected.to contain_package("python") }
it { is_expected.to contain_package("pip").with({"category" => "dev-python"}) }
# Basic python packages (from pip)
it { is_expected.to contain_package("virtualenv")}
# Python::Dev
it { is_expected.not_to contain_package("python-dev") }
describe "with manage_gunicorn" do
context "true" do
let (:params) {{ :manage_gunicorn => true }}
it { is_expected.to contain_package("gunicorn") }
end
context "empty args" do
#let (:params) {{ :manage_gunicorn => '' }}
it { is_expected.to contain_package("gunicorn") }
end
context "false" do
let (:params) {{ :manage_gunicorn => false }}
it {is_expected.not_to contain_package("gunicorn")}
end
end
describe "with python::provider" do
context "pip" do
let (:params) {{ :provider => 'pip' }}
it { is_expected.to contain_package("virtualenv").with(
'provider' => 'pip'
)}
it { is_expected.to contain_package("pip").with(
'provider' => 'pip'
)}
end
# python::provider
context "default" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv")}
it { is_expected.to contain_package("pip")}
describe "with python::virtualenv" do
context "true" do
let (:params) {{ :provider => '', :virtualenv => 'present' }}
it { is_expected.to contain_package("virtualenv").with_ensure('present') }
end
end
describe "with python::virtualenv" do
context "default/empty" do
let (:params) {{ :provider => '' }}
it { is_expected.to contain_package("virtualenv").with_ensure('absent') }
end
end
end
end
end
end

View File

@@ -0,0 +1,36 @@
require 'spec_helper'
describe 'python::gunicorn', :type => :define do
let(:title) { 'test-app' }
context 'on Debian OS' do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:lsbdistcodename => 'squeeze',
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemrelease => '6',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
:concat_basedir => '/dne',
}
end
describe 'test-app with default parameter values' do
context 'configures test app with default parameter values' do
let(:params) { { :dir => '/srv/testapp' } }
it { is_expected.to contain_file('/etc/gunicorn.d/test-app').with_mode('0644').with_content(/--log-level=error/) }
end
context 'test-app with custom log level' do
let(:params) { { :dir => '/srv/testapp', :log_level => 'info' } }
it { is_expected.to contain_file('/etc/gunicorn.d/test-app').with_mode('0644').with_content(/--log-level=info/) }
end
context 'test-app with custom gunicorn preload arguments' do
let(:params) { { :dir => '/srv/testapp', :args => ['--preload'] } }
it { is_expected.to contain_file('/etc/gunicorn.d/test-app').with_mode('0644').with_content(/--preload/) }
end
end
end
end

View File

@@ -0,0 +1,71 @@
require 'spec_helper'
describe 'python::pip', :type => :define do
let (:title) { 'rpyc' }
context "on Debian OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:lsbdistcodename => 'squeeze',
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemrelease => '6',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
:concat_basedir => '/dne',
}
end
describe "virtualenv as" do
context "fails with non qualified path" do
let (:params) {{ :virtualenv => "venv" }}
it { is_expected.to raise_error(/"venv" is not an absolute path./) }
end
context "suceeds with qualified path" do
let (:params) {{ :virtualenv => "/opt/venv" }}
it { is_expected.to contain_exec("pip_install_rpyc").with_cwd('/opt/venv') }
end
context "defaults to system" do
let (:params) {{ }}
it { is_expected.to contain_exec("pip_install_rpyc").with_cwd('/') }
end
end
describe "proxy as" do
context "defaults to empty" do
let (:params) {{ }}
it { should_not contain_exec("pip_install_rpyc").with_command(/--proxy/) }
end
context "does not add proxy to search command if set to latest and proxy is unset" do
let (:params) {{ :ensure => 'latest' }}
it { should_not contain_exec("pip_install_rpyc").with_command(/--proxy/) }
it { is_expected.to contain_exec("pip_install_rpyc").without_unless(/--proxy/) }
end
context "adds proxy to install command if proxy set" do
let (:params) {{ :proxy => "http://my.proxy:3128" }}
it { is_expected.to contain_exec("pip_install_rpyc").with_command("pip wheel --help > /dev/null 2>&1 && { pip wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; { pip --log /tmp/pip.log install $wheel_support_flag --proxy=http://my.proxy:3128 rpyc || pip --log /tmp/pip.log install --proxy=http://my.proxy:3128 rpyc ;}") }
end
context "adds proxy to search command if set to latest" do
let (:params) {{ :proxy => "http://my.proxy:3128", :ensure => 'latest' }}
it { is_expected.to contain_exec("pip_install_rpyc").with_command("pip wheel --help > /dev/null 2>&1 && { pip wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; { pip --log /tmp/pip.log install --upgrade $wheel_support_flag --proxy=http://my.proxy:3128 rpyc || pip --log /tmp/pip.log install --upgrade --proxy=http://my.proxy:3128 rpyc ;}") }
it { is_expected.to contain_exec("pip_install_rpyc").with_unless('pip search --proxy=http://my.proxy:3128 rpyc | grep -i INSTALLED.*latest') }
end
end
describe 'index as' do
context 'defaults to empty' do
let (:params) {{ }}
it { should_not contain_exec('pip_install_rpyc').with_command(/--index-url/) }
end
context 'adds index to install command if index set' do
let (:params) {{ :index => 'http://www.example.com/simple/' }}
it { is_expected.to contain_exec('pip_install_rpyc').with_command("pip wheel --help > /dev/null 2>&1 && { pip wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; { pip --log /tmp/pip.log install $wheel_support_flag --index-url=http://www.example.com/simple/ rpyc || pip --log /tmp/pip.log install --index-url=http://www.example.com/simple/ rpyc ;}") }
end
context 'adds index to search command if set to latest' do
let (:params) {{ :index => 'http://www.example.com/simple/', :ensure => 'latest' }}
it { is_expected.to contain_exec('pip_install_rpyc').with_command("pip wheel --help > /dev/null 2>&1 && { pip wheel --version > /dev/null 2>&1 || wheel_support_flag='--no-use-wheel'; } ; { pip --log /tmp/pip.log install --upgrade $wheel_support_flag --index-url=http://www.example.com/simple/ rpyc || pip --log /tmp/pip.log install --upgrade --index-url=http://www.example.com/simple/ rpyc ;}") }
end
end
end
end

View File

@@ -0,0 +1,27 @@
require 'spec_helper'
describe 'python::pyvenv', :type => :define do
let (:title) { '/opt/env' }
let (:facts) do
{
:lsbdistcodename => 'jessie',
:osfamily => 'Debian',
}
end
it {
is_expected.to contain_file( '/opt/env')
is_expected.to contain_exec( "python_virtualenv_/opt/env").with_command("pyvenv --clear /opt/env")
}
describe 'when ensure' do
context "is absent" do
let (:params) {{
:ensure => 'absent'
}}
it {
is_expected.to contain_file( '/opt/env').with_ensure('absent').with_purge( true)
}
end
end
end

View File

@@ -0,0 +1,50 @@
require 'spec_helper'
describe 'python::requirements', :type => :define do
let (:title) { '/requirements.txt' }
context "on Debian OS" do
let :facts do
{
:id => 'root',
:kernel => 'Linux',
:lsbdistcodename => 'squeeze',
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemrelease => '6',
:path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
:concat_basedir => '/dne',
}
end
describe "requirements as" do
context "/requirements.txt" do
let (:params) {{ :requirements => "/requirements.txt" }}
it { is_expected.to contain_file("/requirements.txt").with_mode('0644') }
end
context "/requirements.txt" do
let (:params) {{ :requirements => "/requirements.txt", :manage_requirements => false }}
it { is_expected.not_to contain_file("/requirements.txt") }
end
describe "with owner" do
context "bob:bob" do
let (:params) {{
:owner => 'bob',
:group => 'bob'
}}
it do
expect {
is_expected.to compile
}.to raise_error(/root user must be used when virtualenv is system/)
end
end
end
describe "with owner" do
context "default" do
it { is_expected.to contain_file("/requirements.txt").with_owner('root').with_group('root') }
end
end
end
end
end

View File

@@ -0,0 +1,6 @@
--format
s
--colour
--loadby
mtime
--backtrace

View File

@@ -0,0 +1,18 @@
require 'puppetlabs_spec_helper/module_spec_helper'
RSpec.configure do |config|
config.hiera_config = 'spec/fixtures/hiera/hiera.yaml'
config.before :each do
# Ensure that we don't accidentally cache facts and environment between
# test cases. This requires each example group to explicitly load the
# facts being exercised with something like
# Facter.collection.loader.load(:ipaddress)
Facter.clear
Facter.clear_messages
end
config.default_facts = {
:environment => 'rp_env',
:operatingsystemmajrelease => '6',
:osfamily => 'RedHat',
}
end

View File

@@ -0,0 +1,33 @@
require 'beaker-rspec'
UNSUPPORTED_PLATFORMS = [ 'windows' ]
unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no'
hosts.each do |host|
if host.is_pe?
install_pe
else
install_puppet
end
end
end
RSpec.configure do |c|
# Project root
proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
# Readable test descriptions
c.formatter = :documentation
# Configure all nodes in nodeset
c.before :suite do
# Install module and dependencies
hosts.each do |host|
shell("rm -rf /etc/puppet/modules/python/")
copy_module_to(host, :source => proj_root, :module_name => 'python')
shell("/bin/touch #{default['puppetpath']}/hiera.yaml")
on host, puppet('module install puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] }
on host, puppet('module install stahnma-epel'), { :acceptable_exit_codes => [0,1] }
end
end
end

View File

@@ -0,0 +1,32 @@
require "spec_helper"
describe Facter::Util::Fact do
before {
Facter.clear
}
let(:pip_version_output) { <<-EOS
pip 6.0.6 from /opt/boxen/homebrew/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pip-6.0.6-py2.7.egg (python 2.7)
EOS
}
describe "pip_version" do
context 'returns pip version when pip present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("pip").returns(true)
Facter::Util::Resolution.expects(:exec).with("pip --version 2>&1").returns(pip_version_output)
expect(Facter.value(:pip_version)).to eq("6.0.6")
end
end
context 'returns nil when pip not present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("pip").returns(false)
expect(Facter.value(:pip_version)).to eq(nil)
end
end
end
end

View File

@@ -0,0 +1,98 @@
require "spec_helper"
describe Facter::Util::Fact do
before {
Facter.clear
}
let(:python2_version_output) { <<-EOS
Python 2.7.9
EOS
}
let(:python3_version_output) { <<-EOS
Python 3.3.0
EOS
}
describe "python_release" do
context 'returns Python release when `python` present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python2_version_output)
expect(Facter.value(:python_release)).to eq("2.7")
end
end
context 'returns nil when `python` not present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(false)
expect(Facter.value(:python_release)).to eq(nil)
end
end
end
describe "python2_release" do
context 'returns Python 2 release when `python` is present and Python 2' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python2_version_output)
expect(Facter.value(:python2_release)).to eq('2.7')
end
end
context 'returns Python 2 release when `python` is Python 3 and `python2` is present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python3_version_output)
Facter::Util::Resolution.expects(:which).with("python2").returns(true)
Facter::Util::Resolution.expects(:exec).with("python2 -V 2>&1").returns(python2_version_output)
expect(Facter.value(:python2_release)).to eq('2.7')
end
end
context 'returns nil when `python` is Python 3 and `python2` is absent' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python3_version_output)
Facter::Util::Resolution.expects(:which).with("python2").returns(false)
expect(Facter.value(:python2_release)).to eq(nil)
end
end
context 'returns nil when `python2` and `python` are absent' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(false)
Facter::Util::Resolution.expects(:which).with("python2").returns(false)
expect(Facter.value(:python2_release)).to eq(nil)
end
end
end
describe "python3_release" do
context 'returns Python 3 release when `python3` present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python3").returns(true)
Facter::Util::Resolution.expects(:exec).with("python3 -V 2>&1").returns(python3_version_output)
expect(Facter.value(:python3_release)).to eq("3.3")
end
end
context 'returns nil when `python3` not present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python3").returns(false)
expect(Facter.value(:python3_release)).to eq(nil)
end
end
end
end

View File

@@ -0,0 +1,98 @@
require "spec_helper"
describe Facter::Util::Fact do
before {
Facter.clear
}
let(:python2_version_output) { <<-EOS
Python 2.7.9
EOS
}
let(:python3_version_output) { <<-EOS
Python 3.3.0
EOS
}
describe "python_version" do
context 'returns Python version when `python` present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python2_version_output)
expect(Facter.value(:python_version)).to eq("2.7.9")
end
end
context 'returns nil when `python` not present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(false)
expect(Facter.value(:python_version)).to eq(nil)
end
end
end
describe "python2_version" do
context 'returns Python 2 version when `python` is present and Python 2' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python2_version_output)
expect(Facter.value(:python2_version)).to eq('2.7.9')
end
end
context 'returns Python 2 version when `python` is Python 3 and `python2` is present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python3_version_output)
Facter::Util::Resolution.expects(:which).with("python2").returns(true)
Facter::Util::Resolution.expects(:exec).with("python2 -V 2>&1").returns(python2_version_output)
expect(Facter.value(:python2_version)).to eq('2.7.9')
end
end
context 'returns nil when `python` is Python 3 and `python2` is absent' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(true)
Facter::Util::Resolution.expects(:exec).with("python -V 2>&1").returns(python3_version_output)
Facter::Util::Resolution.expects(:which).with("python2").returns(false)
expect(Facter.value(:python2_version)).to eq(nil)
end
end
context 'returns nil when `python2` and `python` are absent' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python").returns(false)
Facter::Util::Resolution.expects(:which).with("python2").returns(false)
expect(Facter.value(:python2_version)).to eq(nil)
end
end
end
describe "python3_version" do
context 'returns Python 3 version when `python3` present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python3").returns(true)
Facter::Util::Resolution.expects(:exec).with("python3 -V 2>&1").returns(python3_version_output)
expect(Facter.value(:python3_version)).to eq("3.3.0")
end
end
context 'returns nil when `python3` not present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("python3").returns(false)
expect(Facter.value(:python3_version)).to eq(nil)
end
end
end
end

View File

@@ -0,0 +1,32 @@
require "spec_helper"
describe Facter::Util::Fact do
before {
Facter.clear
}
let(:virtualenv_version_output) { <<-EOS
12.0.7
EOS
}
describe "virtualenv_version" do
context 'returns virtualenv version when virtualenv present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("virtualenv").returns(true)
Facter::Util::Resolution.expects(:exec).with("virtualenv --version 2>&1").returns(virtualenv_version_output)
expect(Facter.value(:virtualenv_version)).to eq("12.0.7")
end
end
context 'returns nil when virtualenv not present' do
it do
Facter::Util::Resolution.stubs(:exec)
Facter::Util::Resolution.expects(:which).with("virtualenv").returns(false)
expect(Facter.value(:virtualenv_version)).to eq(nil)
end
end
end
end

View File

@@ -0,0 +1,61 @@
CONFIG = {
<% if @mode == 'django' -%>
'mode': 'django',
<% else -%>
'mode': 'wsgi',
<% end -%>
<% if @virtualenv -%>
'environment': {
<% if @osenv -%><% @osenv.sort.each do |key, value| -%>
'<%= key %>': '<%= value %>',
<% end -%><% end -%>
<% if @environment -%>
'ENVIRONMENT': '<%= @environment %>',
<% end -%>
'PYTHONPATH': '<%= @virtualenv %>'
},
<% end -%>
'working_dir': '<%= @dir %>',
'user': '<%= @owner %>',
'group': '<%= @group %>',
<% if @virtualenv -%>
'python': '<%= @virtualenv %>/bin/python',
<% else -%>
'python': '/usr/bin/python',
<% end -%>
'args': (
<% if @args.any? -%>
<% for arg in @args do -%>
'<%= arg %>',
<% end -%>
<% end -%>
<% if !@virtualenv and !@bind -%>
'--bind=unix:/tmp/gunicorn-<%= @name %>.socket',
<% elsif @virtualenv and !@bind -%>
'--bind=unix:<%= @virtualenv %>/<%= @name %>.socket',
<% else -%>
'--bind=<%= @bind %>',
<% end -%>
<% if @workers -%>
'--workers=<%= @workers %>',
<% else -%>
'--workers=<%= @processorcount.to_i*2 + 1 %>',
<% end -%>
'--timeout=<%= @timeout %>',
<% if @access_log_format -%>
'--access-logformat=<%= @access_log_format %>',
<% end -%>
<% if @accesslog -%>
'--access-logfile=<%= @accesslog %>',
<% end -%>
<% if @errorlog -%>
'--error-logfile=<%= @errorlog %>',
<% end -%>
<% if @log_level %>
'--log-level=<%= @log_level %>',
<% end -%>
<% if @mode != 'django' -%>
'<%= @appmodule %>',
<% end -%>
),
}

View File

@@ -0,0 +1,8 @@
# this file is managed by puppet
<%- @config.sort.map do |section,conf| -%>
[<%= section -%>]
<%- conf.sort.map do |key,value| -%>
<%= key %> = <%= value %>
<%- end -%>
<%- end -%>

View File

@@ -0,0 +1,20 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::gunicorn { 'vhost':
ensure => present,
virtualenv => '/var/www/project1',
mode => 'wsgi',
dir => '/var/www/project1/current',
bind => 'unix:/tmp/gunicorn.socket',
environment => 'prod',
appmodule => 'app:app',
osenv => {
'DBHOST' => 'dbserver.example.com'
},
timeout => 30,
template => 'python/gunicorn.erb',
}

View File

@@ -0,0 +1,5 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}

View File

@@ -0,0 +1,10 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::pip { 'flask':
virtualenv => '/var/www/project1',
proxy => 'http://proxy.domain.com:3128',
}

View File

@@ -0,0 +1,12 @@
class { 'python':
pip => false,
version => '3',
}
python::pyvenv { '/opt/uwsgi':
}
python::pip { 'uwsgi':
ensure => 'latest',
virtualenv => '/opt/uwsgi'
}

View File

@@ -0,0 +1,16 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::requirements { '/var/www/project1/requirements.txt':
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',
timeout => 2400,
}

View File

@@ -0,0 +1,13 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::virtualenv { '/var/www/project1':
ensure => present,
version => 'system',
requirements => '/var/www/project1/requirements.txt',
proxy => 'http://proxy.domain.com:3128',
systempkgs => true,
}

View File

@@ -0,0 +1,20 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::gunicorn { 'vhost':
ensure => present,
virtualenv => '/var/www/project1',
mode => 'wsgi',
dir => '/var/www/project1/current',
bind => 'unix:/tmp/gunicorn.socket',
environment => 'prod',
appmodule => 'app:app',
osenv => {
'DBHOST' => 'dbserver.example.com'
},
timeout => 30,
template => 'python/gunicorn.erb',
}

View File

@@ -0,0 +1,5 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}

View File

@@ -0,0 +1,10 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::pip { 'flask':
virtualenv => '/var/www/project1',
proxy => 'http://proxy.domain.com:3128',
}

View File

@@ -0,0 +1,12 @@
class { 'python':
pip => false,
version => '3',
}
python::pyvenv { '/opt/uwsgi':
}
python::pip { 'uwsgi':
ensure => 'latest',
virtualenv => '/opt/uwsgi'
}

View File

@@ -0,0 +1,16 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::requirements { '/var/www/project1/requirements.txt':
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',
timeout => 2400,
}

View File

@@ -0,0 +1,13 @@
class { 'python':
version => 'system',
dev => true,
virtualenv => true,
}
python::virtualenv { '/var/www/project1':
ensure => present,
version => 'system',
requirements => '/var/www/project1/requirements.txt',
proxy => 'http://proxy.domain.com:3128',
systempkgs => true,
}