Use Host var in vars dictionary doesn't work in all cases


#1

Hi everybody,

just came accross this and I’m not sure if I got something wrong or if this is a bug or a feature :wink:

In a Host Object I tried to use a Host var (let’s say “address”) in a dictionary residing in “vars.”. I found out, that this doesn’t work in all ways one can define a dictionary:

These examples work:

object Host "hostname.domain.dom" {
  display_name = "hostname"
  address = "hostname.domain.dom"

  vars.test["TEST"]=address
}

OR

object Host "hostname.domain.dom" {
  display_name = "hostname"
  address = "hostname.domain.dom"

  vars.test.TEST=address
}

In both cases the Host got a custom dictionary named “test” in vars with a key “TEST” holding the hosts address:

Test 	{
    TEST => hostname.domain.dom
}

This example creates an error while config check

object Host "hostname.domain.dom" {
  display_name = "hostname"
  address = "hostname.domain.dom"

  vars.test = {
      TEST = address
   }
}

With this “icinga2 daemon -C” results in:

critical/config: Error: Error while evaluating expression: Tried to access undefined script variable 'address'
Location: in /etc/icinga2/zones.d/lan/hostname.conf: 20:9-20:15
/etc/icinga2/zones.d/lan/hostname.conf(18):   vars.test = {
/etc/icinga2/zones.d/lan/hostname.conf(20):  TEST = address
                                                    ^^^^^^^
/etc/icinga2/zones.d/lan/hostname.conf(21):   }
/etc/icinga2/zones.d/lan/hostname.conf(22):

Bug? Feature? Any hints?
Would like to use the latter dictionary definition as it will get not only this key but a few more…

Greetings
T0mcat


#2

The issue is that vars.* and address lie in the same scope. Consider this example:

<10> => hostname.domain.dom = {
<10> ..   address = "hostname.domain.dom"
<10> ..   vars = {
<10> ..     TEST = address
<10> ..   }
<10> .. }

will fail with

Error while evaluating expression: Tried to access undefined script variable 'address'

At the point you are accessing address, it does not exist yet. But this works:

<11> => hostname.domain.dom = {
<11> ..   address = "hostname.domain.dom"
<11> ..   vars["TEST"] = address
<11> .. }

This is due to constraints with the language, so in your case there is no way around the first two examples :frowning:


#3

OK I see, then I rewrite the config regarding this scope thing.

After reading a bit in the docs and stumbled accross “Variable scopes” yeserday I already assumed, that this could have to do with this although there only functions are mentioned.
I even tried constructs like that:

object Host "hostname.domain.dom" {
  display_name = "hostname"
  address = "hostname.domain.dom"

  vars.test = {
      use(address)
      TEST = address
   }
}

which - of course - didn’t work either (as in the docs this just is used with functions) :slight_smile:

As a conclusion:
The three different ways to deal with dictionarys are not 100% identical and interchangeable.
So won’t this be worth mentioning in the docs (under “Variable scopes” and / or “Dictionary”)?


#4

We are always happy to receive pull requests :slight_smile:


#5

Would you mind elaborating a little further on this?

I understand the concept of scope, but I don’t see why the different ways of assigning a key => value should have different scopes from each other.

Why should vars.outerKey.innerKey = vars.otherAttr have a different scope from

vars.outerKey = {
    innerKey = vars.otherAttr
}

Why does the first one work but the second throws an “Undefined script variable ‘vars’” error?


(Michael Friedrich) #6

I don’t think that this is a problem with scopes, but the order of attributes parsed and executed by the compiler. At the point where vars is created, the object attribute address isn’t registered yet nor committed. use and variants won’t help here.


#7

Scope was clearly the wrong word, yes :confused: