Chefspec заглушает Win32::Service в Linux

Наша кулинарная книга используется как на компьютерах с Linux, так и на Windows, и когда она работает/сходится, код отлично работает на обоих типах систем. Однако тест rake unit в Linux не проходит. У меня в рецепте:

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

Ошибка, которую мы получаем:

Неудачи:

  1. perfagent::install_windows Если установлено, что агент для установки в Windows успешно сходится Сбой/Ошибка: expect { chef_run }.to_not raise_error

    не ожидал исключения, получил #‹NameError: неинициализированная константа Win32› с обратной трассировкой: # /tmp/chefspec20200924-2530-350e0zfile_cache_path/cookbooks/perfagent/resources/install_agent.rb:83:in `блок (3 уровня) в class_from_file'

Возможно ли только для систем Linux фиктивное значение в моем файле спецификаций для only_if выше, чтобы мой модульный тест rake выполнялся успешно всякий раз, когда мы запускаем 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. Однако, когда мы запускаем rake unit в Linux, мы получаем указанную выше ошибку, а в Windows rake работает успешно.

Я пробовал добавить:

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

в спецификационный файл, но это по-прежнему не работает в Linux и приводит к сбою rake-модуля Windows.


person Geoff Harrison    schedule 24.09.2020    source источник


Ответы (2)


В случае вложенных классов заглушка немного сложнее. Вам также необходимо заглушить сам класс. Используйте для этого stub_const из RSpec:

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
person Draco Ater    schedule 25.09.2020
comment
Фантастический. Работает отлично. Модуль rake теперь успешно работает как в Linux, так и в Windows. Большое спасибо. - person Geoff Harrison; 25.09.2020

Внутри ресурсов Chef можно использовать if условия. Я не уверен, что элегантно использовать условные операторы для охранников, таких как only_if или not_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

Если ваша платформа ОС windows, то будет проверена защита only_if.


Обновлять:

Другой вариант — установить имя службы в соответствии с платформой и избавиться от only_if Guard. Что-то вроде этого:

# 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
person seshadri_c    schedule 24.09.2020
comment
К сожалению, я уже пробовал это, и я получаю ту же ошибку... :( - person Geoff Harrison; 25.09.2020
comment
Другой вариант — заранее установить имя службы в зависимости от платформы и использовать это имя в service <name> do. - person seshadri_c; 25.09.2020
comment
Добавлено обновление, чтобы дать представление о том, как поваренная книга запускает рассматриваемый рецепт. Также попытался добавить allow(Win32::Service).to receive(:exists?).with(windows_service[:name]).and_return(true) в файл спецификации, но это все еще не работает в Linux. - person Geoff Harrison; 25.09.2020