F5Networks / f5-ansible

Imperative Ansible modules for F5 BIG-IP products
GNU General Public License v3.0
377 stars 233 forks source link

Using environment variables for provider info no longer works, getting "unable to convert to str: 'None'" #2440

Open jagibson opened 3 days ago

jagibson commented 3 days ago
COMPONENT NAME

All F5 modules tried. Examples:

Environment

  environment:
    F5_SERVER: "{{ my.f5.here }}"
    F5_USER: "{{ ansible_user }}"
    F5_PASSWORD: "{{ ansible_password }}"
    F5_VALIDATE_CERTS: false
    F5_SERVER_PORT: "443"
ANSIBLE VERSION
ansible --version
ansible [core 2.16.13]
  config file = /my/homedir/git/ansible/roles/my_rolename/tests/ansible.cfg
  configured module search path = ['/my/homedir/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /my/homedir/git/ansible/roles/my_rolename/.venv/lib/python3.10/site-packages/ansible
  ansible collection location = /my/homedir/git/ansible/roles/my_rolename/tests/collections/ansible_collections
  executable location = /my/homedir/git/ansible/roles/my_rolename/.venv/bin/ansible
  python version = 3.10.15 (main, Sep  7 2024, 00:20:06) [Clang 15.0.0 (clang-1500.3.9.4)] (/my/homedir/git/ansible/roles/my_rolename/.venv/bin/python3.10)
  jinja version = 3.1.4
  libyaml = True
BIGIP VERSION
# tmsh show sys version

Sys::Version
Main Package
  Product     BIG-IP
  Version     15.1.10.3
  Build       0.0.12
  Edition     Point Release 3
  Date        Wed Nov 15 11:32:44 PST 2023
CONFIGURATION
cat ansible.cfg
[defaults]
inventory = ./inventory
collections_path = ./collections/ansible_collections

Running from venv ANSIBLE_PYTHON_INTERPRETER=$(which python) ansible-playbook test.yml

OS / ENVIRONMENT

macOS 15.0.1 (Apple Silicon) virtualenv with python 3.10.15

pip list
Package      Version
------------ -------
ansible-core 2.16.13
cffi         1.17.1
cryptography 43.0.3
Jinja2       3.1.4
MarkupSafe   3.0.2
packaging    24.2
pip          24.2
pycparser    2.22
PyYAML       6.0.2
resolvelib   1.0.1
setuptools   74.1.2
ansible-galaxy collection list

# /my/homedir/git/ansible/roles/my_rolename/tests/collections/ansible_collections
Collection            Version
--------------------- -------
ansible.netcommon     7.1.0  
ansible.utils         5.1.2  
f5networks.f5_modules 1.32.1 
SUMMARY

When I try to use the environment variables (see environment above) for the provider info instead of specifying the provider yaml, I get errors like

fatal: [my.f5.here]: FAILED! => {"changed": false, "msg": "argument 'server' is of type <class 'NoneType'> found in 'provider'. and we were unable to convert to str: 'None' is not a string and conversion is not allowed"}

It seems like the environment variables no longer work. This is inconvenient because now I have to specify the provider config for every single task.

I was able to get the environment variables to work using older code, but I can't find the right combination of Ansible/f5networks.f5_modules again easily.

STEPS TO REPRODUCE
---
- hosts: f5dev
  connection: local
  become: false
  gather_facts: false
  vars:
    ansible_host: "{{ inventory_hostname }}"
    ansible_user: "admin"
    ansible_password: "*******"
    f5_partition: "LOCAL_ONLY"
    f5_check_interval: 300
  environment:
    F5_SERVER: "my.f5.here"
    F5_USER: "{{ ansible_user }}"
    F5_PASSWORD: "{{ ansible_password }}"
    F5_VALIDATE_CERTS: false
    F5_SERVER_PORT: "443"
  tasks:
    - name: panther http monitor
      f5networks.f5_modules.bigip_monitor_http:
        name: "http_monitor"
        description: "HTTP monitor"
        interval: "{{ f5_check_interval }}"
        receive: ""
        timeout: "{{ f5_check_interval + 10 }}"
        partition: "{{ f5_partition }}"
        ### uncomment below and it will work ###
        # provider:
        #   server: "{{ ansible_host }}"
        #   password: "{{ ansible_password }}"
        #   # user: "{{ ansible_user }}"
        #   no_f5_teem: true
        #   validate_certs: false
        state: present
      tags: monitor
cat inventory
[f5dev]
my.f5.here

Run with ANSIBLE_PYTHON_INTERPRETER=$(which python) ansible-playbook test.yml

EXPECTED RESULTS

Ansible to run using the environment variables.

ACTUAL RESULTS

Fails with message

"msg": "argument 'server' is of type <class 'NoneType'> found in 'provider'. and we were unable to convert to str: 'None' is not a string and conversion is not allowed"
PLAY [f5dev] **********************************************************************************************************************************

TASK [http monitor] *******************************************************************************************************************
fatal: [my.f5.here]: FAILED! => {"changed": false, "msg": "argument 'server' is of type <class 'NoneType'> found in 'provider'. and we were unable to convert to str: 'None' is not a string and conversion is not allowed"}

PLAY RECAP ************************************************************************************************************************************
my.f5.here : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

❯ ANSIBLE_PYTHON_INTERPRETER=$(which python) ansible-playbook test.yml --tags monitor -vvv
ansible-playbook [core 2.16.13]
  config file = /my/homedir/git/ansible/roles/my_rolename/tests/ansible.cfg
  configured module search path = ['/my/homedir/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /my/homedir/git/ansible/roles/my_rolename/.venv/lib/python3.10/site-packages/ansible
  ansible collection location = /my/homedir/git/ansible/roles/my_rolename/tests/collections/ansible_collections
  executable location = /my/homedir/git/ansible/roles/my_rolename/.venv/bin/ansible-playbook
  python version = 3.10.15 (main, Sep  7 2024, 00:20:06) [Clang 15.0.0 (clang-1500.3.9.4)] (/my/homedir/git/ansible/roles/my_rolename/.venv/bin/python3.10)
  jinja version = 3.1.4
  libyaml = True
Using /my/homedir/git/ansible/roles/my_rolename/tests/ansible.cfg as config file
host_list declined parsing /my/homedir/git/ansible/roles/my_rolename/tests/inventory as it did not pass its verify_file() method
script declined parsing /my/homedir/git/ansible/roles/my_rolename/tests/inventory as it did not pass its verify_file() method
auto declined parsing /my/homedir/git/ansible/roles/my_rolename/tests/inventory as it did not pass its verify_file() method
Parsed /my/homedir/git/ansible/roles/my_rolename/tests/inventory inventory source with ini plugin
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: test.yml ****************************************************************************************************************************
1 plays in test.yml

PLAY [f5dev] **********************************************************************************************************************************

TASK [http monitor] *******************************************************************************************************************
task path: /my/homedir/git/ansible/roles/my_rolename/tests/test.yml:45
<{{ inventory_hostname }}> ESTABLISH LOCAL CONNECTION FOR USER: username
<{{ inventory_hostname }}> EXEC /bin/sh -c 'echo ~username && sleep 0'
<{{ inventory_hostname }}> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /my/homedir/.ansible/tmp `"&& mkdir "` echo /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023 `" && echo ansible-tmp-1732043683.259428-99731-19617079818023="` echo /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023 `" ) && sleep 0'
Using module file /my/homedir/git/ansible/roles/my_rolename/tests/collections/ansible_collections/f5networks/f5_modules/plugins/modules/bigip_monitor_http.py
<{{ inventory_hostname }}> PUT /my/homedir/.ansible/tmp/ansible-local-997236059_asq/tmpl461sl4g TO /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023/AnsiballZ_bigip_monitor_http.py
<{{ inventory_hostname }}> EXEC /bin/sh -c 'chmod u+x /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023/ /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023/AnsiballZ_bigip_monitor_http.py && sleep 0'
<{{ inventory_hostname }}> EXEC /bin/sh -c 'F5_SERVER=my.f5.here F5_USER=********* F5_PASSWORD='****************' F5_VALIDATE_CERTS=False F5_SERVER_PORT=443 /my/homedir/git/ansible/roles/my_rolename/.venv/bin/python /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023/AnsiballZ_bigip_monitor_http.py && sleep 0'
<{{ inventory_hostname }}> EXEC /bin/sh -c 'rm -f -r /my/homedir/.ansible/tmp/ansible-tmp-1732043683.259428-99731-19617079818023/ > /dev/null 2>&1 && sleep 0'
fatal: [my.f5.here]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "description": "HTTP monitor",
            "interval": 300,
            "ip": null,
            "name": "http_monitor",
            "parent": "/Common/http",
            "partition": "LOCAL_ONLY",
            "port": null,
            "provider": {
                "auth_provider": null,
                "no_f5_teem": false,
                "password": null,
                "server": null,
                "server_port": 443,
                "timeout": null,
                "transport": "rest",
                "user": null,
                "validate_certs": true
            },
            "receive": "",
            "receive_disable": null,
            "reverse": null,
            "send": null,
            "state": "present",
            "target_password": null,
            "target_username": null,
            "time_until_up": null,
            "timeout": 310,
            "up_interval": null
        }
    },
    "msg": "argument 'server' is of type <class 'NoneType'> found in 'provider'. and we were unable to convert to str: 'None' is not a string and conversion is not allowed"
}

PLAY RECAP ************************************************************************************************************************************
my.f5.here : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  
jagibson commented 3 days ago

Also ran with ansible-core 2.17.6. Same result.

pgouband commented 2 days ago

Hi @jagibson,

"{{ my.f5.here }}" is a nested variable so it's parameter here under f5 under my. https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#referencing-nested-variables

With inventory hosts file you shared, you should use:

 environment:
    F5_SERVER: "{{ inventory_hostname }}"