公式提供属性默认值的最佳方式是什么?
What's the best way for a formula to provide attribute defaults?
Chef 有一个非常详尽(也许太多了)的烹饪书方案来提供属性的默认值。我认为 Puppet 对 class 参数做了类似的事情,其中默认值通常进入 params.pp
。对于 Salt,我见过:
- 在 dictionary/pillar 查找中指定默认值。
grains.filter_by
将默认属性值与用户提供的支柱数据(例如,map.jinja in apache-formula)合并
- 在调用
file.managed
状态时,将默认属性值指定为 defaults
参数,将用户指定的支柱数据指定为 context
。
选项 1 似乎是最常见的,但缺点是模板文件变得很难阅读。它还需要在查找完成时重复默认值,因此很容易出错。
选项 2 在精神上感觉最接近 Chef 的方法,但似乎期望默认值根据某些过滤属性(例如,记录在 grains 中的 OS 类型)分解为案例字典。
选项 3 不错,但是将属性默认值放入状态文件,而不是像选项 2 那样将它们分开到自己的文件中。
Saltstack 的 best practices doc 支持选项 2,只是它没有解决如何在不必使用 grains.filter_by
的情况下将默认值与用户指定的值合并。有什么解决办法吗?
注意:defaults.get 的行为在 2015.8 版本中发生了变化,因此此处描述的方法不再有效。我将这个答案留给旧版本的用户,并将 post 当前版本的类似方法。
defaults.get
加上 defaults.yaml
文件应该可以满足您的需求。假设您的公式树如下所示:
my-formula/
files/
template.jinja
init.sls
defaults.yaml
# my-formula/init.sls
my-formula-conf-file:
file.managed:
- name: {{ salt['defaults.get']('conf_location') }}
- source: {{ salt['defaults.get']('conf_source') }}
... and so on.
# defaults.yaml
conf_location: /etc/my-formula.conf
conf_source: salt://my-formula/files/template.jinja
# pillar/my-formula.sls
my-formula:
conf_location: /etc/my-formula/something.conf
这将以使用 salt://my-formula/files/template.jinja
作为源(默认,没有提供支柱覆盖)的配置文件放置在 /etc/my-formula/something.conf
(支柱值)结束。
注意 pillar 和默认文件的不直观结构; defaults.get
期望 defaults.yaml
的值位于文件的根目录,但期望支柱覆盖位于以公式命名的字典中,因为一致性是弱者。
defaults.get 的 documentation 给出了使用 defaults.json
而不是 defaults.yaml
的示例。这行得通,但我发现 yaml 更具可读性。并且可写。
有一个 bug 使用 defaults.get 从托管模板内部而不是在状态文件中,据我所知它仍然打开。它仍然可以工作;解决方法在 link.
后面
defaults.get 的行为在 2015.8 中发生了变化,可能是由于错误。这个答案描述了一种在(至少)2015.8 及以后获得相同结果的兼容方法。
假设您的公式树如下所示:
something/
files/
template.jinja
init.sls
defaults.yaml
# defaults.yaml
conf_location: /etc/something.conf
conf_source: salt://something/files/template.jinja
# pillar/something.sls
something:
conf_location: /etc/something/something.conf
想法是公式默认值在 defaults.yaml 中,但可以在支柱中覆盖。支柱中未提供的任何内容都应使用默认值。您可以在任何给定的 .sls 顶部添加几行来完成此操作:
# something/init.sls
{%- set pget = salt['pillar.get'] %} # Convenience alias
{%- import_yaml slspath + "/defaults.yaml" as defaults %}
{%- set something = pget('something', defaults, merge=True) %}
something-conf-file:
file.managed:
- name: {{ something.conf_location }}
- source: {{ something.conf_source }}
- template: jinja
- context:
slspath: {{ slspath }}
... and so on.
这是做什么的:defaults.yaml 的内容作为嵌套字典加载。然后将该嵌套字典与 something
支柱键的内容合并,支柱赢得冲突。结果是包含默认值和任何支柱覆盖的嵌套字典,然后可以直接使用它而不用关心特定值的来源。
slspath
并不是这个工作的严格要求;这是一个神奇的变量,包含当前-运行 sls 的目录路径。我喜欢使用它,因为它将公式与目录树中的任何特定位置分离。它通常不能从托管模板中获得,这就是我将其作为上面的显式上下文传递的原因。它在旧版本中可能无法按预期工作,在这种情况下,您必须提供相对于盐树根的路径。
这种方法的缺点是,据我所知,您无法使用 salt 的基于冒号的嵌套键语法访问最终字典;您需要一次下降一个级别。我对此没有遇到任何问题(无论如何,点语法更容易输入),但这是一个缺点。另一个缺点是需要在任何使用该技术的 .sls 或模板顶部添加几行样板文件。
有一些好处。一个是你可以用 .items()
遍历最终字典或其子字典,然后正确的事情就会发生,而 defaults.get 则不是这样,这让我发疯。另一个是,如果 salt 团队恢复 defaults.get 的旧功能,这里建议的 defaults/pillar 结构已经兼容,它们可以并排工作。
Chef 有一个非常详尽(也许太多了)的烹饪书方案来提供属性的默认值。我认为 Puppet 对 class 参数做了类似的事情,其中默认值通常进入 params.pp
。对于 Salt,我见过:
- 在 dictionary/pillar 查找中指定默认值。
grains.filter_by
将默认属性值与用户提供的支柱数据(例如,map.jinja in apache-formula)合并- 在调用
file.managed
状态时,将默认属性值指定为defaults
参数,将用户指定的支柱数据指定为context
。
选项 1 似乎是最常见的,但缺点是模板文件变得很难阅读。它还需要在查找完成时重复默认值,因此很容易出错。
选项 2 在精神上感觉最接近 Chef 的方法,但似乎期望默认值根据某些过滤属性(例如,记录在 grains 中的 OS 类型)分解为案例字典。
选项 3 不错,但是将属性默认值放入状态文件,而不是像选项 2 那样将它们分开到自己的文件中。
Saltstack 的 best practices doc 支持选项 2,只是它没有解决如何在不必使用 grains.filter_by
的情况下将默认值与用户指定的值合并。有什么解决办法吗?
注意:defaults.get 的行为在 2015.8 版本中发生了变化,因此此处描述的方法不再有效。我将这个答案留给旧版本的用户,并将 post 当前版本的类似方法。
defaults.get
加上 defaults.yaml
文件应该可以满足您的需求。假设您的公式树如下所示:
my-formula/
files/
template.jinja
init.sls
defaults.yaml
# my-formula/init.sls
my-formula-conf-file:
file.managed:
- name: {{ salt['defaults.get']('conf_location') }}
- source: {{ salt['defaults.get']('conf_source') }}
... and so on.
# defaults.yaml
conf_location: /etc/my-formula.conf
conf_source: salt://my-formula/files/template.jinja
# pillar/my-formula.sls
my-formula:
conf_location: /etc/my-formula/something.conf
这将以使用 salt://my-formula/files/template.jinja
作为源(默认,没有提供支柱覆盖)的配置文件放置在 /etc/my-formula/something.conf
(支柱值)结束。
注意 pillar 和默认文件的不直观结构; defaults.get
期望 defaults.yaml
的值位于文件的根目录,但期望支柱覆盖位于以公式命名的字典中,因为一致性是弱者。
defaults.get 的 documentation 给出了使用 defaults.json
而不是 defaults.yaml
的示例。这行得通,但我发现 yaml 更具可读性。并且可写。
有一个 bug 使用 defaults.get 从托管模板内部而不是在状态文件中,据我所知它仍然打开。它仍然可以工作;解决方法在 link.
后面defaults.get 的行为在 2015.8 中发生了变化,可能是由于错误。这个答案描述了一种在(至少)2015.8 及以后获得相同结果的兼容方法。
假设您的公式树如下所示:
something/
files/
template.jinja
init.sls
defaults.yaml
# defaults.yaml
conf_location: /etc/something.conf
conf_source: salt://something/files/template.jinja
# pillar/something.sls
something:
conf_location: /etc/something/something.conf
想法是公式默认值在 defaults.yaml 中,但可以在支柱中覆盖。支柱中未提供的任何内容都应使用默认值。您可以在任何给定的 .sls 顶部添加几行来完成此操作:
# something/init.sls
{%- set pget = salt['pillar.get'] %} # Convenience alias
{%- import_yaml slspath + "/defaults.yaml" as defaults %}
{%- set something = pget('something', defaults, merge=True) %}
something-conf-file:
file.managed:
- name: {{ something.conf_location }}
- source: {{ something.conf_source }}
- template: jinja
- context:
slspath: {{ slspath }}
... and so on.
这是做什么的:defaults.yaml 的内容作为嵌套字典加载。然后将该嵌套字典与 something
支柱键的内容合并,支柱赢得冲突。结果是包含默认值和任何支柱覆盖的嵌套字典,然后可以直接使用它而不用关心特定值的来源。
slspath
并不是这个工作的严格要求;这是一个神奇的变量,包含当前-运行 sls 的目录路径。我喜欢使用它,因为它将公式与目录树中的任何特定位置分离。它通常不能从托管模板中获得,这就是我将其作为上面的显式上下文传递的原因。它在旧版本中可能无法按预期工作,在这种情况下,您必须提供相对于盐树根的路径。
这种方法的缺点是,据我所知,您无法使用 salt 的基于冒号的嵌套键语法访问最终字典;您需要一次下降一个级别。我对此没有遇到任何问题(无论如何,点语法更容易输入),但这是一个缺点。另一个缺点是需要在任何使用该技术的 .sls 或模板顶部添加几行样板文件。
有一些好处。一个是你可以用 .items()
遍历最终字典或其子字典,然后正确的事情就会发生,而 defaults.get 则不是这样,这让我发疯。另一个是,如果 salt 团队恢复 defaults.get 的旧功能,这里建议的 defaults/pillar 结构已经兼容,它们可以并排工作。