Community discussions

MikroTik App
 
User avatar
shalak
newbie
Topic Author
Posts: 41
Joined: Sat Aug 24, 2019 11:47 am

Using variable as value for [/find] parameter

Wed Apr 12, 2023 1:25 pm

I have the following script:
/ip dns static
:foreach rec in=[find type=[]] do={
  :local name [get $rec name]
  :local address [get $rec address]

  :if ([:len $name] > 0) do={
    :put ("Checking A record: " . $rec . " [name=" . $name . ", address=" . $address . "]")
    :local expectedIpv6Address ("::ffff:" . $address)
    :local existingAAAARecordsWithThisName [find name=$name type=AAAA]

    :if ([:len $existingAAAARecordsWithThisName] > 0) do={
      :foreach existingAAAARecord in=$existingAAAARecordsWithThisName do={
        :put ("Removing old AAAA record: " . $existingAAAARecord . " [name=" . [get $existingAAAARecord name] . ", address=" . [get $existingAAAARecord address] . "]")
        # remove $existingAAAARecord
      }
    }

    :put ("Creating AAAA record for name=" . $name . " address=" . $expectedIpv6Address)
    # add name=$name address=$expectedIpv6Address type=AAAA
  }
}
There's a problem with
:local existingAAAARecordsWithThisName [find name=$name type=AAAA]
- the value becomes an array of all AAAA entries, not just the one matching "name" - it's like the
$name
is not applied at all to the find function.

What am I missing?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:03 pm

Why type=[] instead of !type ?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:14 pm

Simply do that.
/ip dns static
:foreach item in=[find where (!type or (type=A)) and ([:typeof $name]="str")] do={
    remove [find where (name=[get $item name]) and (type=AAAA)]
    add name=[get $item name] type=AAAA address=("::ffff:$[get $item address]")
}
Why complicate script with useless frills for debug???.......
Last edited by rextended on Wed Apr 12, 2023 3:17 pm, edited 2 times in total.
 
User avatar
shalak
newbie
Topic Author
Posts: 41
Joined: Sat Aug 24, 2019 11:47 am

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:21 pm

Why type=[] instead of !type ?

I was not aware on how to use that, thanks for the hint!

Why complicate script with useless frills for debug???.......

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?)
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter  [SOLVED]

Wed Apr 12, 2023 2:24 pm

Ok, this integrate debug...
/ip dns static
/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)]
    :foreach idx in=$removethis do={
        :put "Removing AAAA name $[get $idx name] with address $[get $idx address]"
    }
    remove $removethis
    :put "Adding AAAA name $iname with address $newadd"
    add name=$iname type=AAAA address=$newadd
}
Last edited by rextended on Wed Apr 12, 2023 3:27 pm, edited 4 times in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:27 pm

Warning, I fix a misspell error on previous post #3, check twice.
viewtopic.php?p=995896#p995891


in case a ROS update drops that breaks backwards compatibility.
Is why I write (!type or (type=A)) and not only !type

I write the description for your other question, please wait...
 
User avatar
shalak
newbie
Topic Author
Posts: 41
Joined: Sat Aug 24, 2019 11:47 am

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:32 pm

Ok, this integrate debug...
/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)]
    :foreach idx in=$removethis do={
        :put "Removing AAA record $[get $idx name] with address $[get $idx address]"
    }
    remove $removethis
    :put "Adding AAAA record $iname with address $newadd"
    add name=[get $item name] type=AAAA address=$newadd
}

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.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:35 pm

oh, i was writing to you...
bravo!

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 ;)
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:45 pm

Fixed "AAA" typo and one variable error (not used the existant variable, call again "get" instead) on script #5



You can do also the same for RegEx records.... ;)

Debug version
/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)]
    :foreach idx in=$removethis do={
        :put "Removing AAAA RegEx $[get $idx regexp] with address $[get $idx address]"
    }
    remove $removethis
    :put "Adding AAAA RegEx $iregex with address $newadd"
    add regexp=$iregex type=AAAA address=$newadd
}

Short version
/ip dns static
:foreach item in=[find where (!type or (type=A)) and ([:typeof $regexp]="str")] do={
    remove [find where (regexp=[get $item regexp]) and (type=AAAA)]
    add regexp=[get $item regexp] type=AAAA address=("::ffff:$[get $item address]")
}
Last edited by rextended on Wed Apr 12, 2023 3:17 pm, edited 2 times in total.
 
User avatar
shalak
newbie
Topic Author
Posts: 41
Joined: Sat Aug 24, 2019 11:47 am

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 2:56 pm

oh, i was writing to you...
bravo!

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={
I omith the check of the name because on the first query I request records of "type=A" that have the name specified ;)

The problem on OP script is also the check "[:len $name] > 0".
Since the name can be nil is wrong compare "nil" with something...


Thank you for the insights!

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?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Using variable as value for [/find] parameter

Wed Apr 12, 2023 3:27 pm

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
    }
}

Who is online

Users browsing this forum: No registered users and 20 guests