Ansible python interpreter

Hi All,
I am trying to execute an ansible playbook using github actions but it is failing with the below error:
“Failed to import the required Python library (psycopg2) on fv-az1811-354’s Python /opt/pipx/venvs/ansible-core/bin/python. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter”

Below is the playbook i am using:

  • name: Install SQL scripts on Private PostgreSQL Instance
    hosts: localhost
    gather_facts: no
    become: yes

    tasks:

    • name: Install required python packages
      apt:
      name:
      - libpq-dev
      - python3-psycopg2

    • name: List SQL files to be executed
      find:
      paths: DDL/
      file_type: file
      recurse: yes
      patterns: “*.sql”
      age: “-1d”
      register: files_matched

    • name: Connect to SQL instance
      ignore_errors: true
      loop: “{{ files_matched.files|flatten(levels=1) }}”
      loop_control:
      label: “{{ item.path }}”
      community.postgresql.postgresql_script:
      db: “{{ db_name }}”
      login_host: “{{ ansible_host }}”
      login_password: “{{ db_password }}”
      login_user: “{{ db_user }}”
      port: “5432”
      path: “{{ item.path }}”
      encoding: UTF-8

Below is my github action pipeline.yaml:

name: Ansible Shared CI/CD pipeline DEV

on:
workflow_call:
inputs:
DB_NAME:
required: true
type: string
DB_INSTANCE_NAME:
required: true
type: string
DB_HOST:
required: true
type: string
DB_USER:
required: true
type: string
GCP_PROJECT:
required: true
type: string
SCRIPT_PATH:
required: true
type: string
DB_INSTANCE_LOCATION:
required: true
type: string

env:
DB_INSTANCE_NAME: ${{ inputs.DB_INSTANCE_NAME }}
DB_NAME: ${{ inputs.DB_NAME }}
DB_HOST: ${{ inputs.DB_HOST }}
DB_USER: ${{ inputs.DB_USER }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
GCP_PROJECT: ${{ inputs.GCP_PROJECT }}
TOKEN_KEY: ${{ secrets.GH_PAT }}
SCRIPT_PATH: ${{ inputs.SCRIPT_PATH }}
DB_INSTANCE_LOCATION: ${{ inputs.DB_INSTANCE_LOCATION }}
WORKLOAD_IDENTITY_PROVIDER: ${{ vars.DEV_WORKLOAD_IDENTITY_PROVIDER }}
SERVICE_ACCOUNT: ${{ vars.DEV_SERVICE_ACCOUNT }}
TF_TOKEN_app_terraform_io: ${{ secrets.TF_API_TOKEN }}

jobs:
data-prep:
permissions:
contents: ‘read’
id-token: ‘write’
runs-on: ubuntu-latest
if: always()
steps:
- name: Checkout the repo
uses: actions/checkout@v3

  - id: 'auth'
    uses: 'google-github-actions/auth@v1'
    with:
      token_format: 'access_token'
      workload_identity_provider: '${{ env.WORKLOAD_IDENTITY_PROVIDER }}'
      service_account: '${{ env.SERVICE_ACCOUNT }}'
      project_id: '${{ env.GCP_PROJECT }}'

  - name: 'Setup Cloud SDK'
    uses: 'google-github-actions/setup-gcloud@v1'

  - name: 'Create Temporary storage bucket'
    run: |
      gcloud config set project ${{ env.GCP_PROJECT }}
      gcloud storage buckets create gs://${{ github.sha }} 

  - name: Copy Artifacts to bucket
    run: |
      gsutil -m cp -r . gs://${{ github.sha }}

playbook-execution:
needs: [“data-prep”]
permissions:
contents: ‘read’
id-token: ‘write’
runs-on: ubuntu-latest
if: always()
steps:
- name: Checkout the repo
uses: actions/checkout@v3
with:
repository: brtspd/ansible-repo
ref: refs/heads/master
token: ${{ env.TOKEN_KEY }}

  - id: 'auth'
    uses: 'google-github-actions/auth@v1'
    with:
      token_format: 'access_token'
      workload_identity_provider: '${{ env.WORKLOAD_IDENTITY_PROVIDER }}'
      service_account: '${{ env.SERVICE_ACCOUNT }}'
      project_id: '${{ env.GCP_PROJECT }}'

  - name: 'Setup Cloud SDK'
    uses: 'google-github-actions/setup-gcloud@v1'


  - name: Download artifacts from bucket
    run: |
      gcloud config set project ${{ env.GCP_PROJECT }}
      gsutil -m cp -r gs://${{ github.sha }}/* .


  - name: List files
    run: |
      ls -lrt

  - name: 'Setup Ansible'
    run: |
      sudo apt update
      sudo apt install -y software-properties-common
      sudo add-apt-repository --yes --update ppa:ansible/ansible
      sudo apt install -y ansible

  - name: 'Which python'
    run: |
      which python3
      which ansible-playbook
      ansible-playbook --version

  - name: 'Setup Ansible collection'
    run: |
      ansible-galaxy collection install community.postgresql

  - name: 'Setup cloudSQL proxy'
    run: |
      curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.13.0/cloud-sql-proxy.linux.amd64
      chmod +x cloud-sql-proxy

  - name: 'Start cloudSQL proxy'
    run: |
      nohup ./cloud-sql-proxy --private-ip --port 5432 "${{ env.GCP_PROJECT }}":"${{ env.DB_INSTANCE_LOCATION }}":"${{ env.DB_NAME }}" &

  - name: 'Check if proxy is running'
    run: |
      ps -ef | grep "proxy" | head


  - name: 'Run ansible playbook'
    run: |
      ansible-playbook postgres-deployment.yaml -e db_name="${{ env.DB_NAME }}" -e ansible_host="${{ env.DB_HOST }}" -e db_user="${{ env.DB_USER }}" -e db_password="${{ env.DB_PASSWORD }}"

  - name: 'Stop cloudSQL proxy'
    run: |
      pid=$(ps -ef | grep "proxy" | head -1 | awk -F" " '{print $2}')
      sudo kill -9 "$pid"
      exit 0;
      
  - name: Delete storage bucket
    if: always()
    run: |
      gcloud config set project ${{ env.GCP_PROJECT}}
      gcloud storage rm -r gs://${{ github.sha }}

Below is the snippet of the ansible config:

How do i fix this issue?

The problem is that you are running the modules in a venv (the error message provides you with its path: /opt/pipx/venvs/ansible-core), while you install the required Python module for the OS Python interpreter (with the apt module). Thus the module cannot find it.

You need to use the OS’s Python interpreter for this task (or the whole playbook), so it can make use of the installed psycopg2 Python module.

1 Like

Hi felix,
How do I fix it? I am sorry i am new to ansible…

Hi. You can fix it by installing the “required python packages” in your venv with pip.

---
- name: Install SQL scripts on Private PostgreSQL Instance
  hosts: localhost
  gather_facts: true
  become: true

  tasks:
    - name: Install required python packages
      ansible.builtin.pip:
       name:
         - libpq-dev
         - python3-psycopg2
       virtualenv: "{{ ansible_facts['env']['VIRTUAL_ENV'] }}"
       state: present

The other option is to set the python interpreter to your OS python interpreter, as pointed out by @felixfontein:

---
- name: Install SQL scripts on Private PostgreSQL Instance
  hosts: localhost
  gather_facts: false
  become: true
  vars:
     ansible_python_interpreter: "/usr/bin/python3"