如何在收敛时更新 Chef 中的节点属性?
How to update a node attribute in Chef at converge time?
我正在尝试从文件中解析一个值,以便将其设置为一个属性,以便在配方中进一步使用(设置为子目录名称)。
该文件是从 jenkins 服务器下载的,并在 ruby 块中解析以获取值 - 到目前为止一切顺利。但是,如果我尝试将其分配给节点属性,它就不起作用。我以为我在这里找到了答案:How to lazily evaluate an arbitrary variable with Chef,但是那里提到的方法中有 none 对我有用。我做错了什么?
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}"
这个"works"没有语法错误,但是#{build.call}的值是一个空字符串。该文件肯定存在,并且我已经测试过 ruby 块内的 line_arr[1] 正在获得正确的值(在 RB 内有一个 puts 语句)。我也尝试过使用 lambda 代替 DelayedEvaluator.new.
这里的问题是你的 release_dir =
行在编译时被执行,在 你的 ruby_block
中的代码有 运行 .显然在那个时间点,build.call
只是去 return 一个空字符串,因为设置 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
因此,为了回答您的问题,您是在收敛时设置节点属性。如果你那样做,你必须意识到在编译时不可能访问那个变量,因为在编译时甚至还没有设置变量。要么在编译时设置变量,要么在收敛时不要尝试访问它。不幸的是,你不能两者兼得。
我正在尝试从文件中解析一个值,以便将其设置为一个属性,以便在配方中进一步使用(设置为子目录名称)。
该文件是从 jenkins 服务器下载的,并在 ruby 块中解析以获取值 - 到目前为止一切顺利。但是,如果我尝试将其分配给节点属性,它就不起作用。我以为我在这里找到了答案:How to lazily evaluate an arbitrary variable with Chef,但是那里提到的方法中有 none 对我有用。我做错了什么?
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}"
这个"works"没有语法错误,但是#{build.call}的值是一个空字符串。该文件肯定存在,并且我已经测试过 ruby 块内的 line_arr[1] 正在获得正确的值(在 RB 内有一个 puts 语句)。我也尝试过使用 lambda 代替 DelayedEvaluator.new.
这里的问题是你的 release_dir =
行在编译时被执行,在 你的 ruby_block
中的代码有 运行 .显然在那个时间点,build.call
只是去 return 一个空字符串,因为设置 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
因此,为了回答您的问题,您是在收敛时设置节点属性。如果你那样做,你必须意识到在编译时不可能访问那个变量,因为在编译时甚至还没有设置变量。要么在编译时设置变量,要么在收敛时不要尝试访问它。不幸的是,你不能两者兼得。