# Assign where dictionary key exists in a nested dictionary - possible?

**URL:** <https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785>\
**Category:** Icinga 2\
**Created:** [May 5, 2022, 3:02pm UTC](https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785 "2022-05-05T15:02:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Napsty](https://community.icinga.com/user_avatar/community.icinga.com/napsty/32/781_2.png) [@Napsty](https://community.icinga.com/u/Napsty)\
**Post date:** [May 5, 2022, 3:02pm UTC](https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785/1 "2022-05-05T15:02:36Z")

</div>

- Version used (`icinga2 --version`) r2.13.2-1
- Operating System and version: Debian 11
- Enabled features (`icinga2 feature list`): api checker command ido-mysql influxdb mainlog notification
- Icinga Web 2 version and modules (System - About) N/A

Hello all. It’s been a while.

I have these custom variables in the Host object:

```auto
  vars.http["example.com"] = {
    http_sni = true
    http_ssl = true
    http_uri = "/"
    http_string = "Wordpress"
    ssl_cert_warn = 30
  }
  vars.http["api.example.com"] = {
    http_sni = true
    http_ssl = true
    http_uri = "/_health"
    http_string = "ok"
    ssl_cert_warn = 30
  }

```

I want to create an `Apply for` rule for certificate checks, but want to `assign where` the http\_ssl key is set to true or just simply exists. The problem here is though, that we’re running against a nested dictionaries so the following won’t work:

```auto
assign where host.vars.http.http_ssl

```

To handle the different entries, (I suppose) a wildcard or something similar would be needed:

```auto
assign where host.vars.http[*].http_ssl

```

But obviously that doesn’t work.

I hope you see what I am trying to do.

Is this the right approach or am I over-complicating things? Maybe there’s an easier solution to this? 🙂

---

<div class="post-metadata">

**Author:** ![jbrost](https://community.icinga.com/user_avatar/community.icinga.com/jbrost/32/3374_2.png) [@jbrost](https://community.icinga.com/u/jbrost)\
**Post date:** [May 5, 2022, 3:36pm UTC](https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785/2 "2022-05-05T15:36:24Z")

</div>

You could have a look at [`apply ... for` rules](https://icinga.com/docs/icinga-2/latest/doc/17-language-reference/#apply-for) and instead of using `in host.vars.dictionary` there directly, call a function that filters that dict.

Disclaimer: I didn’t test this so take it with a grain of salt, but hopefully it’s a hint into the right direction.

---

<div class="post-metadata">

**Author:** ![Napsty](https://community.icinga.com/user_avatar/community.icinga.com/napsty/32/781_2.png) [@Napsty](https://community.icinga.com/u/Napsty)\
**Post date:** [May 6, 2022, 9:56am UTC](https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785/3 "2022-05-06T09:56:10Z")

</div>

Thanks for the reply, but writing a function (I took a look at [DSL: Flatten a nested dictionary with a function for apply for rules](https://community.icinga.com/t/dsl-flatten-a-nested-dictionary-with-a-function-for-apply-for-rules/1330)) would complicate things rather than making it easier.  
Unless you have a straightforward example of such a function at hand? 😉

Oh and I can’t use “if” inside the `apply` rule because it is managed by puppet-icinga2.

---

<div class="post-metadata">

**Author:** ![Napsty](https://community.icinga.com/user_avatar/community.icinga.com/napsty/32/781_2.png) [@Napsty](https://community.icinga.com/u/Napsty)\
**Post date:** [June 7, 2022, 9:31am UTC](https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785/4 "2022-06-07T09:31:14Z")

</div>

@jbrost I was trying an alternative, which would use a variable retrieved from the dictionary in the `assign where` part. However this doesn’t seem to work (only works for host.vars ?):

In Host object:

```auto
  vars.http["example.com"] = {
    http_sni = true
    http_ssl = true
    http_uri = "/"
    http_string = "Wordpress"
    ssl_cert_warn = 30
  }
  vars.http["api.example.com"] = {
    http_sni = true
    http_ssl = true
    http_uri = "/_health"
    http_string = "ok"
    ssl_cert_warn = 30
  }

```

Apply Rule:

```auto
apply Service "http " for (servername => config in host.vars.http) {
  import "generic-service"

  check_command = "http"
  vars.http_vhost = servername
  vars += config

  assign where host.vars.http && vars.http_string
}

```

The error:

```auto
[2022-06-07 11:29:42 +0200] critical/config: Error: Error while evaluating expression: Tried to access undefined script variable 'vars'
Location: in /etc/icinga2/zones.d/global-templates/applyrules/test.conf: 37:40-37:43
/etc/icinga2/zones.d/global-templates/applyrules/test.conf(37): assign where host.vars.check_http && vars.http_string
                                                                                                       ^^^^
/etc/icinga2/zones.d/global-templates/applyrules/test.conf(38): }
/etc/icinga2/zones.d/global-templates/applyrules/test.conf(39): 

```

Is there any way I can work with variables (even newly created variables inside the Apply context) and use them in `assign where` or `ignore where` ?

---

<div class="post-metadata">

**Author:** ![Napsty](https://community.icinga.com/user_avatar/community.icinga.com/napsty/32/781_2.png) [@Napsty](https://community.icinga.com/u/Napsty)\
**Post date:** [June 7, 2022, 11:16am UTC](https://community.icinga.com/t/assign-where-dictionary-key-exists-in-a-nested-dictionary-possible/9785/5 "2022-06-07T11:16:53Z")

</div>

Looks like I found a way 🕺  
By using `config` as dictionary identifier and then followed by the actual variable, I can create an `apply` rule which is only applied when certain variables are set in the dictionary.

```auto
apply Service "http " for (servername => config in host.vars.http) {
  import "generic-service"

  check_command = "http"
  vars.http_vhost = servername
  vars += config

  assign where host.vars.http && config.http_string
}

```

Works fine in my test environment with Icinga 2 2.13.2. 😃
