公式提供属性默认值的最佳方法是什么?

时间:2015-06-26 22:52:26

标签: salt-stack

Chef为烹饪书提供了一个非常精细(可能太多)的方案来提供属性的默认值。我认为Puppet与类参数类似,默认情况下通常会进入params.pp。有了盐,我见过:

  1. 指定字典/支柱查找中的默认值。
  2. grains.filter_by合并默认属性值与用户提供的支柱数据(例如map.jinja中的apache-formula
  3. 在调用file.managed州时,将默认属性值指定为defaults参数,将用户指定的支柱数据指定为context
  4. 选项1似乎是最常见的,但缺点是模板文件变得非常难以阅读。它还需要在查找完成时重复默认值,这样就很容易出错。

    选项2在精神上与Chef的方法感觉最接近,但似乎期望默认值基于某些过滤属性(例如,谷物中记录的操作系统类型)分解为案例字典。

    选项3也不错,但是将属性默认值放入状态文件中,而不是像选项2那样将它们分成自己的文件。

    Saltstack的best practices doc支持选项2,但它没有解决如何在不使用grains.filter_by的情况下将默认值与用户指定的值合并的问题。有什么方法吗?

2 个答案:

答案 0 :(得分:4)

注意:defaults.get的行为在版本2015.8中已更改,因此此处描述的方法不再有效。我将为旧版本的用户留下此答案,并将为当前版本发布类似的方法。

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

这将以/etc/my-formula/something.conf(支柱值)的配置文件结束,使用salt://my-formula/files/template.jinja作为源(默认情况下,没有提供支柱覆盖)。

注意支柱和默认文件的非直观结构; defaults.get期望defaults.yaml将其值保存在文件的根目录中,但希望支柱覆盖位于以公式命名的字典中,因为一致性适用于弱点。

defaults.get的documentation使用defaults.json代替defaults.yaml来举例说明。这有效,但我发现yaml更具可读性。可写。

有一个bug来自托管模板内部而不是状态文件中的defaults.get,据我所知,它仍然是打开的。它仍然可以工作;解决方法在链接后面。

答案 1 :(得分:1)

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树根的路径。

这种方法的缺点是,据我所知,你无法使用salt的基于冒号的嵌套键语法访问最终字典;你需要一次下降一级。我没有遇到过这方面的问题(点法语法更容易输入),但这是一个缺点。另一个缺点是需要使用该技术在任何.sls或模板顶部使用几行样板。

有一些上升空间。一个是你可以使用.items()遍历最终字典或其子字典,并且会发生正确的事情,而defaults.get并非如此,这让我疯狂。另一个是,如果盐团队恢复defaults.get的旧功能,这里建议的默认/柱结构已经兼容,它们将并行工作。