Chefspec 剔除 Win32::Service 是 Linux

Chefspec Stubbing out Win32::Service on Linux

我们的食谱在 Linux 和 Windows 机器上使用,当它 runs/converges 时,代码 运行 在两种类型的系统上都完美。然而 rake 单元 测试在 Linux 上失败。在我的食谱中我有:

service 'MyService' do
  action %i[enable start]
  only_if { ::Win32::Service.exists?("MyService") }
  not_if { ::File.exist?("#{install_dir}\scripts\instance-stopped") }
end

我们得到的错误是:

Failures:

  1. perfagent::install_windows When set to install agent on Windows converges successfully Failure/Error: expect { chef_run }.to_not raise_error

    expected no Exception, got #<NameError: uninitialized constant Win32> with backtrace: # /tmp/chefspec20200924-2530-350e0zfile_cache_path/cookbooks/perfagent/resources/install_agent.rb:83:in `block (3 levels) in class_from_file'

是否有可能,对于 Linux 系统,在我的规范文件中为上面的“only_if”虚拟出值,以便我的 rake 单元测试在我们 运行 Linux?

上的耙子

更新:

由于说明书在 Linux 和 Windows 系统上执行,我们在说明书执行的早期进行检查,例如:

if node['platform_family'] == 'windows'
  include_recipe 'cookbook::install_windows'
elsif node['platform_family'] == 'rhel'
  include_recipe 'cookbook::install_linux'
else
  log "This OS family (#{node['platform_family']})  is not supported" do
    level :info
  end
end

这意味着食谱只根据platform_family调用相关食谱。但是,当我们在 Linux 上 运行 rake 单元时,我们会收到上述错误,而在 Windows 上,rake 成功。

我试过添加:

allow(::Win32::Service).to receive(:exists?).with(windows_service[:name]).and_return(true)

到规范文件,但这在 Linux 上仍然失败并导致 Windows rake 单元也失败。

可以在 Chef 资源中使用 if 条件。我不确定对像 only_ifnot_if 这样的守卫使用条件是否优雅(它们本身是条件)。

但您可以执行以下操作:

service 'MyService' do
  action %i[enable start]
  if node['platform'] == 'windows'
    only_if { ::Win32::Service.exists?("MyService") }
  end
  not_if { ::File.exist?("#{install_dir}\scripts\instance-stopped") }
end

如果您的 OS 平台是 windows 只有 only_if 守卫才会被检查。


更新:

其他选项是根据平台设置服务名称并去掉 only_if 守卫。像这样:

# Set the service name appropriate to platform
svc_name = case node['platform']
when 'windows'
  'MyService'
when 'linux'
  'my-service'
end

# Then use the service name that was set:
service svc_name do
  action [ :enable, :start ]
  not_if { ::File.exist?("#{install_dir}\scripts\instance-stopped") }
end

在嵌套 classes 的情况下,存根有点复杂。您还需要存根 class 本身。使用 stub_const from the RSpec for that:

let :subject do
  fake_win32 = Class.new
  stub_const('Win32::Service', fake_win32)
  allow(fake_win32).to receive(:exists?).and_return false
  ChefSpec::Runner.new(platform: 'windows', version: '2008R2').converge described_recipe
end