在运行时未执行主厨保护块ruby代码

问题描述 投票:1回答:1

根据Chef的两个传递模型,ruby-block中的任何代码,保护块和延迟只在运行时执行。

我有一个有三种资源的食谱。

在编译阶段分配其值的变量。

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 = ""

第一个资源 - 检查是否使用保护块中的代码分配了所需的VPN IP地址,如果未分配,则下载conf文件并通知第二个服务资源重新启动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

第二个资源 - 重新启动openvpn服务。此时VPN IP被分配给系统。

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

由于在收敛阶段执行上述服务,因此应根据下载的配置文件分配VPN IP地址。

第3个资源 - 如果在执行第2个资源时未分配VPN IP,则会发出新的vpn conf文件请求。

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 

分配的VPN IP由保护块only_if { Socket.ip_address_list.select{ |ip| ip.ip_address.match(/^10.12/) }.size.eql?(0) }中的代码检查,并且应该仅在运行时执行。在第二次资源执行结束时,VPN IP被确定分配,但上面的防护中的代码无法检测到它。

我在测试ruby块中的配方末尾使用了Pry调试器,以验证在执行第二个服务重启资源后分配了IP。想知道为什么Chef的保护块内的代码无法检测先前资源执行所分配的VPN。

ruby chef chef-recipe chef-solo
1个回答
0
投票

基本上问题是Chef不等待系统后服务资源执行的状态。如果服务启动并运行,Chef不会打扰,它只关心服务的执行。

这是一个典型的竞争状态的例子,厨师移动头来执行下一个资源。为了避免这种情况,我必须在红宝石块中引入所需的睡眠时间。另一种方法是添加一个until true条件,但这在我的情况下不起作用,因为厨师的红宝石块被无限地卡住了,尽管服务已启动并运行。

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  
© www.soinside.com 2019 - 2024. All rights reserved.