How to Install python packages on a virtualenv using Ansible?

Question:

I am not able to launch gunicorn I am getting this error

error:

fatal: [172.105.102.110]: FAILED! => {
   "changed":false,
   "cmd":"/myproject/myprojectenv/bin/gunicorn -D --chdir /myproject --error-logfile /root/.ansible/tmp/ansible-tmp-1593463703.788082-353660-248038870081082/gunicorn.temp.error.log --pid /root/.ansible/tmp/ansible-tmp-1593463703.788082-353660-248038870081082/gunicorn.temp.pid wsgi",
   "msg":"[Errno 2] No such file or directory: b'/myproject/myprojectenv/bin/gunicorn'",
   "rc":2
}

do_tutorial.yml

---
- hosts: DigitialOceanExample
  become: yes
  tasks: 
  - name: Update apt-get repo and cache
    apt: 
      update_cache: yes 
      force_apt_get: yes 
      cache_valid_time: 3600

  - name: Install a list of packages
    apt:
      pkg:
      - python3-pip
      - python3-dev
      - build-essential
      - libssl-dev
      - libffi-dev
      - python3-setuptools
      - python3-venv

  - name: ensure a directory exists or create it
    file: 
      path: /myproject
      state: directory

  - name: Manually create the initial virtualenv
    command:
      cmd: python3 -m venv /myproject/myprojectenv
      creates: "/myproject/myprojectenv"

  - name: "install python packages with the local instance of pip"
    shell: "pip3 install wheel flask gunicorn"

  - name: copy file to server
    copy: 
      src: "{{ item }}"
      dest: /myproject
    loop:
      - ./myproject.py

  - name: Install ufw
    apt:
      name: ufw
      update_cache: true

  - name: "Allow port 5000"
    shell:  "ufw allow 5000"

  - name: copy file to server
    copy: 
      src: ./wsgi.py
      dest: /myproject 

  # - name: "starting gunicorn"
  #   shell: "gunicorn --bind 0.0.0.0:5000 wsgi:app"

  - name: run gunicorn on a virtualenv
    gunicorn:
      app: 'wsgi'
      chdir: '/myproject'
      venv: '/myproject/myprojectenv'


  

myproject.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

wsgi.py

from myproject import app

if __name__ == "__main__":
    app.run()

hosts

[DigitialOceanExample]
PPP.PPP.PPP.PPP (redacted for StackOverFlow question)

command

ansible-playbook -i inventory  do_tutorial.yml 

I am trying to replicate this tutorial using Ansible but I am getting an error with my virtualenv

Answers:

I think you are installing with global pip instead of inside your virtual env.
Try with absolute path of pip3 in your newly created venv:

  - name: "install python packages with the local instance of pip"
    shell: "/myproject/myprojectenv/bin/pip3 install wheel flask gunicorn"
Answered By: Marsu

The above example given by Marsu works fine.

Just in case if anyone wants to execute the playbook on remote machine via Jenkins job, then you need to switch to the absolute path first and afterwards install the packages or requirements.txt

For example:

  - name: "install python packages with the local instance of pip"
shell: "cd /myproject && myprojectenv/bin/pip3 install -r requirements.txt"
Answered By: RaghuCK
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.