Согласно двухпроходной модели Chef, любой код внутри ruby-block, guard-блоков и lazy выполняется только во время выполнения.
У меня есть рецепт с тремя ресурсами.
Переменные, значения которыхназначаются на этапе компиляции.
require 'socket'
require 'down'
require 'net/http'
conf = `hostname`.chomp
vpn_ip_list = Socket.ip_address_list.select{ |ip| ip.ip_address.match(/^10.12/) }
!vpn_ip_list.empty? ? ip_addr = vpn_ip_list.first.ip_address : ip_addr = ""
1-й ресурс - Проверяет, назначен ли желаемый VPN-IP-адрес, используя код в блоке защиты, и, если он не назначен, загружает файл conf и уведомляет 2-й ресурс службы о перезапуске openvpn.Значения для переменных внутри защитного блока получаются на этапе компиляции.
ruby_block 'download_openvpn_conf' do
block do
attempt = 2
begin
retries ||= 0
tempfile = Down.download("http://some-url1/#{conf}",max_redirects: 0)
FileUtils.mv tempfile.path, "#{node['openvpn-conf-path']}/#{tempfile.original_filename}"
FileUtils.chmod 0644, "#{node['openvpn-conf-path']}/#{tempfile.original_filename}"
rescue Down::Error => e
node.run_state['error'] = e.to_s
puts e
Chef::Log.warn ("\n \t ***********#{e}***********")
retry if (retries += 1) < 1
end
end
only_if {vpn_ip_list.size.eql?(0) || vpn_ip_list.size >= 2}
action :run
notifies :restart, 'service[openvpn]', :immediately
notifies :delete, "file[#{node['openvpn-conf-path']}/#{conf}]", :before
end
2-й ресурс - перезапускает службу openvpn.К этому времени IP-адрес VPN назначается системе.
service 'openvpn' do
supports :status => true, :restart => true, :start => true, :stop => true
action :nothing
Chef::Log.info ("\n \t *********Restarting OPEN-VPN*********")
end
Поскольку вышеуказанная услуга выполняется на этапе конвергенции, IP-адрес VPN должен быть назначен на основе загруженного файла конфигурации.
3-й ресурс - если IP-адрес VPN не назначен ко времени выполнения 2-го ресурса, это помещает запрос на новый файл конфигурации vpn.
ruby_block 'manual_vpn' do
block do
if node.run_state['error'] == "file not found"
Chef::Log.info ("\n \t ******** VPN IP has not been assigned. File may be corrupted & initiating re-run********")
uri = URI.parse("http://some-url2=#{host}&action=create")
Chef::Log.info (uri)
http = Net::HTTP.new(uri.host,uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
case response.body
when "error"
Chef::Log.info ("\n \t Website reported an Error. Config for the given serial number could have already been generated")
when "Request for vpn successfully added."
Chef::Log.warn ("\n \t **** Inside response processing => Request Accepted **")
Chef::Log.warn ("\n \t *** New vpn config request has been accepted. Waiting for 3 minutes ***")
sleep 180
else
Chef::Log.info ("\n \t Nothing to do - Extra option for future")
end
else
puts "Config file exists and hence not downloading"
end
end
notifies :run, 'ruby_block[re-download-vpn-conf]', :delayed
only_if { Socket.ip_address_list.select{ |ip| ip.ip_address.match(/^10.12/) }.size.eql?(0) }
not_if {node.run_state['error'].eql?("too many redirects")}
end
Проверен назначенный IP-адрес VPNпо коду в защитном блоке only_if { Socket.ip_address_list.select{ |ip| ip.ip_address.match(/^10.12/) }.size.eql?(0) }
и должен выполняться только во время выполнения.К концу 2-го выполнения ресурса IP-адрес VPN назначен точно, но код в вышеупомянутой защите не может его обнаружить.
Я использовал отладчик Pry в конце рецепта в тестовом блоке ruby, чтобы проверить этот IPназначается после выполнения 2-го ресурса перезапуска службы.Интересно, почему код внутри защитного блока Chef не может обнаружить VPN, назначенную предыдущим выполнением ресурса.