Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: systemglobal_authenticationtacacspolicy_binding module idempotency issue #353

Closed
robbccie opened this issue Jan 25, 2024 · 5 comments
Assignees
Labels

Comments

@robbccie
Copy link

robbccie commented Jan 25, 2024

Summary

systemglobal_authenticationtacacspolicy_binding module will always return changed - despite policy being present

Issue Type

Bug Report

Component Name

systemglobal_authenticationtacacspolicy_binding

Python Version

$ python --version # or python3 --version
Python 3.10.12

Ansible Version

$ ansible --version
ansible [core 2.16.2]

Ansible Configuration

$ ansible-config dump --only-changed

netscaler.adc Collection Version

$ ansible-galaxy collection list netscaler.adc
netscaler.adc 2.4.0  

Target NetScaler Version

> show ns version
 NetScaler NS13.1: Build 49.13.nc

Equivalent NetScaler CLI Command

bind system global dfw02-ise-psn01 -priority 50

Steps to Reproduce

Add policy that is already defined in system and check debug.
Debug shows url using an additional / forward slash between binding/?filter which does not resolve in the api and returns No such argument [arguid]

https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding/?filter=policyname:dfw02-ise-psn01

instead of correct url:

https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding?filter=policyname:dfw02-ise-psn01

Example debug output:
"DEBUG: fetch_url()-resonse-info={'url': 'https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding/?filter=policyname:dfw02-ise-psn01', 'status': 400, 'date': 'Thu, 25 Jan 2024 06:06:37 GMT', 'server': 'Apache', 'x-frame-options': 'SAMEORIGIN', 'expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', 'pragma': 'no-cache', 'vary': 'Accept-Encoding', 'feature-policy': "camera 'none'; microphone 'none'; geolocation 'none'", 'referrer-policy': 'no-referrer', 'x-xss-protection': '1; mode=block', 'x-content-type-options': 'nosniff', 'content-length': '82', 'connection': 'close', 'content-type': 'application/json; charset=utf-8', 'msg': 'HTTP Error 400: Bad Request', 'body': b'{ "errorcode": 1090, "message": "No such argument [arguid]", "severity": "ERROR" }'}",
"TRACE: EXIT: send() returned (400, {'errorcode': 1090, 'message': 'No such argument [arguid]', 'severity': 'ERROR'})",
"TRACE: EXIT: get() returned (400, {'errorcode': 1090, 'message': 'No such argument [arguid]', 'severity': 'ERROR'})",
"TRACE: EXIT: get_resource() returned []",
"TRACE: EXIT: get_existing_resource() returned {}",

Expected Results

Return OK

Actual Results

Return Changed

Additioinal Notes

full debug output:
ok: [lbhostname] => {
"msg": {
"changed": true,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"diff": {
"after": {
"feature": "SYSTEM",
"globalbindtype": "SYSTEM_GLOBAL",
"policyname": "dfw02-ise-psn01",
"priority": 50.0
},
"before": {}
},
"failed": false,
"invocation": {
"module_args": {
"api_path": "nitro/v1/config",
"builtin": null,
"feature": "SYSTEM",
"globalbindtype": "SYSTEM_GLOBAL",
"gotopriorityexpression": null,
"nextfactor": null,
"nitro_auth_token": null,
"nitro_pass": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"nitro_protocol": "https",
"nitro_user": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"nsip": "lbhostname",
"policyname": "dfw02-ise-psn01",
"priority": 50.0,
"save_config": true,
"state": "present",
"validate_certs": false
}
},
"item": {
"feature": "SYSTEM",
"globalbindtype": "SYSTEM_GLOBAL",
"policyname": "dfw02-ise-psn01",
"priority": 50
},
"loglines": [
"DEBUG: Initializing ModuleExecutor for resource systemglobal_authenticationtacacspolicy_binding",
"TRACE: ENTRY: get_valid_desired_states() called with ('systemglobal_authenticationtacacspolicy_binding',), {}",
"TRACE: EXIT: get_valid_desired_states() returned {'absent', 'present'}",
"TRACE: ENTRY: get_netscaler_version() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {}",
"TRACE: ENTRY: get_resource() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'nsversion'), {}",
"TRACE: ENTRY: get() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {'resource': 'nsversion', 'id': None, 'args': None, 'attrs': None, 'filter': None}",
"TRACE: ENTRY: url_builder() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'nsversion'), {'id': None, 'args': None, 'attrs': None, 'filter': None}",
"TRACE: EXIT: url_builder() returned https://lbhostname/nitro/v1/config/nsversion",
"TRACE: ENTRY: send() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'GET', 'https://lbhostname/nitro/v1/config/nsversion'), {}",
"DEBUG: self={'_module': <ansible.module_utils.basic.AnsibleModule object at 0x7f5024868e80>, 'check_mode': True, 'api_path': 'nitro/v1/config', '_headers': {'Content-Type': 'application/json', 'User-Agent': 'ansible-ctxadc', 'X-NITRO-USER': '', 'X-NITRO-PASS': ''}}",
"DEBUG: fetch_url()-resonse-info={'url': 'https://lbhostname/nitro/v1/config/nsversion', 'status': 200, 'date': 'Thu, 25 Jan 2024 06:06:36 GMT', 'server': 'Apache', 'x-frame-options': 'SAMEORIGIN', 'expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', 'pragma': 'no-cache', 'vary': 'Accept-Encoding', 'feature-policy': "camera 'none'; microphone 'none'; geolocation 'none'", 'referrer-policy': 'no-referrer', 'x-xss-protection': '1; mode=block', 'x-content-type-options': 'nosniff', 'content-length': '201', 'content-type': 'application/json; charset=utf-8', 'connection': 'close', 'cookies_string': '', 'cookies': {}, 'msg': 'OK (201 bytes)'}",
"TRACE: EXIT: send() returned (200, {'errorcode': 0, 'message': 'Done', 'severity': 'NONE', 'nsversion': {'installedversion': False, 'version': 'NetScaler NS13.1: Build 49.13.nc, Date: Jul 10 2023, 12:00:59 (64-bit)', 'mode': '1'}})",
"TRACE: EXIT: get() returned (200, {'errorcode': 0, 'message': 'Done', 'severity': 'NONE', 'nsversion': {'installedversion': False, 'version': 'NetScaler NS13.1: Build 49.13.nc, Date: Jul 10 2023, 12:00:59 (64-bit)', 'mode': '1'}})",
"TRACE: EXIT: get_resource() returned [{'installedversion': False, 'version': 'NetScaler NS13.1: Build 49.13.nc, Date: Jul 10 2023, 12:00:59 (64-bit)', 'mode': '1'}]",
"TRACE: EXIT: get_netscaler_version() returned (13.1, 49.13)",
"INFO: NetScaler version: 13.1-49.13",
"DEBUG: All params (including non module-specific params) are: {'nsip': 'lbhostname', 'nitro_user': '', 'nitro_pass': '', 'nitro_protocol': 'https', 'validate_certs': False, 'save_config': True, 'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM', 'state': 'present', 'api_path': 'nitro/v1/config', 'nitro_auth_token': None, 'builtin': None, 'gotopriorityexpression': None, 'nextfactor': None}",
"TRACE: ENTRY: _filter_resource_module_params() called with (<ansible_collections.netscaler.adc.plugins.module_utils.module_executor.ModuleExecutor object at 0x7f5024868310>,), {}",
"DEBUG: self.module.params: {'nsip': 'lbhostname', 'nitro_user': '', 'nitro_pass': '', 'nitro_protocol': 'https', 'validate_certs': False, 'save_config': True, 'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM', 'state': 'present', 'api_path': 'nitro/v1/config', 'nitro_auth_token': None, 'builtin': None, 'gotopriorityexpression': None, 'nextfactor': None}",
"DEBUG: k: nsip, v: lbhostname",
"DEBUG: k: nitro_user, v: ",
"DEBUG: k: nitro_pass, v: ",
"DEBUG: k: nitro_protocol, v: https",
"DEBUG: k: validate_certs, v: False",
"DEBUG: k: save_config, v: True",
"DEBUG: k: policyname, v: dfw02-ise-psn01",
"DEBUG: k: globalbindtype, v: SYSTEM_GLOBAL",
"DEBUG: k: priority, v: 50.0",
"DEBUG: k: feature, v: SYSTEM",
"DEBUG: k: state, v: present",
"DEBUG: k: api_path, v: nitro/v1/config",
"DEBUG: k: nitro_auth_token, v: None",
"DEBUG: k: builtin, v: None",
"DEBUG: k: gotopriorityexpression, v: None",
"DEBUG: k: nextfactor, v: None",
"DEBUG: Desired systemglobal_authenticationtacacspolicy_binding module specific params are: {'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM'}",
"TRACE: EXIT: _filter_resource_module_params() returned None",
"TRACE: ENTRY: get_existing_resource() called with (<ansible_collections.netscaler.adc.plugins.module_utils.module_executor.ModuleExecutor object at 0x7f5024868310>,), {}",
"TRACE: ENTRY: get_resource() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {'resource_name': 'systemglobal_authenticationtacacspolicy_binding', 'resource_id': '', 'args': {}, 'filter': {'policyname': 'dfw02-ise-psn01'}}",
"TRACE: ENTRY: get() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {'resource': 'systemglobal_authenticationtacacspolicy_binding', 'id': '', 'args': {}, 'attrs': None, 'filter': {'policyname': 'dfw02-ise-psn01'}}",
"TRACE: ENTRY: url_builder() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'systemglobal_authenticationtacacspolicy_binding'), {'id': '', 'args': {}, 'attrs': None, 'filter': {'policyname': 'dfw02-ise-psn01'}}",
"TRACE: EXIT: url_builder() returned https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding/?filter=policyname:dfw02-ise-psn01",
"TRACE: ENTRY: send() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'GET', 'https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding/?filter=policyname:dfw02-ise-psn01'), {}",
"DEBUG: self={'_module': <ansible.module_utils.basic.AnsibleModule object at 0x7f5024868e80>, 'check_mode': True, 'api_path': 'nitro/v1/config', '_headers': {'Content-Type': 'application/json', 'User-Agent': 'ansible-ctxadc', 'X-NITRO-USER': '', 'X-NITRO-PASS': '
'}}",
"DEBUG: fetch_url()-resonse-info={'url': 'https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding/?filter=policyname:dfw02-ise-psn01', 'status': 400, 'date': 'Thu, 25 Jan 2024 06:06:37 GMT', 'server': 'Apache', 'x-frame-options': 'SAMEORIGIN', 'expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', 'pragma': 'no-cache', 'vary': 'Accept-Encoding', 'feature-policy': "camera 'none'; microphone 'none'; geolocation 'none'", 'referrer-policy': 'no-referrer', 'x-xss-protection': '1; mode=block', 'x-content-type-options': 'nosniff', 'content-length': '82', 'connection': 'close', 'content-type': 'application/json; charset=utf-8', 'msg': 'HTTP Error 400: Bad Request', 'body': b'{ "errorcode": 1090, "message": "No such argument [arguid]", "severity": "ERROR" }'}",
"TRACE: EXIT: send() returned (400, {'errorcode': 1090, 'message': 'No such argument [arguid]', 'severity': 'ERROR'})",
"TRACE: EXIT: get() returned (400, {'errorcode': 1090, 'message': 'No such argument [arguid]', 'severity': 'ERROR'})",
"TRACE: EXIT: get_resource() returned []",
"TRACE: EXIT: get_existing_resource() returned {}",
"TRACE: ENTRY: main() called with (<ansible_collections.netscaler.adc.plugins.module_utils.module_executor.ModuleExecutor object at 0x7f5024868310>,), {}",
"TRACE: ENTRY: create_or_update() called with (<ansible_collections.netscaler.adc.plugins.module_utils.module_executor.ModuleExecutor object at 0x7f5024868310>,), {}",
"TRACE: ENTRY: update_diff_list() called with (<ansible_collections.netscaler.adc.plugins.module_utils.module_executor.ModuleExecutor object at 0x7f5024868310>,), {'existing': {}, 'desired': {'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM'}}",
"TRACE: EXIT: update_diff_list() returned None",
"INFO: Resource systemglobal_authenticationtacacspolicy_binding: does not exist. Will be CREATED.",
"TRACE: ENTRY: create_resource() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'systemglobal_authenticationtacacspolicy_binding', {'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM'}), {}",
"TRACE: ENTRY: _check_create_resource_params() called with ('systemglobal_authenticationtacacspolicy_binding', {'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM'}), {}",
"TRACE: ENTRY: change_primary_key() called with ('systemglobal_authenticationtacacspolicy_binding', {'policyname': 'dfw02-ise-psn01', 'globalbindtype': 'SYSTEM_GLOBAL', 'priority': 50.0, 'feature': 'SYSTEM'}, ''), {}",
"TRACE: EXIT: change_primary_key() returned ",
"WARNING: Key globalbindtype is not allowed for the resource systemglobal_authenticationtacacspolicy_binding for CREATE operation. Skipping the key for the operation",
"WARNING: Key feature is not allowed for the resource systemglobal_authenticationtacacspolicy_binding for CREATE operation. Skipping the key for the operation",
"TRACE: EXIT: _check_create_resource_params() returned (True, None, {'policyname': 'dfw02-ise-psn01', 'priority': 50.0})",
"TRACE: ENTRY: post() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {'post_data': {'systemglobal_authenticationtacacspolicy_binding': {'policyname': 'dfw02-ise-psn01', 'priority': 50.0}}, 'resource': 'systemglobal_authenticationtacacspolicy_binding', 'action': None}",
"TRACE: ENTRY: url_builder() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'systemglobal_authenticationtacacspolicy_binding'), {'action': None}",
"TRACE: EXIT: url_builder() returned https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding",
"TRACE: ENTRY: send() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'POST', 'https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding', '{"systemglobal_authenticationtacacspolicy_binding": {"policyname": "dfw02-ise-psn01", "priority": 50.0}}'), {}",
"DEBUG: self={'_module': <ansible.module_utils.basic.AnsibleModule object at 0x7f5024868e80>, 'check_mode': True, 'api_path': 'nitro/v1/config', '_headers': {'Content-Type': 'application/json', 'User-Agent': 'ansible-ctxadc', 'X-NITRO-USER': '', 'X-NITRO-PASS': ''}}",
"DEBUG: check_mode is enabled, skipping POST:https://lbhostname/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding request",
"TRACE: EXIT: send() returned (0, {})",
"TRACE: EXIT: post() returned (0, {})",
"TRACE: ENTRY: return_response() called with (), {'status_code': 0, 'response_body': {}, 'operation': 'create_resource', 'resource_name': 'systemglobal_authenticationtacacspolicy_binding'}",
"DEBUG: create_resource systemglobal_authenticationtacacspolicy_binding SUCCESS",
"TRACE: EXIT: return_response() returned (True, {})",
"TRACE: EXIT: create_resource() returned (True, {})",
"TRACE: EXIT: create_or_update() returned None",
"TRACE: ENTRY: save_config() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {}",
"TRACE: ENTRY: post() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>,), {'post_data': {'nsconfig': {}}, 'resource': 'nsconfig', 'action': 'save'}",
"TRACE: ENTRY: url_builder() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'nsconfig'), {'action': 'save'}",
"TRACE: EXIT: url_builder() returned https://lbhostname/nitro/v1/config/nsconfig?action=save",
"TRACE: ENTRY: send() called with (<ansible_collections.netscaler.adc.plugins.module_utils.client.NitroAPIClient object at 0x7f50240203a0>, 'POST', 'https://lbhostname/nitro/v1/config/nsconfig?action=save', '{"nsconfig": {}}'), {}",
"DEBUG: self={'_module': <ansible.module_utils.basic.AnsibleModule object at 0x7f5024868e80>, 'check_mode': True, 'api_path': 'nitro/v1/config', '_headers': {'Content-Type': 'application/json', 'User-Agent': 'ansible-ctxadc', 'X-NITRO-USER': '', 'X-NITRO-PASS': ''}}",
"DEBUG: check_mode is enabled, skipping POST:https://lbhostname/nitro/v1/config/nsconfig?action=save request",
"TRACE: EXIT: send() returned (0, {})",
"TRACE: EXIT: post() returned (0, {})",
"TRACE: ENTRY: return_response() called with (), {'status_code': 0, 'response_body': {}, 'operation': 'save_config', 'resource_name': 'nsconfig'}",
"DEBUG: save_config nsconfig SUCCESS",
"TRACE: EXIT: return_response() returned (True, {})",
"TRACE: EXIT: save_config() returned (True, {})",
"TRACE: ENTRY: return_success() called with (<ansible_collections.netscaler.adc.plugins.module_utils.module_executor.ModuleExecutor object at 0x7f5024868310>,), {}"
]
}
],
"skipped": false
}
}

No response

@robbccie
Copy link
Author

Is there any advice or feedback here? The module doesn't function if the policy is already defined.

@sumanth-lingappa
Copy link
Collaborator

I will look into this soon and update you @robbccie

@sumanth-lingappa
Copy link
Collaborator

@robbccie, can you please help me with the ansible-playbook you are getting this issue?

@robbccie
Copy link
Author

robbccie commented Feb 3, 2024

Hi @sumanth-lingappa , sure thing please see below.

  • name: Test module
    hosts:
    - localhost
    gather_facts: no

    tasks:

    • name: systemglobal_authenticationtacacspolicy_binding api
      delegate_to: localhost
      netscaler.adc.systemglobal_authenticationtacacspolicy_binding:
      nsip: "10.255.241.31"
      nitro_user: "{{ ansible_user }}"
      nitro_pass: "{{ ansible_password }}"
      nitro_protocol: "https"
      validate_certs: false
      state: present
      save_config: false
      feature: "SYSTEM"
      globalbindtype: "SYSTEM_GLOBAL"
      policyname: "dfw02-ise-psn01"
      priority: "10"

The issue seems to be with the additional forward slash when it is looking to filter on the policyname:

"TRACE: EXIT:
url_builder() returned https://10.255.241.31/nitro/v1/config/systemglobal_authenticationtacacspolicy_binding/?filter=policyname:dfw02-ise-psn01",

If I check the API without the forward slash using systemglobal_authenticationtacacspolicy_binding?filter=policyname:dfw02-ise-psn01 it is there.
image

@sumanth-lingappa
Copy link
Collaborator

Thank you for the extensive information. Specially the information regarding the extra /.
It is very rare that the issue-reporter will go one step beyond and tries to solve the bug himself/herself.

Truely appreciate your efforts.

This has been fixed in the above PR.

You can always install the latest unreleased version of netscaler.adc ansible collection via below command

ansible-galaxy collection install "git+https://github.com/netscaler/ansible-collection-netscaleradc.git" --force

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants