Защитный блок Chef Guard не выполняется во время выполнения - PullRequest
1 голос
/ 06 марта 2019

Согласно двухпроходной модели 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, назначенную предыдущим выполнением ресурса.

1 Ответ

0 голосов
/ 13 марта 2019

По сути, проблема в том, что Chef не ждет состояния выполнения ресурса службы после службы. Шеф-повар не беспокоится о том, запущена ли служба, он просто заботится о ее выполнении.

Это классический пример условия гонки с шеф-поваром, перемещающим голову для выполнения следующего ресурса. Чтобы избежать этого, мне пришлось ввести желаемое время сна в рубиновом блоке. Другой подход заключается в добавлении условия until true, но в моем случае это не сработало, поскольку блок ruby ​​в шеф-поваре застрял бесконечно, хотя служба была запущена и работает.

service 'openvpn' do
   supports :status => true, :restart => true, :start => true, :stop => true
   action :nothing
   Chef::Log.info ("\n \t *********Restarting OPEN-VPN*********")
end


ruby_block 'wait for vpn ip' do
    block do
        Chef::Log.warn ("****************** Sleep block starts ********************")
        sleep 30
        Chef::Log.warn ("****************** Sleep block exits ********************")
    end 
    action :run
end

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  
...