Skip to content

Commit

Permalink
feat(map): use targeting like syntax for configuration
Browse files Browse the repository at this point in the history
The `config_get_lookup` and `config_get` sources lack flexibility.

It's not easy to query several pillars and/or grains keys with the
actual system. And the query method is forced to `config.get` without
being configurable by the user.

We define a mechanism to select `map.jinja` sources with similar
notation as the salt targeting system.

Each source has a type:

- `Y` to load values from YAML files, this is the default when no type
  is defined
- `C` to lookup values with `config.get`
- `G` to lookup values with `grains.get`
- `I` to lookup values with `pillar.get`

The YAML type can define the query method to lookup the key value to
build the file name:

- `C` to query with `config.get`, this is the default when to query
  method is defined
- `G` to query with `grains.get`
- `I` to query with `pillar.get`

The `C`, `G` or `I` types can define the `SUB` attribute to merge
values in the sub key `mapdata.<key>` instead of directly in `mapdata`.

BREAKING CHANGE: the `map_jinja:config_get_roots` is replaced by
                 compound like `map_jinja:sources`

BREAKING CHANGE: the two `map_jinja:sources` `config_get_lookup` and
                 `config_get` are replaced by `C@<tplroot>:lookup` and
		 `C@<tplroot>` sources
  • Loading branch information
baby-gnu committed Aug 25, 2020
1 parent 34a9c8f commit fe98819
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 139 deletions.
181 changes: 102 additions & 79 deletions openssh/map.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"os_family",
"os",
"osfinger",
"config_get_lookup",
"config_get",
"C@" ~ tplroot ~ ":lookup",
"C@" ~ tplroot,
"id",
] %}
{#- Configure map.jinja from defaults.yaml #}
Expand All @@ -47,32 +47,6 @@
~ map_sources
) %}

{#- Lookup with `config.get` from configurable roots #}
{%- do salt["log.debug"](
"map.jinja: initialise 'config.get' roots with 'tplroot' "
~ tplroot
) %}
{%- set config_get_roots = [tplroot] %}
{#- Configure `config.get` from defaults.yaml #}
{%- set config_get_roots = default_settings | traverse(
"values:map_jinja:config_get_roots",
config_get_roots
) %}
{#- Lookup global `config.get` roots #}
{%- set config_get_roots = salt["config.get"](
"map_jinja:config_get_roots",
config_get_roots
) %}
{#- Lookup per formula `config.get` roots #}
{%- set config_get_roots = salt["config.get"](
tplroot ~ ":map_jinja:config_get_roots",
config_get_roots,
) %}
{%- do salt["log.debug"](
"map.jinja: load parameters with 'config.get' from roots "
~ config_get_roots
) %}

{#- Work around assignment inside for loop #}
{#- load configuration values used in `config.get` merging strategies #}
{%- set _config = {
Expand Down Expand Up @@ -106,62 +80,111 @@
) %}
{%- endif %}

{%- set query_map = {
"C": "config.get",
"G": "grains.get",
"I": "pillar.get",
} %}

{#- process each `map.jinja` source #}
{#- Process each `map.jinja` source #}
{#- each source has a type: #}
{#- - `Y` to load values from YAML files (the default when no type is set) #}
{#- - `C` to lookup values with `config.get` #}
{#- - `G` to lookup values with `grains.get` #}
{#- - `I` to lookup values with `pillar.get` #}
{#- The YAML type can define query type to build the file name: #}
{#- - `C` for query with `config.get` (the default when to query type is set) #}
{#- - `G` for query with `grains.get` #}
{#- - `I` for query with `pillar.get` #}
{#- The `C`, `G` or `I` types can define the `SUB` attribute #}
{#- to merge values in the sub key `mapdata.<key>` instead of directly in `mapdata` #}
{%- for map_source in map_sources %}
{%- if map_source in ["config_get", "config_get_lookup"] %}
{%- for _config_root in config_get_roots %}
{%- set _config_key = {
"config_get": _config_root,
"config_get_lookup": _config_root ~ ":lookup",
}.get(map_source) %}

{%- do salt["log.debug"](
"map.jinja: retrieve '"
~ _config_key
~ "' with 'config.get'"
~ _config["merge_msg"]
) %}
{%- set _config_get = salt["config.get"](
_config_key, default={}, **_config["merge_opt"]
) %}

{#- `slsutil.merge` defaults to `smart` instead of `None` for `config.get` #}
{%- set _strategy = _config["merge_strategy"] | default("smart", boolean=True) %}
{%- do salt["log.debug"](
"map.jinja: merge '"
~ _config_key
~ "' retrieved with 'config.get'"
~ ", merge: strategy='"
~ _strategy
~ "', lists='"
~ _config["merge_lists"]
~ "'"
) %}

{#- Keep values under each root key when there are more than one #}
{%- if config_get_roots|length > 1 %}
{%- set _config_get = { _config_root: _config_get } %}
{%- endif %}
{%- do _config.update(
{
"stack": salt["slsutil.merge"](
_config["stack"],
_config_get,
strategy=_strategy,
merge_lists=_config["merge_lists"],
)
}
) %}
{%- endfor %}
{%- set source_parts = map_source.split('@') %}
{%- if source_parts|length == 1 %}
{#- By default we load YAML files for config looked up by `config.get` #}
{%- set source_type = "Y" %}
{%- set query_type = "C" %}
{%- set source_key = map_source %}
{%- elif source_parts[0][0] == "Y" %}
{%- set source_type = "Y" %}
{%- set query_type = source_parts[0].split(':')[1] | default("C") %}
{%- set source_key = source_parts[1] %}
{%- elif source_parts[0][0] in query_map.keys() %}
{%- set source_type = source_parts[0].split(':') | first %}
{%- set query_type = source_type %}
{%- set is_sub_key = source_parts[0].split(':')[1] | default(False) == "SUB" %}
{%- set source_key = source_parts[1] %}
{%- endif %}

{#- Define which method to use for query #}
{%- set query_method = query_map[query_type] %}

{%- if source_type in query_map.keys() %}
{#- Lookup source `<QUERY_METHOD>@key:to:query` #}
{%- if source_type == "C" %}
{%- set merge_opts = _config["merge_opt"] %}
{%- set merge_msg = _config["merge_msg"] %}
{%- else %}
{#- No merging strategy supported for `grains.get` and `pillar.get` #}
{%- set merge_opts = {} %}
{%- set merge_msg = "" %}
{%- endif %}

{%- do salt["log.debug"](
"map.jinja: retrieve '"
~ source_key
~ "' with '" ~ query_method ~ "'"
~ merge_msg
) %}
{%- set _config_get = salt[query_method](
source_key,
default={},
**merge_opts
) %}

{#- `slsutil.merge` defaults to `smart` instead of `None` for `config.get` #}
{%- set _strategy = _config["merge_strategy"] | default("smart", boolean=True) %}
{%- do salt["log.debug"](
"map.jinja: merge "
~ "sub key " * is_sub_key
~ "'" ~ source_key
~ "' retrieved with '"
~ query_method ~ "'"
~ ", merge: strategy='"
~ _strategy
~ "', lists='"
~ _config["merge_lists"]
~ "'"
) %}

{%- if is_sub_key %}
{#- Merge values with `mapdata.<key>`, `<key>` and `<key>:lookup` are merged together #}
{%- set _config_get = { source_key.rstrip(':lookup'): _config_get } %}
{%- endif %}
{%- do _config.update(
{
"stack": salt["slsutil.merge"](
_config["stack"],
_config_get,
strategy=_strategy,
merge_lists=_config["merge_lists"],
)
}
) %}
{%- else %}
{#- Lookup the grain/pillar/... #}
{#- Load YAML file matching the grain/pillar/... #}
{#- Fallback to use the source name as a direct filename #}
{%- set map_values = salt["config.get"](map_source, []) %}
{%- do salt["log.debug"](
"map.jinja: lookup "
~ "'" ~ source_key ~ "'"
~ " with "
~ "'" ~ query_method ~ "'"
) %}
{%- set map_values = salt[query_method](source_key, []) %}

{#- Mangle `map_source` to use it as literal path #}
{#- Mangle `source_key` to use it as literal path #}
{%- if map_values | length == 0 %}
{%- set map_source_parts = map_source.split("/") %}
{%- set map_source_parts = source_key.split("/") %}
{%- set map_source = map_source_parts[0:-1] | join("/") %}
{%- set map_values = map_source_parts[-1].rstrip(".yaml") %}
{%- endif %}
Expand All @@ -174,7 +197,7 @@
{%- for map_value in map_values %}
{%- set yamlfile = [
map_sources_dir,
map_source,
source_key,
map_value ~ ".yaml",
]
| join("/")
Expand Down
21 changes: 17 additions & 4 deletions openssh/parameters/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,23 @@
---
values:
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- "osarch"
- "os_family"
- "os"
- "osfinger"

# Merge values from `config.get` under `mapdata.<key>` to keep
# compatibility with user pillars.
# The `<key>` and `<key>:lookup` are merged together
- "C:SUB@openssh:lookup"
- "C:SUB@openssh"
- "C:SUB@sshd_config:lookup"
- "C:SUB@sshd_config"
- "C:SUB@ssh_config:lookup"
- "C:SUB@ssh_config"

- "id"

openssh:
sshd_enable: true
Expand Down
16 changes: 12 additions & 4 deletions test/integration/default/files/_mapdata/amazonlinux-1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
# Amazon Linux AMI-2018
---
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- osarch
- os_family
- os
- osfinger
- C:SUB@openssh:lookup
- C:SUB@openssh
- C:SUB@sshd_config:lookup
- C:SUB@sshd_config
- C:SUB@ssh_config:lookup
- C:SUB@ssh_config
- id
openssh:
absent_dsa_keys: false
absent_ecdsa_keys: false
Expand Down
16 changes: 12 additions & 4 deletions test/integration/default/files/_mapdata/amazonlinux-2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
# Amazon Linux-2
---
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- osarch
- os_family
- os
- osfinger
- C:SUB@openssh:lookup
- C:SUB@openssh
- C:SUB@sshd_config:lookup
- C:SUB@sshd_config
- C:SUB@ssh_config:lookup
- C:SUB@ssh_config
- id
openssh:
absent_dsa_keys: false
absent_ecdsa_keys: false
Expand Down
16 changes: 12 additions & 4 deletions test/integration/default/files/_mapdata/arch-base-latest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
# Arch
---
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- osarch
- os_family
- os
- osfinger
- C:SUB@openssh:lookup
- C:SUB@openssh
- C:SUB@sshd_config:lookup
- C:SUB@sshd_config
- C:SUB@ssh_config:lookup
- C:SUB@ssh_config
- id
openssh:
absent_dsa_keys: false
absent_ecdsa_keys: false
Expand Down
16 changes: 12 additions & 4 deletions test/integration/default/files/_mapdata/centos-6.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
# CentOS-6
---
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- osarch
- os_family
- os
- osfinger
- C:SUB@openssh:lookup
- C:SUB@openssh
- C:SUB@sshd_config:lookup
- C:SUB@sshd_config
- C:SUB@ssh_config:lookup
- C:SUB@ssh_config
- id
openssh:
absent_dsa_keys: false
absent_ecdsa_keys: false
Expand Down
16 changes: 12 additions & 4 deletions test/integration/default/files/_mapdata/centos-7.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
# CentOS Linux-7
---
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- osarch
- os_family
- os
- osfinger
- C:SUB@openssh:lookup
- C:SUB@openssh
- C:SUB@sshd_config:lookup
- C:SUB@sshd_config
- C:SUB@ssh_config:lookup
- C:SUB@ssh_config
- id
openssh:
absent_dsa_keys: false
absent_ecdsa_keys: false
Expand Down
16 changes: 12 additions & 4 deletions test/integration/default/files/_mapdata/centos-8.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
# CentOS Linux-8
---
map_jinja:
config_get_roots:
- openssh
- sshd_config
- ssh_config
sources:
- osarch
- os_family
- os
- osfinger
- C:SUB@openssh:lookup
- C:SUB@openssh
- C:SUB@sshd_config:lookup
- C:SUB@sshd_config
- C:SUB@ssh_config:lookup
- C:SUB@ssh_config
- id
openssh:
absent_dsa_keys: false
absent_ecdsa_keys: false
Expand Down
Loading

0 comments on commit fe98819

Please sign in to comment.