ansible-collections / ansible.utils

A collection of ansible utilities for the content creator.
GNU General Public License v3.0
75 stars 78 forks source link

validate does not resolve external references #255

Open bk2zsto opened 1 year ago

bk2zsto commented 1 year ago
SUMMARY

The default RefResolver in jsonschema correctly loads references that the validate module does not

ISSUE TYPE
COMPONENT NAME

ansible.utils.validate

ANSIBLE VERSION
ansible [core 2.14.5]
  config file = /home/user/ansible_home/ansible.cfg
  configured module search path = ['/home/user/ansible_home/plugins/modules']
  ansible python module location = /home/user/venv/lib64/python3.11/site-packages/ansible
  ansible collection location = /home/user/ansible_dev/collections:/home/user/ansible_home/collections:/home/user/playbooks/collections
  executable location = /home/user/venv/bin/ansible
  python version = 3.11.3 (main, Apr  5 2023, 00:00:00) [GCC 12.2.1 20221121 (Red Hat 12.2.1-4)] (/home/user/venv/bin/python3)
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
# /home/user/ansible_home/collections/ansible_collections
Collection    Version
------------- -------
ansible.utils 2.9.0

# /home/user/venv/lib/python3.11/site-packages/ansible_collections
Collection    Version
------------- -------
ansible.utils 2.9.0

# /home/user/venv/lib64/python3.11/site-packages/ansible_collections
Collection    Version
------------- -------
ansible.utils 2.9.0
CONFIGURATION
ANSIBLE_HOME(env: ANSIBLE_HOME) = /home/user/ansible_home
BECOME_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/become']
COLLECTIONS_PATHS(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_dev/collections', '/home/user/ansible_home/collections', '/home/user/playbooks/collections']
CONFIG_FILE() = /home/user/ansible_home/ansible.cfg
DEFAULT_ACTION_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/action']
DEFAULT_CACHE_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/cache']
DEFAULT_CALLBACK_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/callback']
DEFAULT_CONNECTION_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/connection']
DEFAULT_FILTER_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/filter']
DEFAULT_HOST_LIST(/home/user/ansible_home/ansible.cfg) = ['/home/user/code/netbox_inventory']
DEFAULT_INVENTORY_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/inventory']
DEFAULT_LOOKUP_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/lookup']
DEFAULT_MODULE_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/modules']
DEFAULT_MODULE_UTILS_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/module_utils']
DEFAULT_ROLES_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/roles']
DEFAULT_STRATEGY_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/strategy']
DEFAULT_TERMINAL_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/terminal']
DEFAULT_TEST_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/test']
DEFAULT_VARS_PLUGIN_PATH(/home/user/ansible_home/ansible.cfg) = ['/home/user/ansible_home/plugins/vars']
INVENTORY_ENABLED(/home/user/ansible_home/ansible.cfg) = ['host_list', 'script', 'auto', 'yaml', 'ini', 'toml', 'constructed']
PERSISTENT_COMMAND_TIMEOUT(/home/user/ansible_home/ansible.cfg) = 120
RETRY_FILES_ENABLED(/home/user/ansible_home/ansible.cfg) = False
RETRY_FILES_SAVE_PATH(/home/user/ansible_home/ansible.cfg) = /home/user/.ansible-retry
OS / ENVIRONMENT

Fedora Remix 37 on WSL

STEPS TO REPRODUCE

https://gist.github.com/bk2zsto/f9df69ed86a5b0558b103bfaab3a63d1

EXPECTED RESULTS

validate loads external references and/or errors when they are not resolved

ACTUAL RESULTS

validate ignores external references


$ python /tmp/debug.py
Validation of 192.0.2.0 failed with combined
Validation of 192.0.2.0 failed with referring

$ ansible-playbook /tmp/debug.yml

PLAY [localhost] *******************************************************************************************************

TASK [setup test_data] *************************************************************************************************
ok: [localhost]

TASK [validate with combined schema] ***********************************************************************************
ok: [localhost] => (item=cidr)
failed: [localhost] (item=not_cidr) => {"ansible_loop_var": "item", "changed": false, "errors": [{"data_path": "network", "expected": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/[0-9]{1,2}", "found": "192.0.2.0", "json_path": "$.network", "message": "'192.0.2.0' does not match '^[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}/[0-9]{1,2}'", "relative_schema": {"$comment": "CIDR, IPv4-only", "pattern": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/[0-9]{1,2}", "type": "string"}, "schema_path": "properties.network.pattern", "validator": "pattern"}], "item": {"name": "not_cidr", "network": "192.0.2.0"}, "msg": "Validation errors were found.\nAt 'properties.network.pattern' '192.0.2.0' does not match '^[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}/[0-9]{1,2}'. "}
...ignoring

TASK [validate with referring schema] **********************************************************************************
ok: [localhost] => (item=cidr)
ok: [localhost] => (item=not_cidr) <==============================

PLAY RECAP *************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1
ryanmerolle commented 1 year ago

I think your problem is that validate does not reference some shared directory to build a schema store for referring to or use a referring approach like you did.

You basically want a new feature to pass a referring schema file or a schema directory.

I gave up on this all and just created a module with jsonschema and jinja template rendering.