puppet 代码设计:如何将参数收集到字符串中(避免可能出现的重复声明错误)

puppet 代码设计:如何将参数收集到字符串中(避免可能出现的重复声明错误)

我在 puppet(版本 5.5)代码设计方面遇到了麻烦。我编写了一个组件模块来处理 ucarp。它利用了模块eyp-systemd在 systemd 中注册 ucarp 服务。现在我想从两个管理不同服务的独立配置文件模块(在我的情况下实际上是 haproxy 和 bind9)中使用 ucarp 模块。本质上这看起来像这样:

class ucarp {
  systemd::service { 'ucarp':
    # list of parameters
  }
}

define ucarp::vip {
  # defines a virtual IP to be shared among several nodes
}

# ====================

class profile_haproxy {
  include ::ucarp
  ::ucarp::vip { 'haproxy': }
  # setup haproxy
}

# =====================

class profile_bind9 {
  include ::ucarp
  ::ucarp::vip { 'bind9': }
  # setup bind9
}

这很简单,而且效果很好。

现在实际问题是:最佳做法是将 ucarp 服务排在通过 ucarp 运行的服务之后。可以使用 after 参数来实现:

class ucarp(
  Array[String] $after,
) {
  systemd::service { 'ucarp':
    after => $after.join(' '),
    # list of other parameters
  }
}

这需要替换include ::ucarp

class { '::ucarp':
  after => ['haproxy'],
}

或者

class { '::ucarp':
  after => ['bind9'],
}

当然这会立即导致“重复声明”错误。

我实际上想要的是 ucarp 类的单一实例,它将所有after参数收集到单个字符串中,可以传递给 systemd::service。我该如何做呢?

目前我想到两种可能的解决方案:

  1. eyp-systemd,删除 after 参数并将其替换为已定义的类型,例如,systemd::service::after管理服务定义文件中的相应条目。我真的不想这样做。通常我不愿意修改 forge 模块,因为这会迫使我自己维护它们。在这种情况下,更改似乎也相当大(包括界面更改)。
  2. 在 ucarp 模块中引入我自己定义的类型ucarp::order_after,它不执行任何操作。配置文件模块将定义此类型的虚拟实例。然后,ucarp 类可以使用 puppetdb 查询来收集 的所有实例ucarp::order_after。这里最大的缺点是我只处理虚拟资源,而不处理导出的资源。因此实际上根本不需要涉及 puppetdb,这使得这种方法成为一种丑陋的解决方法。

进一步的解决方案受到 c4f4t0r 的启发:

  1. 引入一个 ucarp 配置文件模块,该模块的单一任务是使用正确的服务实例化 ucarp 组件类after。服务列表after由 hiera 提供:
    类 profile_ucarp (
      数组[字符串] $after,
    ){
      类 {'::ucarp':
        之后 => $之后,
      }
    }
    个人资料_ucarp.之后:
        -‘haproxy’
        -'bind9'
    
    其他配置文件类不再需要实例化该类ucarp- 消除了潜在的重复声明问题。我认为这个解决方案优于上述两个解决方案。但我仍然不满意,因为使用 hiera 修复仅与代码相关的问题是对 hiera 的滥用。

我希望还有其他我现在想不到的可能性。

答案1

您需要使用包含函数并将类参数放在层次中。

在您的配置文件模块中,您的类 profile::haproxy 和 profile::bind 只能是一个,因为您重复了类,因为您没有使用 hiera 来存储类参数

class profile::ucarp {
  contain ::ucarp
  contain ::ucarp::vip
}

class profile::haproxy {
  contain ::haproxy
}

 #now I can create a role using this profiles

class role::elb {
  contain ::profile::ucarp
  contain ::profile::haproxy
}

现在,在 hiera 中,您可以根据主机功能存储参数,如果您想避免错误,请尝试使用 puppet doc 角色和配置文件检查您的设计

来自 Puppet 文档

Having classes contain other classes can be very useful, especially in larger modules where you want to improve code readability by moving chunks of implementation into separate files.

    However, unlike resources, Puppet does not automatically contain classes when they are declared inside another class. This is because classes can be declared in several places via include and similar functions. Most of these places shouldn’t contain the class, and trying to contain it everywhere would cause huge problems.

    Instead, you must manually contain any classes that need to be contained.

相关内容