2

我们将 Puppet(v3.6.2) 与 Foreman enc 一起使用,并且有很多自定义模块,其模式如下图模块所示;

#mkdir/manifests/init.pp
class mkdir ($path, $mode) {
  class {'mkdir::file': }
}

#mkdir/manifests/file.pp
class mkdir::file {
  file {$mkdir::path:
    ensure => 'directory',
    mode   => $mkdir::mode,
  }
}

#mkdir/spec/classes/mkdir_spec.rb
require 'spec_helper'
describe 'mkdir' do
  let(:params) {{ :path=>'/foo', :mode=>'777' }}
  it { should contain_class( 'mkdir::file' ) }
end

# All good so far, but here's the rub
# mkdir/spec/classes/file_spec.rb
require 'spec_helper'
describe 'mkdir::file' do
  # how can I set $mkdir::path and $mkdir::mode???
  let(:params) {{ :path=>'/bar', :mode=>'555' }}

  it { should contain_file('/bar').with({
    mode=>'555' })
  }
end

正如代码注释所说,如何在 file_spec 测试中设置模块参数 $mkdir::path 和 $mkdir::mode ?

显然,可以重构模块以将所有需要的参数传递给每个子类,如果这是唯一的方法,我会这样做,但似乎不可能没有办法测试这种模式。

我还看到了很多使用 module::params 模式的示例,这对于使用 hiera 的安装来说无疑是一个干净的模式,但是我无法使该模式适用于 Foreman,而且充其量需要包括两个每个参数化模块的木偶类很难看。

4

2 回答 2

3

你的结论是对的。但是params类模式独立于您的节点级配置方案。可能可以将 Hiera 更紧密地绑定到其中,但这是您通常想要做的:

  1. params在类中定义默认值。默认值可能取决于 Fact 值,例如$osfamily.
  2. 将模块的主类设为类inheritparams并将其中声明的变量params用作模块类参数的默认值。
  3. 使用 ENC 时,请确保将节点变量数据作为参数值传递给模块,以便params在适当的情况下覆盖类的默认值。
  4. 使模块类将所有必要的配置数据分别转发给模块中的每个类。

例如:

class mkdir::params {
    case $osfamily {
        'Debian': { $path = '/usr/share/foo' }
        'RedHat': { $path = '/var/lib/foo' }
        default:  { fail "The $osfamily platform is not supported by the mkdir module." }
    }
    $mode = 644
}

class mkdir($mode = $mkdir::params::mode,
            $path = $mkdir::params::path) inherits mkdir::params
{
    class { 'mkdir::file': mode => $mode, path => $path }
}

class mkdir::file($path, $mode) {
    # ...
}

那么编写测试应该非常简单。

于 2014-11-26T11:38:25.783 回答
0

重构和使用 Felix 的解决方案可能是更好的解决方案,但对于后代来说,另一个选择是:

#spec_helper.rb
def setup_mkdir(p_mode, p_path)
  return "class { 'mkdir':
                    mode => p_mode
                    path => p_path}"
end

# mkdir/spec/classes/file_spec.rb
require 'spec_helper'
describe 'mkdir::file' do
  let(:pre_condition) do
    [ setup_mkdir('555', '/bar') ]
  end

  it { should contain_file('/bar').with({
    mode=>'555' })
  }
end

关键是在一个pre_condition块中模拟基类。不要重复自己并将类模拟放在参数化方法中。

于 2015-07-13T07:48:47.463 回答