# -*- coding: utf-8 -*- # vim: ft=jinja {#- Get the `tplroot` from `tpldir` #} {%- set tplroot = tpldir.split("/")[0] %} {%- from tplroot ~ "/libsaltcli.jinja" import cli with context %} {#- Where to lookup parameters source files #} {%- set map_sources_dir = tplroot ~ "/parameters" %} {#- List of sources to lookup for parameters #} {#- Fallback to previously used grains plus minion `id` #} {%- set map_sources = [ "Y:G@osarch", "Y:G@os_family", "Y:G@os", "Y:G@osfinger", "C@" ~ tplroot ~ ":lookup", "C@" ~ tplroot, "Y:G@id", ] %} {%- do salt["log.debug"]( "map.jinja: built-in configuration sources:\n" ~ {"values": { "map_jinja": {"sources": map_sources} } } | yaml(False) ) %} {#- Allow centralised map.jinja configuration #} {%- set _global_map_filename = "parameters/map_jinja.yaml" %} {%- do salt["log.debug"]( "map.jinja: load global map.jinja values from " ~ _global_map_filename ) %} {%- load_yaml as global_map_settings %} {%- include _global_map_filename ignore missing %} {%- endload %} {%- if global_map_settings %} {%- do salt["log.debug"]( "map.jinja: configure sources from global map.jinja configuration " ~ _global_map_filename ~ ":\n" ~ {"map_jinja": global_map_settings} | yaml(False) ) %} {%- set map_sources = global_map_settings | traverse( "values:sources", map_sources, ) %} {%- endif %} {#- Allow per formula map.jinja configuration #} {%- set _map_filename = map_sources_dir ~ "/map_jinja.yaml" %} {%- do salt["log.debug"]( "map.jinja: load per formula map.jinja values from " ~ _map_filename ) %} {%- load_yaml as map_settings %} {%- include _map_filename ignore missing %} {%- endload %} {%- if map_settings %} {%- do salt["log.debug"]( "map.jinja: configure sources from formula map.jinja configuration " ~ _map_filename ~ ":\n" ~ {"map_jinja": map_settings} | yaml(False) ) %} {%- set map_sources = map_settings | traverse( "values:sources", map_sources, ) %} {%- endif %} {%- do salt["log.debug"]( "map.jinja: load parameters from sources:\n" ~ map_sources | yaml(False) ) %} {#- Load formula defaults values #} {%- set _defaults_filename = map_sources_dir ~ "/defaults.yaml" %} {%- do salt["log.debug"]( "map.jinja: load per formula default values from " ~ _defaults_filename ) %} {%- load_yaml as default_settings %} {%- include _defaults_filename ignore missing %} {%- endload %} {%- if not default_settings %} {%- set default_settings = {'values': {} } %} {%- endif %} {#- Make sure to track `map.jinja` configuration with `_mapdata` #} {%- do default_settings["values"].update( { "map_jinja": map_settings | traverse("values", {}) } ) %} {#- Work around assignment inside for loop #} {#- load configuration values used in `config.get` merging strategies #} {%- set _config = { "stack": default_settings.get("values", {}), "merge_strategy": salt["config.get"](tplroot ~ ":strategy", None), "merge_lists": salt["config.get"](tplroot ~ ":merge_lists", False), } %} {#- the `config.get` merge option only works for `minion` or `local` salt command types #} {%- if cli in ["minion", "local"] %} {%- do _config.update( { "merge_opt": {"merge": _config["merge_strategy"]}, "merge_msg": ", merge: strategy='" ~ _config["merge_strategy"] ~ "'", } ) %} {#- the `config.get` merge option is not available for `ssh` or `unknown` salt command types #} {%- else %} {%- if _config["merge_strategy"] %} {%- do salt["log.error"]( "map.jinja: the 'merge' option of 'config.get' is skipped when the salt command type is '" ~ cli ~ "'" ) %} {%- endif %} {%- do _config.update( { "merge_opt": {}, "merge_msg": "", } ) %} {%- endif %} {%- set query_map = { "C": "config.get", "G": "grains.get", "I": "pillar.get", } %} {#- 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 option 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` option #} {#- to merge values in the sub key `mapdata.` instead of directly in `mapdata` #} {%- for map_source in map_sources %} {%- 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 %} {%- set query_method = query_map[query_type] %} {%- if source_type in query_map.keys() %} {#- Lookup source `@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.`, `` and `: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 %} {#- Load YAML file matching the grain/pillar/... #} {#- Fallback to use the source name as a direct filename #} {%- do salt["log.debug"]( "map.jinja: lookup '" ~ source_key ~ "' with '" ~ query_method ~ "'" ) %} {%- set map_values = salt[query_method](source_key, []) %} {#- Mangle `source_key` to use it as literal path #} {%- if map_values | length == 0 %} {%- set map_source_parts = source_key.split("/") %} {%- set source_key = map_source_parts[0:-1] | join("/") %} {%- set map_values = map_source_parts[-1].rstrip(".yaml") %} {%- endif %} {#- Some configuration return list #} {%- if map_values is string %} {%- set map_values = [map_values] %} {%- endif %} {#- `source_key` can be an empty string with literal path like `myconf.yaml` #} {%- set yaml_dir = [ map_sources_dir, source_key ] | select | join("/") %} {%- for map_value in map_values %} {%- set yamlfile = [ yaml_dir, map_value ~ ".yaml" ] | join("/") %} {%- do salt["log.debug"]("map.jinja: load parameters from file " ~ yamlfile) %} {%- load_yaml as loaded_values %} {%- include yamlfile ignore missing %} {%- endload %} {%- if loaded_values %} {#- Merge loaded values on the stack #} {%- do salt["log.debug"]("map.jinja: merge parameters from " ~ yamlfile) %} {%- do _config.update( { "stack": salt["slsutil.merge"]( _config["stack"], loaded_values.get("values", {}), strategy=loaded_values.get("strategy", "smart"), merge_lists=loaded_values.get("merge_lists", False) | to_bool, ) } ) %} {%- endif %} {%- endfor %} {%- endif %} {%- endfor %} {%- do salt["log.debug"]("map.jinja: save parameters in variable 'mapdata'") %} {%- set mapdata = _config["stack"] %}