Skip to content
This repository has been archived by the owner on Sep 12, 2022. It is now read-only.

Install pyenv for version control #282

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
([#278](https://github.com/cyverse/clank/pull/278))
- Cleanup email variables, remove unused, change SUPPORT_EMAIL
([#280](https://github.com/cyverse/clank/pull/280))
- Install pyenv for python version management ([#282](https://github.com/cyverse/clank/pull/282))

## [v34-0](https://github.com/cyverse/clank/compare/v33-0...v34-0) - 2018-09-17
### Added
Expand Down
1 change: 0 additions & 1 deletion dist_files/variables.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#1. Required configuration
###############################
WORKSPACE: /opt/dev #NOTE: This is where atmosphere/troposphere directories reside.
VIRTUAL_ENV_DIR: "/opt/env" #NOTE: This is where atmosphere/troposphere virtualenv directories reside.

###
# SECRETS_REPO - This repo should contain the SSH Keys, TLS certificates, and an atmosphere-ansible directory (including hosts file and group_vars directory) that you intend to use when installing Atmosphere.
Expand Down
2 changes: 1 addition & 1 deletion group_vars/atmosphere
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ atmosphere_github_repo: https://github.com/CyVerse/atmosphere.git
atmosphere_github_branch: master
atmosphere_virtualenv_name: atmo
atmosphere_directory_path: "{{workspace}}/{{atmosphere_directory_name}}"
atmosphere_virtualenv_path: "{{ VIRTUAL_ENV_ATMOSPHERE | default(virtualenv_dir+'/'+atmosphere_virtualenv_name) }}"
atmosphere_virtualenv_path: "{{virtualenv_dir}}/{{atmosphere_virtualenv_name}}"
atmosphere_server_name: "{{ server_name }}"
atmosphere_server_url: "https://{{ atmosphere_server_name }}"
atmosphere_uwsgi_processes: 24
Expand Down
4 changes: 3 additions & 1 deletion group_vars/common
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ database_engine: django.db.backends.postgresql_psycopg2
conn_max_age: 60
workspace: "{{WORKSPACE | default('/opt/dev')}}"
secrets_repo: "{{ SECRETS_REPO | default('/opt/dev/clank_workspace/atmo-extras')}}"
virtualenv_dir: "{{VIRTUAL_ENV_DIR | default('/opt/env')}}"
virtualenv_dir: '/opt/env'
github_branch: master
pg_version: 9.6
server_name: "{{ SERVER_NAME | default(ansible_fqdn) }}"
Expand All @@ -14,3 +14,5 @@ install_jenkins: "{{ DJANGO_JENKINS | default(False) }}"
shallow_clone: true
TLS_LETSENCRYPT_TLS_SERVICE: "nginx"
FLOWER_PORT: 5555
PYENV_ROOT: /opt/dev/pyenv
PYTHON_VERSION: 2.7.9
5 changes: 4 additions & 1 deletion playbooks/deploy_atmosphere.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
when: clean_target,
tags: ['dependencies', 'apt-install', 'install'] }

- { role: setup-pyenv,
tags: ['dependencies', 'setup-virtualenv'] }

- { role: setup-postgres,
DB_USER: "{{ ATMO_DBUSER | default(atmosphere_database_user) }}",
DB_VERSION: "{{ pg_version }}",
Expand Down Expand Up @@ -96,7 +99,7 @@
APP_NAME: 'atmosphere',
APP_ENV_VARS: ["DJANGO_SETTINGS_MODULE=atmosphere.settings"],
APP_SRC_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
APP_VIRTUAL_ENV_DIR : "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
APP_VIRTUAL_ENV_DIR : "{{ atmosphere_virtualenv_path }}",
APP_MODULE: "atmosphere.wsgi",
NUM_PROCESSES: "{{ atmosphere_uwsgi_processes | default(16) }}",
AUTORELOAD: "{{ UWSGI_AUTORELOAD | default(false) }}",
Expand Down
3 changes: 3 additions & 0 deletions playbooks/deploy_troposphere.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
when: clean_target,
tags: ['dependencies', 'apt-install', 'install'] }

- { role: setup-pyenv,
tags: ['dependencies', 'setup-virtualenv'] }

- { role: setup-postgres,
DB_USER: "{{ TROPO_DBUSER | default(troposphere_database_user) }}",
DB_VERSION: "{{ pg_version }}",
Expand Down
18 changes: 11 additions & 7 deletions playbooks/setup_atmosphere.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@
GLOB: "*.pyc",
tags: ['atmosphere'] }

- { role: app-install-uwsgi,
INSTALL_ENV: "{{ atmosphere_virtualenv_path }}",
tags: "uwsgi" }

- { role: app-pip-install-requirements,
APP_BASE_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
REQUIREMENTS_FILE_NAME: 'requirements.txt',
USE_PIP_TOOLS_SYNC: False,
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
PIP_EXTRA_ARGS: '--no-binary pycparser',
tags: ['atmosphere', 'pip-install-requirements'],
when: not (INSTALL_DEV_REQUIREMENTS | default(False)) }
Expand All @@ -36,7 +40,7 @@
APP_BASE_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
REQUIREMENTS_FILE_NAME: 'dev_requirements.txt',
USE_PIP_TOOLS_SYNC: False,
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
PIP_EXTRA_ARGS: '--no-binary pycparser',
tags: ['atmosphere', 'pip-install-requirements'],
when: INSTALL_DEV_REQUIREMENTS | default(False) }
Expand All @@ -49,7 +53,7 @@
- { role: app-generate-ini-config,
template_vars: "{{ ATMO }}",
APP_BASE_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
tags: ['atmosphere', 'generate-config'] }

- { role: app-setup-ssh-keys,
Expand All @@ -68,24 +72,24 @@
- { role: app-generate-ini-config,
template_vars: "{{ ATMOSPHERE_ANSIBLE }}",
APP_BASE_DIR: "{{ ANSIBLE_DEPLOY_LOCATION | default(atmosphere_ansible_directory_path) }}",
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_ansible_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
tags: ['atmosphere', 'ansible-deploy'] }

- { role: app-django-manage-collectstatic,
APP_BASE_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
DJANGO_SETTINGS_MODULE: 'atmosphere.settings',
tags: ['atmosphere', 'manage-collectstatic'] }

- { role: app-django-manage-migrate,
APP_BASE_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
DJANGO_SETTINGS_MODULE: 'atmosphere.settings',
tags: ['atmosphere', 'manage-migrate'] }

- { role: app-django-manage-load-tables,
APP_BASE_DIR: "{{ ATMOSPHERE_LOCATION | default(atmosphere_directory_path) }}",
VIRTUAL_ENV: "{{ VIRTUAL_ENV_ATMOSPHERE | default(atmosphere_virtualenv_path) }}",
VIRTUAL_ENV: "{{ atmosphere_virtualenv_path }}",
DJANGO_SETTINGS_MODULE: 'atmosphere.settings',
tags: ['atmosphere','manage-load-tables'] }

Expand Down
4 changes: 4 additions & 0 deletions playbooks/setup_troposphere.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
GLOB: "*.pyc",
tags: ['troposphere'] }

- { role: app-install-uwsgi,
INSTALL_ENV: "{{ VIRTUAL_ENV_TROPOSPHERE | default(troposphere_virtualenv_path) }}",
tags: "uwsgi" }

- { role: app-pip-install-requirements,
APP_BASE_DIR: "{{ TROPOSPHERE_LOCATION | default(troposphere_directory_path) }}",
REQUIREMENTS_FILE_NAME: 'requirements.txt',
Expand Down
13 changes: 13 additions & 0 deletions roles/app-install-uwsgi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ansible-uwsgi

Installs uWSGI

### Role Variables

A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.

| Variable | Required | Default | Choices | Comments |
|-------------------------|----------|---------|---------------------------|--------------------------------------------|
| PYTHON_VERSION | yes | 2.7.9 | Any version number | Controls the version of python to use |
| UWSGI_VERSION | yes | 2.0.15 | Any version number | Controls the version of uWSGI to install |
| INSTALL_ENV | yes | "/usr/local"| | Location to install uwsgi binary |
5 changes: 5 additions & 0 deletions roles/app-install-uwsgi/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

PYTHON_VERSION: "2.7.9"
UWSGI_VERSION: "2.0.15"
INSTALL_ENV: "/usr/local"
54 changes: 54 additions & 0 deletions roles/app-install-uwsgi/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
# We are installing the official uwsgi package to get its init scripts and
# canonical file structure
- name: Install uwsgi package
package:
name: 'uwsgi'
state: 'latest'

- name: Install build dependencies
package:
name: "build-essential"
state: present

- name: Download uWSGI source
unarchive:
src: "https://github.com/unbit/uwsgi/archive/{{ UWSGI_VERSION }}.tar.gz"
dest: "/tmp"
remote_src: True

- name: Build uWSGI core (python version agnostic)
shell: |
export PYENV_ROOT={{ PYENV_ROOT }} \
PATH="{{ PYENV_ROOT }}/bin:$PATH"
eval "$({{ PYENV_ROOT }}/bin/pyenv init -)"
python uwsgiconfig.py --build nolang
args:
chdir: /tmp/uwsgi-{{ UWSGI_VERSION }}

- name: Build uWSGI python plugin for python {{ PYTHON_VERSION }}
shell: |
export PYENV_ROOT={{ PYENV_ROOT }} \
PATH="{{ PYENV_ROOT }}/bin:$PATH" \
PYTHON_CFLAGS=-fPIC \
PYTHON=python
eval "$({{ PYENV_ROOT }}/bin/pyenv init -)"
./uwsgi --build-plugin 'plugins/python python{{ PYTHON_VERSION | replace(".", "")}}'
args:
chdir: "/tmp/uwsgi-{{ UWSGI_VERSION }}"

- name: Reinstall uWSGI to support custom python version
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
remote_src: yes
with_items:
# Instal python-less uWSGI binary
- src: "/tmp/uwsgi-{{ UWSGI_VERSION }}/uwsgi"
dest: "/usr/bin"
mode: "0755"
# Install uWSGI plugin containing python version
- src: "/tmp/uwsgi-{{ UWSGI_VERSION }}/python{{ PYTHON_VERSION | replace(\".\", \"\")}}_plugin.so"
dest: "/usr/lib/uwsgi/plugins"
mode: "0644"
2 changes: 1 addition & 1 deletion roles/app-pip-install-requirements/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
- pip

- name: wheel install requirements
command: "{{ VIRTUAL_ENV_ATMOSPHERE }}/bin/wheel install-scripts {{ item }}"
command: "{{ VIRTUAL_ENV }}/bin/wheel install-scripts {{ item }}"
with_items: "{{ WHEEL_INSTALL_SCRIPT_PACKAGES }}"
when: RUN_WHEEL_SCRIPTS
register: output
Expand Down
2 changes: 2 additions & 0 deletions roles/configure-uwsgi/templates/app.ini.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[uwsgi]
plugins-dir = /usr/lib/uwsgi/plugins
plugin = python{{ PYTHON_VERSION | replace(".", "")}}
check-static = {{ APP_SRC_DIR }}
chdir = {{ APP_SRC_DIR }}
home = {{ APP_VIRTUAL_ENV_DIR }}
Expand Down
3 changes: 1 addition & 2 deletions roles/install-dependencies/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@

- name: Nginx packages installed
package:
name: '{{ item }}'
name: 'nginx-full'
state: 'latest'
with_items: '{{ NGINX_PACKAGES }}'
tags:
- 'install'
- 'apt-install'
Expand Down
5 changes: 0 additions & 5 deletions roles/install-dependencies/vars/Ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,4 @@ LIB_PACKAGES:
- python-tk
- zlib1g-dev

NGINX_PACKAGES:
- uwsgi
- uwsgi-plugin-python
- nginx-full

APACHE: apache2
34 changes: 34 additions & 0 deletions roles/setup-pyenv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
setup-pyenv
=========

Install [pyenv](https://github.com/pyenv/pyenv) for python version control.

Role Variables
--------------

| Variable | Required | Default | Choices | Comments |
|----------------|----------|--------------|---------|-----------------------------------------------------------|
| PYTHON_VERSION | no | 2.7.9 | | The version of python to install and set as global python |
| PYENV_ROOT | no | /root/.pyenv | | The directory where pyenv will live |

Dependencies
------------
None.

Example Playbook
----------------

```
---

- name: Install pyenv
remote_user: root
hosts: localhost
roles:
- setup-pyenv
```

Author Information
------------------

https://cyverse.org
4 changes: 4 additions & 0 deletions roles/setup-pyenv/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---

PYTHON_VERSION: 2.7.9
PYENV_ROOT: /root/.pyenv
55 changes: 55 additions & 0 deletions roles/setup-pyenv/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---

- name: OS-specific variables gathered
include_vars: '{{ item }}'
with_first_found:
- files:
- '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml'
- '{{ ansible_distribution }}.yml'
- '{{ ansible_os_family }}.yml'
skip: true
tags: 'vars'

- name: Install pyenv dependencies
package:
name: "{{ PYENV_DEPENDENCIES }}"
state: present
when: PYENV_DEPENDENCIES is defined

- name: Clone pyenv
git:
repo: https://github.com/pyenv/pyenv.git
dest: "{{ PYENV_ROOT }}"
clone: yes
depth: 1
update: yes

- name: Add pyenv to path using ~/.bashrc
blockinfile:
path: "/root/.bashrc"
state: present
marker: "# {mark} ANSIBLE MANAGED BLOCK"
insertafter: "EOF"
block: |
export PYENV_ROOT={{ PYENV_ROOT }}
export PATH="{{ PYENV_ROOT }}/bin:$PATH"
eval "$(pyenv init -)"

# It's not clear to me why we need the PIC compilation flag, if it's
# absent then we're unable to build the shared object python version
# used by uwsgi in roles/app-install-uwsgi. Exact error and solution
# found here: https://stackoverflow.com/a/38863007/1213041
- name: Build python {{ PYTHON_VERSION }} with support for linking
shell: |
export PYENV_ROOT={{ PYENV_ROOT }} \
PATH="{{ PYENV_ROOT }}/bin:$PATH" \
PYTHON_CFLAGS=-fPIC
eval "$(pyenv init -)"
pyenv install --skip-existing {{ PYTHON_VERSION }}

- name: Set pyenv global python version to {{ PYTHON_VERSION }}
shell: |
export PYENV_ROOT={{ PYENV_ROOT }}
export PATH="{{ PYENV_ROOT }}/bin:$PATH"
eval "$(pyenv init -)"
pyenv global {{ PYTHON_VERSION }}
19 changes: 19 additions & 0 deletions roles/setup-pyenv/vars/Ubuntu-18.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---

PYENV_DEPENDENCIES:
- make
- build-essential
- zlib1g-dev
- libbz2-dev
- libreadline-dev
- libsqlite3-dev
- wget
- curl
- llvm
- libncurses5-dev
- libncursesw5-dev
- xz-utils
- tk-dev
- libffi-dev
- liblzma-dev
- libssl1.0-dev
14 changes: 8 additions & 6 deletions roles/setup-virtualenv/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
state: absent
when: REINSTALL | default(False)

- name: Create virtualenv
command: virtualenv {{ VIRTUAL_ENV_FULL_PATH }} creates="{{ VIRTUAL_ENV_FULL_PATH }}"
register: output

- debug: var=output.stdout_lines
when: CLANK_VERBOSE | default(False)
- name: Create pyenv virtualenv {{ VIRTUAL_ENV_FULL_PATH }}
shell: |
export PYENV_ROOT={{ PYENV_ROOT }} \
PATH="{{ PYENV_ROOT }}/bin:$PATH"
eval "$(pyenv init -)"
virtualenv -p $({{ PYENV_ROOT }}/bin/pyenv which python) {{ VIRTUAL_ENV_FULL_PATH }}
args:
creates: "{{ VIRTUAL_ENV_FULL_PATH }}"
2 changes: 0 additions & 2 deletions roles/setup-virtualenv/vars/main.yml

This file was deleted.