Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

COOK-432, updated python cookbook with pip and virtualenv LWRPs

  • Loading branch information...
commit 3acfd7839bddd586211b52b29e67d5f82b71ba9b 1 parent 311f416
@schisamo schisamo authored
View
131 python/README.md
@@ -0,0 +1,131 @@
+Description
+===========
+
+Installs and configures Python 2.6. Also includes LWRPs for managing `pip` packages and `virtualenv` isolated Python environments.
+
+Requirements
+============
+
+Platform
+--------
+
+* Debian, Ubuntu
+* CentOS, Red Hat, Fedora
+
+Cookbooks
+---------
+
+Attributes
+==========
+
+None at this time.
+
+Resource/Provider
+=================
+
+This cookbook includes LWRPs for managing:
+
+* pip packages
+* virtualenv isolated Python environments
+
+`python_pip`
+------------
+
+Install packages using the new hotness in Python package management...[`pip`](http://pypi.python.org/pypi/pip). Yo dawg...easy_install is so 2009, you better ask your local Pythonista if you don't know! The usage semantics are like that of any normal package provider.
+
+# Actions
+
+- :install: Install a pip package - if version is provided, install that specific version
+- :upgrade: Upgrade a pip package - if version is provided, upgrade to that specific version
+- :remove: Remove a pip package
+- :purge: Purge a pip package (this usually entails removing configuration files as well as the package itself). With pip packages this behaves the same as `:remove`
+
+# Attribute Parameters
+
+- package_name: name attribute. The name of the pip package to install
+- version: the version of the package to install/upgrade. If no version is given latest is assumed.
+- virtualenv: virtualenv environment to install pip package into
+- options: Add additional options to the underlying pip package command
+
+# Example
+
+ # install latest gunicorn into system path
+ python_pip "gunicorn" do
+ action :install
+ end
+
+ # target a virtualenv
+ python_pip "gunicorn" do
+ virtualenv "/home/ubunut/my_ve"
+ action :install
+ end
+
+ # install Django 1.1.4
+ python_pip "django" do
+ version "1.1.4"
+ action :install
+ end
+
+ # use this provider with the core package resource
+ package "django" do
+ provider Chef::Provider::PythonPip
+ action :install
+ end
+
+`python_virtualenv`
+-------------------
+
+[`virtualenv`](http://pypi.python.org/pypi/virtualenv) is a great tool that creates isolated python environments. Think of it as RVM without all those hipsters and tight jeans.
+
+# Actions
+
+- :create: creates a new virtualenv
+- :delete: deletes an existing virtualenv
+
+# Attribute Parameters
+
+- path: name attribute. The path where the virtualenv will be created
+- interpreter: The Python interpreter to use. default is `python2.6`
+- owner: The owner for the virtualenv
+- group: The group owner of the file (string or id)
+
+# Example
+
+ # create a 2.6 virtualenv owned by ubuntu user
+ python_virtualenv "/home/ubuntu/my_cool_ve" do
+ owner "ubuntu"
+ group "ubuntu"
+ action :create
+ end
+
+ # create a Python 2.4 virtualenv
+ python_virtualenv "/home/ubuntu/my_old_ve" do
+ interpreter "python2.4"
+ owner "ubuntu"
+ group "ubuntu"
+ action :create
+ end
+
+Usage
+=====
+
+Simply include the recipe where you want Python 2.6 installed.
+
+License and Author
+==================
+
+Author:: Seth Chisamore (<schisamo@opscode.com>)
+
+Copyright:: 2011, Opscode, Inc
+
+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
75 python/metadata.json
@@ -1,36 +1,45 @@
{
- "recommendations": {
- },
- "attributes": {
- },
- "maintainer": "Opscode, Inc.",
- "suggestions": {
- },
- "dependencies": {
- },
- "maintainer_email": "cookbooks@opscode.com",
- "conflicting": {
- },
- "platforms": {
- "debian": [
+ "name": "python",
+ "description": "Installs python packages",
+ "long_description": "",
+ "maintainer": "Opscode, Inc.",
+ "maintainer_email": "cookbooks@opscode.com",
+ "license": "Apache 2.0",
+ "platforms": {
+ "debian": [
- ],
- "ubuntu": [
+ ],
+ "ubuntu": [
- ]
- },
- "license": "Apache 2.0",
- "version": "0.7.0",
- "providing": {
- },
- "recipes": {
- "python": "Installs python and common python module packages"
- },
- "replacing": {
- },
- "name": "python",
- "description": "Installs python packages",
- "groupings": {
- },
- "long_description": ""
- }
+ ],
+ "centos": [
+
+ ],
+ "redhat": [
+
+ ],
+ "fedora": [
+
+ ]
+ },
+ "dependencies": {
+ },
+ "recommendations": {
+ },
+ "suggestions": {
+ },
+ "conflicting": {
+ },
+ "providing": {
+ },
+ "replacing": {
+ },
+ "attributes": {
+ },
+ "groupings": {
+ },
+ "recipes": {
+ "python": "Installs python, pip, and virtualenv"
+ },
+ "version": "0.99.0"
+}
View
6 python/metadata.rb
@@ -2,10 +2,10 @@
maintainer_email "cookbooks@opscode.com"
license "Apache 2.0"
description "Installs python packages"
-version "0.7"
+version "0.99"
-recipe "python", "Installs python and common python module packages"
+recipe "python", "Installs python, pip, and virtualenv"
-%w{ debian ubuntu }.each do |os|
+%w{ debian ubuntu centos redhat fedora }.each do |os|
supports os
end
View
146 python/providers/pip.rb
@@ -0,0 +1,146 @@
+#
+# Author:: Seth Chisamore <schisamo@opscode.com>
+# Cookbook Name:: python
+# Provider:: pip
+#
+# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
+#
+# 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.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+# the logic in all action methods mirror that of
+# the Chef::Provider::Package which will make
+# refactoring into core chef easy
+
+action :install do
+ # If we specified a version, and it's not the current version, move to the specified version
+ if @new_resource.version != nil && @new_resource.version != @current_resource.version
+ install_version = @new_resource.version
+ # If it's not installed at all, install it
+ elsif @current_resource.version == nil
+ install_version = candidate_version
+ end
+
+ if install_version
+ Chef::Log.info("Installing #{@new_resource} version #{install_version}")
+ status = install_package(@new_resource.package_name, install_version)
+ if status
+ @new_resource.updated_by_last_action(true)
+ end
+ end
+end
+
+action :upgrade do
+ if @current_resource.version != candidate_version
+ orig_version = @current_resource.version || "uninstalled"
+ Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}")
+ status = upgrade_package(@new_resource.package_name, candidate_version)
+ if status
+ @new_resource.updated_by_last_action(true)
+ end
+ end
+end
+
+action :remove do
+ if removing_package?
+ Chef::Log.info("Removing #{@new_resource}")
+ remove_package(@current_resource.package_name, @new_resource.version)
+ @new_resource.updated_by_last_action(true)
+ else
+ end
+end
+
+def removing_package?
+ if @current_resource.version.nil?
+ false # nothing to remove
+ elsif @new_resource.version.nil?
+ true # remove any version of a package
+ elsif @new_resource.version == @current_resource.version
+ true # remove the version we have
+ else
+ false # we don't have the version we want to remove
+ end
+end
+
+def expand_options(options)
+ options ? " #{options}" : ""
+end
+
+# these methods are the required overrides of
+# a provider that extends from Chef::Provider::Package
+# so refactoring into core Chef should be easy
+
+def load_current_resource
+ @current_resource = Chef::Resource::PythonPip.new(@new_resource.name)
+ @current_resource.package_name(@new_resource.package_name)
+ @current_resource.version(nil)
+
+ unless current_installed_version.nil?
+ @current_resource.version(current_installed_version)
+ end
+
+ @current_resource
+end
+
+def current_installed_version
+ @current_installed_version ||= begin
+ delimeter = /==/
+
+ version_check_cmd = "pip freeze#{expand_virtualenv(can_haz_virtualenv(@new_resource))} | grep -i #{@new_resource.package_name}"
+ # incase you upgrade pip with pip!
+ if @new_resource.package_name.eql?('pip')
+ delimeter = /\s/
+ version_check_cmd = "pip --version"
+ end
+ p = shell_out!(version_check_cmd)
+ p.stdout.split(delimeter)[1].strip
+ rescue Chef::Exceptions::ShellCommandFailed
+ end
+end
+
+def candidate_version
+ @candidate_version ||= begin
+ # `pip search` doesn't return versions yet
+ # `pip list` may be coming soon:
+ # https://bitbucket.org/ianb/pip/issue/197/option-to-show-what-version-would-be
+ @new_resource.version||'latest'
+ end
+end
+
+def install_package(name,version)
+ v = "==#{version}" unless version.eql?('latest')
+ shell_out!("pip install#{expand_options(@new_resource.options)}#{expand_virtualenv(can_haz_virtualenv(@new_resource))} #{name}#{v}")
+end
+
+def upgrade_package(name, version)
+ v = "==#{version}" unless version.eql?('latest')
+ shell_out!("pip install --upgrade#{expand_options(@new_resource.options)}#{expand_virtualenv(can_haz_virtualenv(@new_resource))} #{@new_resource.name}#{v}")
+end
+
+def remove_package(name, version)
+ shell_out!("pip uninstall -y#{expand_options(@new_resource.options)}#{expand_virtualenv(can_haz_virtualenv(@new_resource))} #{@new_resource.name}")
+end
+
+def expand_virtualenv(virtualenv)
+ virtualenv && " --environment=#{virtualenv}"
+end
+
+# TODO remove when provider is moved into Chef core
+# this allows PythonPip to work with Chef::Resource::Package
+def can_haz_virtualenv(nr)
+ nr.respond_to?("virtualenv") ? nr.virtualenv : nil
+end
View
60 python/providers/virtualenv.rb
@@ -0,0 +1,60 @@
+#
+# Author:: Seth Chisamore <schisamo@opscode.com>
+# Cookbook Name:: python
+# Provider:: virtualenv
+#
+# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
+#
+# 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.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+action :create do
+ unless exists?
+ Chef::Log.info("Creating virtualenv #{@new_resource} at #{@new_resource.path}")
+ execute "virtualenv --python=#{@new_resource.interpreter} #{@new_resource.path}" do
+ user new_resource.owner if new_resource.owner
+ group new_resource.group if new_resource.group
+ end
+ new_resource.updated_by_last_action(true)
+ end
+end
+
+action :delete do
+ if exists?
+ Chef::Log.info("Deleting virtualenv #{@new_resource} at #{@new_resource.path}")
+ FileUtils.rm_rf(@new_resource.path)
+ new_resource.updated_by_last_action(true)
+ end
+end
+
+def load_current_resource
+ @current_resource = Chef::Resource::PythonVirtualenv.new(@new_resource.name)
+ @current_resource.path(@new_resource.path)
+
+ if exists?
+ cstats = ::File.stat(@current_resource.path)
+ @current_resource.owner(cstats.uid)
+ @current_resource.group(cstats.gid)
+ end
+ @current_resource
+end
+
+private
+def exists?
+ ::File.exist?(@current_resource.path) && ::File.directory?(@current_resource.path) \
+ && ::File.exists?("#{@current_resource.path}/bin/activate")
+end
View
41 python/recipes/default.rb
@@ -1,8 +1,9 @@
#
+# Author:: Seth Chisamore <schisamo@opscode.com>
# Cookbook Name:: python
# Recipe:: default
#
-# Copyright 2009, Opscode, Inc.
+# Copyright 2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,15 +17,37 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-package "python" do
- action :install
-end
-%w{
- dev imaging matplotlib matplotlib-data matplotlib-doc mysqldb
- numpy numpy-ext paramiko scipy setuptools sqlite
-}.each do |pkg|
- package "python-#{pkg}" do
+python_pkgs = value_for_platform(
+ ["debian","ubuntu"] => {
+ "default" => ["python","python-dev"]
+ },
+ ["centos","redhat","fedora"] => {
+ "default" => ["python26","python26-devel"]
+ },
+ "default" => ["python","python-dev"]
+)
+
+python_pkgs.each do |pkg|
+ package pkg do
action :install
end
end
+
+# Ubuntu's python-setuptools, python-pip and python-virtualenv packages
+# are broken...this feels like Rubygems!
+# http://stackoverflow.com/questions/4324558/whats-the-proper-way-to-install-pip-virtualenv-and-distribute-for-python
+# https://bitbucket.org/ianb/pip/issue/104/pip-uninstall-on-ubuntu-linux
+bash "install-pip" do
+ cwd Chef::Config[:file_cache_path]
+ code <<-EOH
+ curl -O http://python-distribute.org/distribute_setup.py
+ python distribute_setup.py
+ easy_install pip
+ EOH
+ not_if "which pip"
+end
+
+python_pip "virtualenv" do
+ action :install
+end
View
26 python/resources/pip.rb
@@ -0,0 +1,26 @@
+#
+# Author:: Seth Chisamore <schisamo@opscode.com>
+# Cookbook Name:: python
+# Resource:: pip
+#
+# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
+#
+# 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.
+#
+
+actions :install, :upgrade, :remove, :purge
+
+attribute :package_name, :kind_of => String, :name_attribute => true
+attribute :version, :default => nil
+attribute :virtualenv, :kind_of => String
+attribute :options, :kind_of => String
View
26 python/resources/virtualenv.rb
@@ -0,0 +1,26 @@
+#
+# Author:: Seth Chisamore <schisamo@opscode.com>
+# Cookbook Name:: python
+# Resource:: virtualenv
+#
+# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
+#
+# 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.
+#
+
+actions :create, :delete
+
+attribute :path, :kind_of => String, :name_attribute => true
+attribute :interpreter, :default => 'python2.6'
+attribute :owner, :regex => Chef::Config[:user_valid_regex]
+attribute :group, :regex => Chef::Config[:group_valid_regex]
Please sign in to comment.
Something went wrong with that request. Please try again.