1

我正在尝试为 Hashicorp Consul DCS 构建两个 Puppet 配置文件。Consul 可以作为客户端或服务器代理运行,服务器模式是客户端模式的超集。这直接反映在配置中:

Consul 服务器代理通常需要 Consul 客户端代理所需的配置超集。

我的 Puppet 设计方法基于此模式: https ://puppet.com/docs/pe/2018.1/the_roles_and_profiles_method.html

根据 Puppet 文档,应该可以(并且最可能需要)在consul_client配置文件中包含配置consul_server文件以避免代码重复:

配置文件可以包括其他配置文件。

为了实现这一点,我在两个配置文件上都使用了一些强制参数,并在执行自动 rspec 单元测试期间遇到了问题。

consul_client单元测试文件consul_client_spec.rb中,我只是提供了所需的参数,如下所示:

let(:params) { {
  'datacenter' => 'unit-test',
  'encrypt' => 'DUMMY',
  'server_agent_nodes' => [ '1.2.3.4' ]
} }

尝试运行consul_server_spec.rb单元测试时出现问题。天真地,我只是传递了consul_server配置文件的一个附加必需参数:

let(:params) { {
  'bootstrap_expect' => 3,
} }

由于consul_client配置文件由配置文件include编辑/require编辑consul_server,因此测试失败,缺少consul_client配置文件类的参数。这似乎表明这种方法存在一些普遍的结构性问题。


现在,我不确定是否应该在consul_client配置文件类中重新声明配置文件类的所有参数consul_server——在我看来,这会违反 DRY 原则。profile::consul_client::*此外,当将来使用 Hiera 数据时,这将导致其中profile::consul_server::*包含一些相同的重复数据,因为必须为两个配置文件重复数据的客户端相关部分。

补充说明:并且在类中复制参数consul_server甚至可能不起作用,因为参数不能显式传递,而只能通过数据传递到类似包含的资源定义 - 所以那些重复的参数不能传递给consul_client类。

相反,文档说明了以下内容,但我不确定这是否也适用于包含的配置文件类(因为它们可能不是组件类?):

配置文件拥有其组件类的所有类参数。如果配置文件省略了一个,那意味着你肯定想要默认值;组件类不应使用 Hiera 数据中的值。如果您需要设置之前省略的类参数,请重构配置文件。


除了这些想法之外,人们还可以看到两个配置文件类被重构为单独模块的普通类,这可能有助于了解不同设计方法的含义。


总之,出现以下问题:

  • 嵌套配置文件中的参数应该如何处理,应该由分层数据单独为每个配置文件类单独设置?
  • 如何在单元测试期间将参数传递给嵌套配置文件?以某种方式提供模拟 hiera 数据作为测试夹具的一部分是否是正确的方法?
  • 模拟consul_client配置文件类会是更好的选择吗?
4

1 回答 1

0

由于consul_client配置文件由配置文件include编辑/require编辑 consul_server,因此测试失败,缺少 consul_client配置文件类的参数。这似乎表明这种方法存在一些普遍的结构性问题。

不是特别。

请理解,如果您使用具有所需参数的类的类似包含声明,那么这些参数将需要通过自动数据绑定或通过同一类的先前类似资源的声明来获取值。不过,这绝不是一个“一般的结构问题”,因为一般来说,无论如何都应该通过 Hiera 将参数提供给类(因此自动数据绑定)。

在单元测试环境中,这确实变得有点棘手。可以为您的测试套件配置 Hiera 数据,但编写前置条件可能更容易。事实上,我今天做了非常相似的事情。例子:

describe 'profile::consul_server' do
  # ...
  context "..." do
    let(:pre_condition) do
      'class { "profile::consul_client": param1 => "value1", param2 => "value2" }'
    end
    let(:params) { { bootstrap_expect: 3 } }

    it do
      is_expected.to # ...
    end
  end
end

然而,虽然这里没有特别的结构问题,但可能存在语义问题。如果您的consul_server个人资料包含您的consul_client个人资料,则表明每个领事服务器也必须是领事客户端。我对领事不是很熟悉,所以我不能确定这不是明智的,但它至少是可疑的。如果服务器不一定是客户端,那么恰好在两个配置文件之间共享的代码只是偶然地重复,并且挤出这种偶然的重复更有可能导致问题而不是解决它们。

现在,我不确定是否应该在 consul_client配置文件类中重新声明配置文件类的所有参数consul_server——在我看来,这会违反 DRY 原则。profile::consul_client::*此外,当将来使用 Hiera 数据时,这将导致其中 profile::consul_server::*包含一些相同的重复数据,因为必须为两个配置文件重复数据的客户端相关部分。

这些都是合理的担忧。就个人而言,我最小化了我的配置文件类的参数数量。大多数人根本没有。我的组件类是参数化的,它们的参数值大多来自自动数据绑定。我的配置文件类很少使用组件类的类似资源的声明,但是当它们使用时,它几乎总是由配置文件的标识驱动,而不是它的参数。

此外,您可能会发现它可以缓解您的重构问题。如果您的领事服务器和客户端之间共享配置详细信息,那么它们可能适合通过两个配置文件声明的一个或多个组件类进行管理。这样就不需要数据复制了,因为它是那些您将绑定数据的共享类的参数。

于 2020-03-06T22:24:51.247 回答