Add role to ensure python3 is installed on target host
Change-Id: I3b514f3a3cb1f50ac121ca9d865eb500cf49b975
This commit is contained in:
parent
5f01cdc90a
commit
10c1eda1fc
7
roles/tobiko-ensure-python/defaults/main.yaml
Normal file
7
roles/tobiko-ensure-python/defaults/main.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
|
||||
python_version: '3'
|
||||
python_command: 'python{{ python_version }}'
|
||||
|
||||
unversioned_python_command: '/usr/bin/python'
|
||||
unversioned_python_alternative: '/usr/bin/python3'
|
142
roles/tobiko-ensure-python/files/get_python_info.py
Normal file
142
roles/tobiko-ensure-python/files/get_python_info.py
Normal file
@ -0,0 +1,142 @@
|
||||
# Copyright 2018 Red Hat
|
||||
#
|
||||
# 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.
|
||||
from __future__ import absolute_import
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
GET_PYTHON_VERSION_SCRIPT = """
|
||||
import sys
|
||||
|
||||
version = '.'.join(str(i) for i in sys.version_info[:3])
|
||||
print(version)
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--quiet', '-q',
|
||||
action="store_true",
|
||||
help="mute logging messages from STDERR")
|
||||
parser.add_argument('--base', '-b',
|
||||
action="store_true",
|
||||
help="print Python base prefix")
|
||||
args = parser.parse_args()
|
||||
|
||||
setup_logging(quiet=args.quiet)
|
||||
version = get_python_version()
|
||||
executables = [
|
||||
info['executable']
|
||||
for info in iter_python_executables_info(match_version=version,
|
||||
base=args.base)]
|
||||
info = {'version': version, 'executables': executables}
|
||||
output = json.dumps(info, indent=4, sort_keys=True)
|
||||
print(output)
|
||||
|
||||
|
||||
def setup_logging(quiet=False):
|
||||
if quiet:
|
||||
level = logging.ERROR
|
||||
else:
|
||||
level = logging.DEBUG
|
||||
logging.basicConfig(
|
||||
level=level,
|
||||
stream=sys.stderr,
|
||||
format='%(name)-s: %(levelname)-7s %(asctime)-15s | %(message)s')
|
||||
|
||||
|
||||
def get_python_version():
|
||||
return '.'.join(str(i) for i in sys.version_info[:3])
|
||||
|
||||
|
||||
def iter_python_executables_info(match_version=None, base=None):
|
||||
last_error = None
|
||||
for executable in iter_python_executables(base=base):
|
||||
command = subprocess.list2cmdline(
|
||||
[executable, '-c', GET_PYTHON_VERSION_SCRIPT])
|
||||
try:
|
||||
version = execute(command).splitlines()[0]
|
||||
except subprocess.CalledProcessError:
|
||||
LOG.exception('Unable to get version from script')
|
||||
else:
|
||||
if not match_version or match_version == version:
|
||||
yield {'executable': executable, 'version': version}
|
||||
else:
|
||||
if last_error:
|
||||
raise last_error
|
||||
|
||||
|
||||
def iter_python_executables(base=None):
|
||||
iterated = set()
|
||||
for executable in _iter_python_executables(base=base):
|
||||
# Iterate every executable only once
|
||||
if executable not in iterated:
|
||||
iterated.add(executable)
|
||||
yield executable
|
||||
|
||||
|
||||
def _iter_python_executables(base):
|
||||
if base:
|
||||
base_prefix = getattr(sys, 'base_prefix', None)
|
||||
if base_prefix:
|
||||
for executable in iter_prefix_executables(base_prefix):
|
||||
yield executable
|
||||
|
||||
for executable in iter_prefix_executables(sys.prefix):
|
||||
yield executable
|
||||
|
||||
yield sys.executable
|
||||
|
||||
|
||||
def iter_prefix_executables(prefix):
|
||||
if os.path.isdir(prefix):
|
||||
for python_name in iter_versioned_names():
|
||||
executable = os.path.join(prefix, 'bin', python_name)
|
||||
if os.path.isfile(executable):
|
||||
yield executable
|
||||
|
||||
|
||||
def iter_versioned_names(unversioned=None):
|
||||
unversioned = unversioned or 'python'
|
||||
short_versioned = unversioned + str(sys.version_info[0])
|
||||
long_versioned = '.'.join([short_versioned, str(sys.version_info[1])])
|
||||
yield long_versioned
|
||||
yield short_versioned
|
||||
yield unversioned
|
||||
|
||||
|
||||
def execute(command, *args, **kwargs):
|
||||
if args or kwargs:
|
||||
command = command.format(*args, **kwargs)
|
||||
LOG.debug('%s', command)
|
||||
env = kwargs.get('env', None)
|
||||
return subprocess.check_output(command, shell=True,
|
||||
universal_newlines=True,
|
||||
env=env)
|
||||
|
||||
|
||||
def name_from_path(path):
|
||||
return os.path.splitext(os.path.basename(path))[0]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
LOG = logging.getLogger(name_from_path(__file__))
|
||||
main()
|
4
roles/tobiko-ensure-python/meta/main.yaml
Normal file
4
roles/tobiko-ensure-python/meta/main.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
|
||||
dependencies:
|
||||
- role: tobiko-common
|
102
roles/tobiko-ensure-python/tasks/main.yaml
Normal file
102
roles/tobiko-ensure-python/tasks/main.yaml
Normal file
@ -0,0 +1,102 @@
|
||||
---
|
||||
|
||||
- name: "validate python_version value: {{ python_version }}"
|
||||
assert:
|
||||
that:
|
||||
- (python_version|string).split(".") | length >= 1
|
||||
- (python_version|string).split(".") | length <= 2
|
||||
- (python_version|string).split(".")[0] == '3'
|
||||
|
||||
|
||||
- name: "include OS-specific variables"
|
||||
include_vars: "{{ item }}"
|
||||
ignore_errors: yes
|
||||
with_first_found:
|
||||
- "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yaml"
|
||||
- "{{ ansible_distribution }}.{{ ansible_architecture }}.yaml"
|
||||
- "{{ ansible_distribution }}.yaml"
|
||||
- "{{ ansible_os_family }}.yaml"
|
||||
|
||||
|
||||
- block:
|
||||
- name: "get Python info for '{{ python_command }}'"
|
||||
script:
|
||||
cmd: get_python_info.py --base --quiet
|
||||
executable: '{{ python_command }}'
|
||||
register: get_python_info
|
||||
|
||||
rescue:
|
||||
- name: "install Python {{ python_version }} packages"
|
||||
become: true
|
||||
package:
|
||||
name: "{{ python_packages }}"
|
||||
|
||||
- name: "get Python info for '{{ python_command }}'"
|
||||
script:
|
||||
cmd: get_python_info.py --base --quiet
|
||||
executable: '{{ python_command }}'
|
||||
register: get_python_info
|
||||
|
||||
|
||||
- name: "set python_info fact"
|
||||
set_fact:
|
||||
python_info: '{{ get_python_info.stdout | from_json }}'
|
||||
|
||||
|
||||
- name: "update Python executable facts"
|
||||
set_fact:
|
||||
python_command: '{{ python_info.executables | first | basename }}'
|
||||
python_executable: '{{ python_info.executables | first }}'
|
||||
python_version: '{{ python_info.version }}'
|
||||
|
||||
|
||||
- name: "show Python executables facts"
|
||||
debug:
|
||||
msg:
|
||||
python_command: '{{ python_command }}'
|
||||
python_executable: '{{ python_executable }}'
|
||||
python_info: '{{ python_info }}'
|
||||
python_version: '{{ python_version }}'
|
||||
|
||||
|
||||
- block:
|
||||
- name: "get Python info for '{{ unversioned_python_command }}'"
|
||||
script:
|
||||
cmd: get_python_info.py --base --quiet
|
||||
executable: '{{ unversioned_python_command }}'
|
||||
register: get_unversioned_python_info
|
||||
|
||||
rescue:
|
||||
- name: "set '{{ python_executable }}' as default alternative for python"
|
||||
become: true
|
||||
command: "alternatives --set python '{{ unversioned_python_alternative }}'"
|
||||
|
||||
- name: "get Python info for '{{ unversioned_python_command }}'"
|
||||
script:
|
||||
cmd: get_python_info.py --base --quiet
|
||||
executable: '{{ unversioned_python_command }}'
|
||||
register: get_unversioned_python_info
|
||||
|
||||
|
||||
- name: "set unversioned_python_info fact"
|
||||
set_fact:
|
||||
unversioned_python_info: '{{ get_unversioned_python_info.stdout | from_json }}'
|
||||
|
||||
|
||||
- name: "update unversioned Python executable facts"
|
||||
set_fact:
|
||||
unversioned_python_command:
|
||||
'{{ unversioned_python_info.executables | first | basename }}'
|
||||
unversioned_python_executable:
|
||||
'{{ unversioned_python_info.executables | first }}'
|
||||
unversioned_python_version:
|
||||
'{{ unversioned_python_info.version }}'
|
||||
|
||||
|
||||
- name: "show unversioned Python executables facts"
|
||||
debug:
|
||||
msg:
|
||||
unversioned_python_command: '{{ unversioned_python_command }}'
|
||||
unversioned_python_executable: '{{ unversioned_python_executable }}'
|
||||
unversioned_python_info: '{{ unversioned_python_info }}'
|
||||
unversioned_python_version: '{{ unversioned_python_version }}'
|
18
roles/tobiko-ensure-python/vars/RedHat.yaml
Normal file
18
roles/tobiko-ensure-python/vars/RedHat.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
|
||||
python_command: '/usr/bin/python{{ python_version }}'
|
||||
|
||||
python_package_name: "python{{ python_version | regex_replace('\\.', '') }}"
|
||||
|
||||
python_packages:
|
||||
- bzip2-devel
|
||||
- gcc
|
||||
- make
|
||||
- openssl-devel
|
||||
- readline-devel
|
||||
- sqlite-devel
|
||||
- zlib-devel
|
||||
- '{{ python_package_name }}'
|
||||
- '{{ python_package_name }}-devel'
|
||||
- '{{ python_package_name }}-setuptools'
|
||||
- '{{ python_package_name }}-virtualenv'
|
@ -11,9 +11,9 @@ tox_command_line: >
|
||||
{% if tox_envlist %} -e {{ tox_envlist | quote }} {% endif %}
|
||||
{{ tox_extra_args }}
|
||||
|
||||
tox_python: 'python3'
|
||||
tox_python: '{{ python_executable }}'
|
||||
tox_report_dir: '{{ test_report_dir | realpath }}'
|
||||
tox_report_name: '{{ test_report_name }}_{{ tox_envlist }}'
|
||||
tox_report_name: '{{ test_report_name }}{% if tox_envlist %}_{{ tox_envlist }}{% endif %}'
|
||||
tox_report_env:
|
||||
TOBIKO_TEST_REPORT_DIR: '{{ tox_report_dir }}'
|
||||
TOBIKO_TEST_REPORT_NAME: '{{ tox_report_name }}'
|
||||
|
@ -2,3 +2,4 @@
|
||||
|
||||
dependencies:
|
||||
- role: tobiko-common
|
||||
- role: tobiko-ensure-python
|
||||
|
Loading…
x
Reference in New Issue
Block a user