条件资源属性

Conditonal resource attributes

为了安装包,我将来自 Hiera 的数据输入到 for 循环中。一些包需要额外的参数。对于不需要参数的包,我将值设置为 undef,但是,Chocolatey 读取 undef 并抱怨。

如何让 package 资源在 install_options 属性为空或 undef 时忽略它?

Hiera 片段:

profile::business::packages:
  office365business:
    version: latest
    provider: chocolatey
    arguments: ['/productid:O365BusinessRetail']
  xmind:
    version: latest
    provider: chocolatey
    arguments: undef
  slack:
    version: latest
    provider: chocolatey
    arguments: undef

Class 例子:

class profile::business(
  Hash $packages,
){
  if $::kernel == 'windows' {
    $packages.each | $key, $value | {
      package { "install_${key}" :
        name            => $key,
        ensure          => $value['version'],
        provider        => $value['provider'],
        install_options => $value['arguments'],
        notify          => Reboot['after_profile_business'],
      }
    }
    reboot { 'after_profile_business' :
      apply   => finished,
      message => 'Reboot: Business profile applied.'
    }
  }
}

我能想到的最好办法是使用 if 子句来应用 package 资源的不同实例,有或没有 install_options,具体取决于 arguments 的值:

$packages.each | $key, $value | {
  if $value['arguments'] != 'undef' {
    package { "install_${key}" :
      name            => $key,
      ensure          => $value['version'],
      provider        => $value['provider'],
      install_options => $value['arguments'],
      notify          => Reboot['after_profile_admin'],
    }
  } else {
    package { "install_${key}" :
      name     => $key,
      ensure   => $value['version'],
      provider => $value['provider'],
      notify   => Reboot['after_profile_admin'],
    }
  }
}

但是,这看起来很笨拙,我希望有人能告诉我更好的方法?

我看过 Puppet Selector 条件示例,但我不知道这是否适合我。

T.I.A

这个 YAML 片段 ...

    arguments: undef

... 将 'arguments' 键的值设置为 字符串 'undef'。这并不意味着在 Puppet 方面与 Puppet 文字 undef.

的意思相同

有解决办法。所有最好的,IMO,都围绕着通过善意数据缺失来表示数据缺失。这避免了对特殊保留字的任何需要。因此,假设您的数据看起来像这样:

profile::business::packages:
  office365business:
    version: latest
    provider: chocolatey
    arguments: ['/productid:O365BusinessRetail']
  xmind:
    version: latest
    provider: chocolatey
  slack:
    version: latest
    provider: chocolatey

请注意,没有包含 arguments 键的条目,实际上没有要指定的参数。如果您在定义数据类型方面一直严格而彻底,那么您可能需要为这些数据调整数据类型以适应这种情况,但这样更好,因为这样可以更好地描述实际的数据语义。 该数据修改可能会自行解决您的问题,因为在确实存在的散列中查找不存在的键应该产生 undef(还有 dig() 如果不确定性可以发生在深层数据结构的更高级别)。

但是,还要考虑 Puppet 有一个快捷方式来声明资源 属性 值是从哈希中提取的。这不太适合您当前的数据,因为您的密钥与所需的 属性 名称不同,但您可以更改数据中的密钥或将它们映射到 Puppet 级别。后者可能看起来像这样:

# Defining the key / property name mappings here makes them clear, and is easy to
# change if you need to update the mappings
$mappings = { 'version' => 'ensure', 'arguments' => 'install_options' }

$packages.each |$package, $properties| {

  # map the keys appearing in the data to Puppet property names, based on
  # the hash defined above
  $filtered_props = $properties.reduce({}) |$memo, $pair| {
      $mapped_key = $pair[0] in $mappings ? { true => $mappings[$pair[0]], default => $pair[0] }
      $memo + { $mapped_key => $pair[1] }
  }

  # one declaration covering all cases
  package { "install_${package}" :
    name     => $package,
    provider => $value['provider'],
    notify   => Reboot['after_profile_admin'],
    *        => $filtered_props,
  }
}