我正在尝试解析文件中的值,以便将其设置为在配方中使用的属性(设置为子目录名称)。
该文件从jenkins服务器下载并在ruby块中解析以获取值 - 到目前为止一直很好。但是,如果我尝试将其分配给节点属性,则它不起作用。我以为我在这里找到了答案:How to lazily evaluate an arbitrary variable with Chef,但那里提到的方法都不适用于我。我做错了什么?
ruby_block "get build number" do
block do
f = File.open("/tmp/MyappJenkinsBuildInfo.txt")
f.each {|line|
line_arr = line.split('=')
if line_arr[0] == 'jenkins.build.number'
node.default['myapp']['jenkins']['build'] = line_arr[1]
break
end
}
f.close
end
end
build = DelayedEvaluator.new { node['myapp']['jenkins']['build'] }
release_dir = "#{node['myapp']['dir']['main']}/releases/#{build.call}"
这“有效”,因为没有语法错误,但#{build.call}的值是一个空字符串。该文件肯定存在,我已经测试过ruby块中的line_arr [1]获得了正确的值(在RB内部有一个puts语句)。我也尝试使用lambda代替DelayedEvaluator.new。
答案 0 :(得分:1)
这里的问题是您的release_dir =
行在编译时执行,在ruby_block
中的代码运行之前。显然,在那个时间点,build.call
只会返回一个空字符串,因为设置node['myapp']['jenkins']['build']
的代码尚未运行。
换句话说,配方中的代码就像这样执行:
# Compile time
ruby_block "get build number" do
block do
# Random stuff here that will get executed at converge time
end
end
build = DelayedEvaluator.new { node['myapp']['jenkins']['build'] }
release_dir = "#{node['myapp']['dir']['main']}/releases/#{build.call}"
# ...
# Okay, everything's compiled. Now we converge...
f = File.open("/tmp/MyappJenkinsBuildInfo.txt")
f.each {|line|
line_arr = line.split('=')
if line_arr[0] == 'jenkins.build.number'
node.default['myapp']['jenkins']['build'] = line_arr[1]
break
end
}
f.close
因此,要回答您的问题, 在收敛时设置节点属性。如果你这样做,你必须意识到在编译时访问该变量不可能,因为在编译时该变量尚未设置。在编译时设置变量,或者在收敛时间之前不要尝试访问它。不幸的是,你不能同时拥有两者。