I was not aware on how to use that, thanks for the hint!
To understand what's happening and not deploy the code that might break stuff. Mikrotik scripting has a lots of quirks, e.g. you might expect that [find type=A] would return a list of A records. But it doesn't. Hence the need to be verbose, especially while designing scripts. And the need to maintain them properly, e.g. in case a ROS update drops that breaks backwards compatibility.
Thank you for the suggestion, but I'm still unaware on why my solution doesn't work Any suggestions? Is it a scoping issue (i.e. the [find ...] creates a new scope, in which the $name does not exist?)
Thank you! Your script has helped me debug the underlying issue: the $name appears to be a reserved keyword, as soon as I changed it to $iname my script started to work correctly.
In fact that word is reserved in the context /ip dns static, if you notice I didn’t declare “name” but I used it… and ([:typeof $name]=“str”)] do={
The problem on OP script is also the check “[:len $name] > 0”.
Since the name can be nil is wrong compare “nil” with something…
I omith the check of the name because on the first query I request records of “type=A” that have the name specified
I even went further and upgraded the solution like this:
/ip dns static
:foreach ARecord in=[find where (!type or (type=A)) and ([:typeof $name]="str")] do={
:local correctIpv6 ("::ffff:$[get $ARecord address]")
:local iname [get $ARecord name]
:local wrongAAAA [find where (name=$iname) and (type=AAAA) and !(address=$correctIpv6)]
:local correctAAAA [find where (name=$iname) and (type=AAAA) and (address=$correctIpv6)]
:foreach idx in=$wrongAAAA do={
:put "Removing AAA record $[get $idx name] with address $[get $idx address]"
remove $idx
}
:if ([:len $correctAAAA] = 0) do={
:put "Adding AAAA record $iname with address $correctIpv6"
add name=$iname type=AAAA address=$correctIpv6
}
}
That way, I can run this in scheduler every couple of minutes and nothing will happen if all the AAAA records are aligned properly to their corresponding A records.
I hope it's not too much to ask - would you mind proof-checking for some pitfalls, I might not be aware of?
It’s more efficient to remove all records with one command, rather than deleting each individual record individually,
that’s why on my versions remove is outside the :put logging.
For Name
/ip dns static
:foreach item in=[find where (!type or (type=A)) and ([:typeof $name]="str")] do={
:local newadd ("::ffff:$[get $item address]")
:local iname [get $item name]
:local removethis [find where (name=$iname) and (type=AAAA) and (address!=$newadd)]
:foreach idx in=$removethis do={
:put "Removing AAAA name $[get $idx name] with address $[get $idx address]"
}
remove $removethis
:if ([:len [find where (name=$iname) and (type=AAAA) and (address=$newadd)]] = 0) do={
:put "Adding AAAA name $iname with address $newadd"
add name=$iname type=AAAA address=$newadd
}
}
For RegEx
/ip dns static
:foreach item in=[find where (!type or (type=A)) and ([:typeof $regexp]="str")] do={
:local newadd ("::ffff:$[get $item address]")
:local iregex [get $item regexp]
:local removethis [find where (regexp=$iregex) and (type=AAAA) and (address!=$newadd)]
:foreach idx in=$removethis do={
:put "Removing AAAA RegEx $[get $idx regexp] with address $[get $idx address]"
}
remove $removethis
:if ([:len [find where (regexp=$iregex) and (type=AAAA) and (address=$newadd)]] = 0) do={
:put "Adding AAAA RegEx $iregex with address $newadd"
add regexp=$iregex type=AAAA address=$newadd
}
}