Closed izzzhoga closed 1 year ago
Why is this task not idempotent if the initial and final state of the system are the same?
I'll have to check out the sources. It definitely does look wrong...
Did you also run the playbook with --diff
to see whether that prints something?
I launched the playbook with the --diff flag, here is the output:
TASK [1DEV/mkt-config-snmp : Configure SNMP Community and other] **********************************************************
--- before
+++ after
@@ -2,7 +2,7 @@
"values": [
{
".id": "*0",
- "addresses": "xx.xx.xx.xx/32,yy.yy.yy.yy/32",
+ "addresses": "xx.xx.xx.xx,yy.yy.yy.yy",
"authentication-password": "",
"authentication-protocol": "MD5",
"default": true,
changed: [Mikrotik]
What does "{{ ZP_Server }},{{ local_zb_proxy_ip }}"
evaluate to?
Also this diff does not match the output you have further up. There old_data
has 0.0.0.0,1.1.1.1
for addresses
, but according to the diff addresses
in old_data
should have been xx.xx.xx.xx/32,yy.yy.yy.yy/32
.
These are the ip addresses that I don't want to show :) But I can assure you that they are identical. As I understand it, the problem itself lies in the subnet mask: xx.xx.xx.xx/32
.
(0.0.0.0,1.1.1.1
and xx.xx.xx.xx,yy.yy.yy.yy
are the same)
But where is that mask? In the input data? In the data sent by the router?
I think I was able to solve it on my own. A very stupid mistake.
The addresses in Mikrotik look like this:
But I passed them to Ansible without a subnet mask (without /32
).
Then I tried to pass an ip address with a subnet mask in a variable, now everything works correctly. Maybe I'm not explaining it well, but I'm ready to tell you more if you have any questions.
I think the issue can be closed :)
I have another question about the idempotency of the module, but another one. When using the community.routeros.api
, I run the add
command.
When restarting the Playbook, this command is executed each time, adding the same entries to Mikrotik.
- name: Configure radius rules in last number
community.routeros.api:
path: "radius"
add: "address={{RADIUS_SERVER}} secret={{RADIUS_COMMON_SECRET}} service=login src-address={{main_ip_address}}"
register: raduis_rules
Output after the first run of the playbook and after the second run:
ok: [Mikrotik] => {
"msg": {
"changed": true,
"failed": false,
"msg": [
"added: .id= *1"
]
}
}
ok: [Mikrotik] => {
"msg": {
"changed": true,
"failed": false,
"msg": [
"added: .id= *2"
]
}
}
Is this the normal behavior of the module? The essence of idempotence is violated, I already have such a rule, why add more?
The same incomprehensible behavior of community.routeros.api
with the add
command is observed when adding an snmp community:
- name: Add customer Configure SNMP Community
community.routeros.api:
path: "snmp community"
add: "addresses=0.0.0.0/0 name={{ CST_LOCAL_SNMP_SERVER }} security=none disabled=no"
register: snmp_add
Output after the second run of the Playbook:
TASK [1DEV/mkt-config-snmp : Add customer Configure SNMP Community] **************************************************************************************
fatal: [Mikrotik]: FAILED! => {"changed": false, "msg": ["failure: community with the same name already exists!"]}
The same error is observed in Mikrotik itself:
Why is Ansible trying to add the snmp community again if it already exists?
I think I was able to solve it on my own. A very stupid mistake. The addresses in Mikrotik look like this: But I passed them to Ansible without a subnet mask (without
/32
).Then I tried to pass an ip address with a subnet mask in a variable, now everything works correctly. Maybe I'm not explaining it well, but I'm ready to tell you more if you have any questions.
So basically this means that you didn't pass it in without a subnet mask to the module, but the API returned it with a subnet mask? The new_data
/ old_data
you pasted did not have that subnet mask.
In any case, the module does not know which strings RouterOS treats to be equal, so if it sees a difference, it will update the record with what you passed into the module. So adjusting what you put in (as you now did) is the correct way. In any case, --diff
is helpful here since it shows you what the module sees as differences.
I have another question about the idempotency of the module, but another one. When using the
community.routeros.api
, I run theadd
command. [...] Is this the normal behavior of the module? The essence of idempotence is violated, I already have such a rule, why add more?
The api
module is as idempotent as the command
module: you yourself are responsible of making its calls idempotent. If you want idempotency, use the api_find_and_modify
or api_modify
modules (if they support your use-case).
I don't quite understand you...
Please explain what logic is involved in the operation of the community.routeros.api
module within this parameter?
Do I understand correctly that Ansible will always try to execute the add
command regardless of the Mikrotik settings by the specified path?
Yes, it will always execute it. The api module has no way of knowing whether the add
(or any other of the commands you use it to run) command is still necessary or not.
Then how can the community.routeros.api
module be idempotent if the add
command is always executed?
An operation is considered idempotent if its repeated execution leads to the same result as a single execution.
The community.routeros.api
module is never idempotent by itself. You have to use when:
to only run it when needed.
The same for the command/shell/raw and community.routeros.command modules. You are responsible yourself to make your use of them idempotent.
The
api
module is as idempotent as thecommand
module
Apparently I misunderstood this comment. In any case, it became clearer to me, thank you for your help!
Do I understand correctly from my practice that the modules community.routeros.api_find_and_modify
module and community.routeros.api_modify
module are idempotent?
Yes, they are. Assuming you pass in the data in the same format as the API returns it, like with the subnet mask in case of the IPs in the original post in this issue. The modules do not understand the API that well :)
Great, thanks for the explanation and quick answers :)
SUMMARY
Hello! I am using the community.routeros.api_find_and_modify module to configure the snmp community. When the role is first started, the default community will change to the required one, at the end the host state is "changed". When restarting and the configured community, the task state is "changed", although old_data and new_data are the same.
ISSUE TYPE
COMPONENT NAME
community.routeros.api_find_и_modify
ANSIBLE VERSION
COLLECTION VERSION
OS / ENVIRONMENT
MikroTik RouterOS 6.46.5
STEPS TO REPRODUCE
EXPECTED RESULTS
When the role is restarted, it is expected that the task state will be "changed=0"
ACTUAL RESULTS
Identical old_data and new_data, with the state "changed=1" at the end after the role is restarted