Add new role, 'debops.python'

parent 0f329398
......@@ -1020,6 +1020,24 @@ stages:
JANE_DIFF_PATTERN: '.*/debops.prosody/.*'
JANE_LOG_PATTERN: '\[debops\.prosody\]'
'python role':
<<: *test_role_no_deps
variables:
JANE_TEST_PLAY: '${DEBOPS_PLAYBOOKS}/service/python.yml'
JANE_INVENTORY_GROUPS: 'debops_service_python'
JANE_DIFF_PATTERN: '.*/debops.python/.*'
JANE_LOG_PATTERN: '\[debops\.python\]'
'python/raw role':
<<: *test_role_no_deps
variables:
JANE_TEST_PLAY: '${DEBOPS_PLAYBOOKS}/service/python_raw.yml'
JANE_INVENTORY_HOSTVARS: 'ansible_python_interpreter=/usr/bin/python3'
JANE_INVENTORY_GROUPS: 'debops_service_python'
JANE_DIFF_PATTERN: '.*/debops.python/.*'
JANE_LOG_PATTERN: '\[debops\.python\]'
# --- r --- [[[2
'rabbitmq_management role':
......
......@@ -37,6 +37,9 @@ Added
longer used. This role needs to be executed manually, it's not included in
the main playbook.
- :ref:`debops.python`: manage Python environment, with support for multiple
Python versions used at the same time.
- [debops.users] Selected UNIX accounts can now be configured to linger when
not logged in via the ``item.linger`` parameter. This allows these accounts
to maintain long-running services when not logged in via their own private
......
---
- name: Manage Python environment
hosts: [ 'debops_all_hosts', 'debops_service_python' ]
become: True
environment: '{{ inventory__environment | d({})
| combine(inventory__group_environment | d({}))
| combine(inventory__host_environment | d({})) }}'
roles:
- role: debops.python
tags: [ 'role::python' ]
---
- name: Bootstrap Python environment
hosts: [ 'debops_all_hosts', 'debops_service_python' ]
become: True
gather_facts: False
roles:
- role: debops.python/raw
tags: [ 'role::python_raw' ]
debops.python - Manage Python environment using Ansible
Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
Copyright (C) 2018 DebOps https://debops.org/
This Ansible role is part of DebOps.
DebOps is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
DebOps is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DebOps. If not, see https://www.gnu.org/licenses/.
---
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
# debops.python default variables
# ===============================
# .. contents:: Sections
# :local:
# General configuration [[[
# -------------------------
# .. envvar:: python__enabled [[[
#
# Enable or disable Python management via the :ref:`debops.python` role.
python__enabled: True
# ]]]
# ]]]
# Python 3 management [[[
# -----------------------
# .. envvar:: python__v3 [[[
#
# Enable or disable support for Python 3 management. Python 3 will be
# automatically disabled on some OS releases due to missing or outdated Python
# 3 packages.
python__v3: '{{ False
if (ansible_distribution_release|d() in
[ "wheezy", "precise" ])
else True }}'
# ]]]
# .. envvar:: python__core_packages3 [[[
#
# List of core Python 3 APT packages to install. These packages will be
# installed in the "raw" mode as well as during normal role operation.
python__core_packages3:
- 'python3'
- 'python3-apt'
# ]]]
# .. envvar:: python__base_packages3 [[[
#
# List of base Python 3 packges to install via APT. These packages should allow
# creation of Python 3 virtual environments and installation of Python packages
# via the :command:`pip3` command from the PyPI repository, as well as Ansible
# opration on the remote host.
python__base_packages3:
- 'python3-httplib2'
- 'python3-pip'
- 'python3-setuptools'
- 'python3-pycurl'
- 'python3-virtualenv'
- 'python3-wheel'
- 'virtualenv'
# ]]]
# .. envvar:: python__packages3 [[[
#
# List of Python 3 APT packages which should be installed on all hosts in the
# Ansible inventory.
python__packages3: []
# ]]]
# .. envvar:: python__group_packages3 [[[
#
# List of Python 3 APT packages which should be installed on hosts in
# a specific Ansible inventory group.
python__group_packages3: []
# ]]]
# .. envvar:: python__host_packages3 [[[
#
# List of Python 3 APT packages which should be installed on specific hosts in
# the Ansible inventory.
python__host_packages3: []
# ]]]
# .. envvar:: python__dependent_packages3 [[[
#
# List of Python 3 APT packages defined by other Ansible roles via role
# dependent variables.
python__dependent_packages3: []
# ]]]
# ]]]
# Python 2 management [[[
# -----------------------
# .. envvar:: python__v2 [[[
#
# Enable or disable support for Python 2.7 management. Python 2.7 support will
# be automatically disabled if the ``ansible_python_interpreter`` inventory
# variable is set to ``/usr/bin/python3``, otherwise it will be enabled by
# default.
#
# If Python 2.7 support is disabled, using the role in the "raw" mode will
# purge Python 2.7 packages automatically. This can be controlled by the
# :envvar:`python__raw_purge_v2` variable.
python__v2: '{{ False
if ((ansible_python_interpreter|d("python")).endswith("python3"))
else True }}'
# ]]]
# .. envvar:: python__core_packages2 [[[
#
# List of core Python 2 APT packages to install. These packages will be
# installed in the "raw" mode as well as during normal role operation.
python__core_packages2:
- 'python'
- 'python-apt'
# ]]]
# .. envvar:: python__base_packages2 [[[
#
# List of base Python 2 packges to install via APT. These packages should allow
# creation of Python 2 virtual environments and installation of Python packages
# via the :command:`pip` command from the PyPI repository, as well as Ansible
# opration on the remote host.
python__base_packages2:
- 'python-httplib2'
- 'python-pip'
- 'python-setuptools'
- 'python-pycurl'
- 'python-virtualenv'
- '{{ [] if (ansible_distribution_release in
[ "wheezy", "precise" ])
else "python-wheel" }}'
# ]]]
# .. envvar:: python__packages2 [[[
#
# List of Python 2 APT packages which should be installed on all hosts in the
# Ansible inventory.
python__packages2: []
# ]]]
# .. envvar:: python__group_packages2 [[[
#
# List of Python 2 APT packages which should be installed on hosts in
# a specific Ansible inventory group.
python__group_packages2: []
# ]]]
# .. envvar:: python__host_packages2 [[[
#
# List of Python 2 APT packages which should be installed on specific hosts in
# the Ansible inventory.
python__host_packages2: []
# ]]]
# .. envvar:: python__dependent_packages2 [[[
#
# List of Python 2 APT packages defined by other Ansible roles via role
# dependent variables.
python__dependent_packages2: []
# ]]]
# ]]]
# Python 2/3 package installation [[[
# -----------------------------------
# .. envvar:: python__core_packages [[[
#
# List of APT packages that contains core Python packages selected by the role
# for installation. These packages will be installed in the "raw" mode as well
# as during normal operation. This variable is used in the role tasks.
python__core_packages: '{{ (python__core_packages3
if (python__v3|bool) else [])
+ (python__core_packages2
if (python__v2|bool) else []) }}'
# ]]]
# .. envvar:: python__combined_packages [[[
#
# List of APT packages that contains Python packages selected by the role for
# installation. This variable is used in the role tasks.
python__combined_packages: '{{ python__core_packages
+ ((python__base_packages3
+ python__packages3
+ python__group_packages3
+ python__host_packages3
+ python__dependent_packages3)
if python__v3|bool else [])
+ ((python__base_packages2
+ python__packages2
+ python__group_packages2
+ python__host_packages2
+ python__dependent_packages2)
if python__v2|bool else []) }}'
# ]]]
# ]]]
# Python 2 package purging [[[
# ----------------------------
# .. envvar:: python__raw_purge_v2 [[[
#
# Enable or disable purging of the Python 2.7 packages in the "raw" mode. This
# is useful if you want to completely remove Python 2.7 environment during host
# bootstrapping, and will be enabled by default if the
# ``ansible_python_interpreter`` inventory variable is set to
# ``/usr/bin/python3``.
#
# The packages will not be purged if the role detects the presence of the
# :file:`/etc/ansible/facts.d/python.fact` script.
python__raw_purge_v2: '{{ False
if (python__v2|bool)
else True }}'
# ]]]
# .. envvar:: python__raw_purge_packages2 [[[
#
# List of Python 2.7 APT packages which will be purged by the role in the "raw"
# mode.
python__raw_purge_packages2:
- 'python'
- 'python2.7'
- 'libpython2.7-minimal'
# ]]]
# ]]]
---
dependencies: []
galaxy_info:
author: 'Maciej Delmanowski'
description: 'Manage Python environment'
company: 'DebOps'
license: 'GPL-3.0'
min_ansible_version: '2.4.0'
platforms:
- name: Ubuntu
versions:
- precise
- trusty
- xenial
- bionic
- name: Debian
versions:
- wheezy
- jessie
- stretch
- buster
galaxy_tags:
- development
- pip
- python
- python2
- python3
- programming
- virtualenv
../defaults
\ No newline at end of file
---
- name: Update APT repositories, install core Python packages
raw: |
if [ -z "$(find /var/cache/apt/pkgcache.bin -mmin -43200)" ]; then
apt-get -q update
fi
if [ "{{ python__raw_purge_v2 | bool | lower }}" = "true" ] && [ ! -f "/etc/ansible/facts.d/python.fact" ] ; then
LANG=C apt-get --purge -yq remove {{ python__raw_purge_packages2 | join(" ") }}
fi
LANG=C apt-get --no-install-recommends -yq install {{ python__core_packages | join(" ") }}
register: python__register_raw
when: python__enabled|bool
changed_when: '"0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." not in python__register_raw.stdout_lines'
---
- name: Install requested APT packages
apt:
name: '{{ item }}'
state: 'present'
install_recommends: False
with_flattened: '{{ python__combined_packages }}'
when: python__enabled|bool and ansible_pkg_mgr == 'apt'
- name: Install requested packages
package:
name: '{{ item }}'
state: 'present'
with_flattened: '{{ python__combined_packages }}'
when: python__enabled|bool and ansible_pkg_mgr != 'apt'
- name: Make sure that Ansible local fact directory exists
file:
path: '/etc/ansible/facts.d'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0755'
- name: Save Python local facts
vars:
fact_src: '{{ "python.fact.py2"
if (ansible_python_version is version_compare("3.5", "<"))
else "python.fact" }}'
template:
src: 'etc/ansible/facts.d/{{ fact_src }}.j2'
dest: '/etc/ansible/facts.d/python.fact'
owner: 'root'
group: 'root'
mode: '0755'
register: python__register_facts
- name: Re-read local facts if they have been modified
action: setup
when: python__register_facts is changed
#!/usr/bin/python3
# {{ ansible_managed }}
from __future__ import print_function
from json import loads, dumps
from sys import exit
import os
def cmd_exists(cmd):
return any(
os.access(os.path.join(path, cmd), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
output = loads("""{{ ({'configured': True,
'enabled': python__enabled | bool,
'enabled2': python__v2 | bool,
'enabled3': python__v3 | bool
}) | to_nice_json }}""")
output['installed2'] = cmd_exists('python2')
output['installed3'] = cmd_exists('python3')
print(dumps(output, sort_keys=True, indent=4))
#!/usr/bin/python
# {{ ansible_managed }}
from __future__ import print_function
from json import loads, dumps
from sys import exit
import os
def cmd_exists(cmd):
return any(
os.access(os.path.join(path, cmd), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
output = loads("""{{ ({'configured': True,
'enabled': python__enabled | bool,
'enabled2': python__v2 | bool,
'enabled3': python__v3 | bool
}) | to_nice_json }}""")
output['installed2'] = cmd_exists('python2')
output['installed3'] = cmd_exists('python3')
print(dumps(output, sort_keys=True, indent=4))
......@@ -54,6 +54,7 @@ methods.
- :ref:`debops.java`
- :ref:`debops.nodejs`
- :ref:`debops.php`
- :ref:`debops.python`
- :ref:`debops.ruby`
- ``debops.hwraid``
- ``debops.rails_deploy``
......
Getting started
===============
.. contents::
:local:
Support for multiple Python versions
------------------------------------
The role allows management of multiple Python versions at the same time. The
available Python version is dependent on the OS release used on a given host.
Separate default variables can be used to specify APT packages to install for
Python 2.x and Python 3.x series. The different Python versions can then be
enabled or disabled independently - role automatically disables Python
3 support on older OS releases without adequate versions available, and
disables Python 2 support if Ansible is configured to use Python 3 interpreter
on a given host.
Python environment bootstrapping
--------------------------------
The special "raw" mode of operation with a custom Ansible playbook that doesn't
gather Ansible facts automatically can be used to "bootstrap" Python support on
a host. Role will automatically purge an existing Python 2.x packages if Python
2.x operation is disabled; this can be leveraged to maintain Python 3.x-only
setup, depending on the OS release used on the host.
Example inventory
-----------------
The ``debops.python`` role is included by default in the ``common.yml`` DebOps
playbook; you don't need to add hosts to any Ansible groups to enable it.
Example playbook
----------------
If you are using this role without DebOps, here's an example Ansible playbook
that uses the ``debops.python`` role:
.. literalinclude:: ../../../../ansible/playbooks/service/python.yml
:language: yaml
There's a separate Ansible playbook that allows usage of the ``debops.python``
role in a "raw" mode, without fact gathering. This can be used to bootstrap
Python support on a host, so that normal Ansible modules can be used
afterwards:
.. literalinclude:: ../../../../ansible/playbooks/service/python_raw.yml
:language: yaml
Ansible tags
------------
You can use Ansible ``--tags`` or ``--skip-tags`` parameters to limit what
tasks are performed during Ansible run. This can be used after a host was first
configured to speed up playbook execution, when you are sure that most of the
configuration is already in the desired state.
Available role tags:
``role::python``
Main role tag, should be used in the playbook to execute all of the role
tasks as well as role dependencies.
Other resources
---------------
List of other useful resources related to the ``debops.python`` Ansible role:
- Manual pages: :man:`python(1)`, :man:`pip(1)`, :man:`virtualenv(1)`
- `Debian Python Policy`__
- `Python page`__ in Debian Wiki
- `Status of Python 3 packages in Debian`__
- `Debian plans for Python 3`__ article in Linux Weekly News
- `Python page`__ in Ubuntu Wiki
- `Python (programming language)`__ in Wikipedia
- `import antigravity`__
.. __: https://www.debian.org/doc/packaging-manuals/python-policy/
.. __: https://wiki.debian.org/Python
.. __: https://wiki.debian.org/Python/Python3Packages
.. __: https://lwn.net/Articles/642334/
.. __: https://wiki.ubuntu.com/Python
.. __: https://en.wikipedia.org/wiki/Python_(programming_language)
.. __: https://xkcd.com/353/
.. _debops.python:
debops.python
=============
`Python`__ is a popular, dynamic programming language available on GNU/Linux
platforms. Ansible is written in Python and requires Python on remote host for
normal operations.
.. __: https://www.python.org/
The ``debops.python`` Ansible role can be used to manage the Python environment
on a Debian/Ubuntu host. Role supports multiple Python versions installed on
a host at the same time, which is the default practice in Debian.
A special "raw" mode of operation with a separate Ansible playbook can be used
to bootstrap Python environment on a host, so that Ansible can then install
packages and operate normally.
.. toctree::
:maxdepth: 2
getting-started
defaults
Copyright
---------
.. literalinclude:: ../../../../ansible/roles/debops.python/COPYRIGHT
..
Local Variables:
mode: rst
ispell-local-dictionary: "american"
End:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment