有没有办法遍历 Chef 食谱中的 node.run_state 数据?
Is there a way to iterate through node.run_state data in a Chef recipe?
有没有办法遍历 node.run_state 数据?
这是在具有 Active Directory 用户的 RHEL 环境中。
我有一个填充 node.run_state 的 ruby 块。我必须在收敛时使用此 运行,因为整个说明书将用于构建自动化。在第一个 运行 上,cookbook 安装了 Centrify,然后需要 运行 adquery 来收集用户信息以使用 SSH 密钥填充主目录。
在 chef-client 运行 上,我看到了这个:
Compiling Cookbooks...
{}
显然,这就是编译时针对空散列的 puts 运行ning。
在收敛时,2 个目录和 1 个模板资源的循环中没有任何反应。
这是食谱的相关部分:
ruby_block 'set uid, gid, and homedir for users' do
block do
base_attr['ssh_keys'].each do |user, pubkeys|
# next unless Dir.exist?(homedir)
node.run_state[user] = {}
puts "Checking user #{user}..."
if local_users.key?(user)
node.run_state[user]['homedir'] = local_users[user]['homedir']
node.run_state[user]['uid'] = local_users[user]['uid'].to_i
node.run_state[user]['gid'] = local_users[user]['gid'].to_i
elsif centrify_users.key?(user)
node.run_state[user]['homedir'] = centrify_users[user]['homedir']
node.run_state[user]['uid'] = centrify_users[user]['uid'].to_i
node.run_state[user]['gid'] = centrify_users[user]['gid'].to_i
else
puts "user #{user} not found."
# Place holder values.
node.run_state[user]['homedir'] = "/tmp/#{user}"
node.run_state[user]['uid'] = 0
node.run_state[user]['gid'] = 0
end
end
end
end
# Dir.exist? guard should bypass compile-time error.
# "name is a required property"
# next unless Dir.exist?(homedir)
puts node.run_state
node.run_state.each do |user|
directory node.run_state[user]['homedir'] do
owner node.run_state[user]['uid']
group node.run_state[user]['gid']
mode '0700'
end
directory "#{node.run_state[user]['homedir']}/.ssh" do
owner node.run_state[user]['uid']
group node.run_state[user]['gid']
mode '0700'
end
template "#{node.run_state[user]['homedir']}/.ssh/authorized_keys" do
owner node.run_state[user]['uid']
group node.run_state[user]['gid']
mode '0600'
source 'authorized_keys.erb'
variables(
sshkeys: base_attr['ssh_keys'][user]
)
end
end
有什么想法可以实现吗?
在 node.run_state 您使用它的地方添加惰性 {} 块。所以在你的目录和模板资源中。 lazy {} 确保资源在 Chef Infra Client 运行 的执行阶段进行评估(而不是在编译阶段)。您可以阅读有关惰性块的更多信息 here
由于你在执行阶段设置node.run_state
,你也需要在执行阶段阅读它。目前您的 node.run_state.each
被跳过,因为正如您正确指出的那样,node.run_state
是空的。
因此您需要将此 node.run_state.each
执行移至执行阶段。一种可能性是创建一个 ruby_block
并将你的循环移到那里,不幸的是你不能像食谱中那样使用那里的资源方法,但你可以直接使用资源 类:
ruby_block 'Create ssh authorized keys' do
block do
node.run_state.each do |user|
d = Chef::Resource::Directory.new(node.run_state[user]['homedir'], run_context)
d.owner node.run_state[user]['uid']
d.group node.run_state[user]['gid']
d.mode '0700'
d.run_action :create
d = Chef::Resource::Directory.new("#{node.run_state[user]['homedir']}/.ssh", run_context)
d.owner node.run_state[user]['uid']
d.group node.run_state[user]['gid']
d.mode '0700'
d.run_action :create
t = Chef::Resource::Template.new("#{node.run_state[user]['homedir']}/.ssh/authorized_keys", run_context)
t.owner node.run_state[user]['uid']
t.group node.run_state[user]['gid']
t.mode '0600'
t.source 'authorized_keys.erb'
t.variables(sshkeys: base_attr['ssh_keys'][user])
t.run_action :create
end
end
end
今天早上我的潜意识告诉我拉目录资源里面的路径,然后在上面使用 lazy。所以我有可行的解决方案。 node.run_state 在 ruby_block 中,并在使用 node.run_state 的后续资源中围绕必要属性进行惰性块。感谢您对此问题的反馈。
有没有办法遍历 node.run_state 数据? 这是在具有 Active Directory 用户的 RHEL 环境中。 我有一个填充 node.run_state 的 ruby 块。我必须在收敛时使用此 运行,因为整个说明书将用于构建自动化。在第一个 运行 上,cookbook 安装了 Centrify,然后需要 运行 adquery 来收集用户信息以使用 SSH 密钥填充主目录。
在 chef-client 运行 上,我看到了这个:
Compiling Cookbooks...
{}
显然,这就是编译时针对空散列的 puts 运行ning。 在收敛时,2 个目录和 1 个模板资源的循环中没有任何反应。
这是食谱的相关部分:
ruby_block 'set uid, gid, and homedir for users' do
block do
base_attr['ssh_keys'].each do |user, pubkeys|
# next unless Dir.exist?(homedir)
node.run_state[user] = {}
puts "Checking user #{user}..."
if local_users.key?(user)
node.run_state[user]['homedir'] = local_users[user]['homedir']
node.run_state[user]['uid'] = local_users[user]['uid'].to_i
node.run_state[user]['gid'] = local_users[user]['gid'].to_i
elsif centrify_users.key?(user)
node.run_state[user]['homedir'] = centrify_users[user]['homedir']
node.run_state[user]['uid'] = centrify_users[user]['uid'].to_i
node.run_state[user]['gid'] = centrify_users[user]['gid'].to_i
else
puts "user #{user} not found."
# Place holder values.
node.run_state[user]['homedir'] = "/tmp/#{user}"
node.run_state[user]['uid'] = 0
node.run_state[user]['gid'] = 0
end
end
end
end
# Dir.exist? guard should bypass compile-time error.
# "name is a required property"
# next unless Dir.exist?(homedir)
puts node.run_state
node.run_state.each do |user|
directory node.run_state[user]['homedir'] do
owner node.run_state[user]['uid']
group node.run_state[user]['gid']
mode '0700'
end
directory "#{node.run_state[user]['homedir']}/.ssh" do
owner node.run_state[user]['uid']
group node.run_state[user]['gid']
mode '0700'
end
template "#{node.run_state[user]['homedir']}/.ssh/authorized_keys" do
owner node.run_state[user]['uid']
group node.run_state[user]['gid']
mode '0600'
source 'authorized_keys.erb'
variables(
sshkeys: base_attr['ssh_keys'][user]
)
end
end
有什么想法可以实现吗?
在 node.run_state 您使用它的地方添加惰性 {} 块。所以在你的目录和模板资源中。 lazy {} 确保资源在 Chef Infra Client 运行 的执行阶段进行评估(而不是在编译阶段)。您可以阅读有关惰性块的更多信息 here
由于你在执行阶段设置node.run_state
,你也需要在执行阶段阅读它。目前您的 node.run_state.each
被跳过,因为正如您正确指出的那样,node.run_state
是空的。
因此您需要将此 node.run_state.each
执行移至执行阶段。一种可能性是创建一个 ruby_block
并将你的循环移到那里,不幸的是你不能像食谱中那样使用那里的资源方法,但你可以直接使用资源 类:
ruby_block 'Create ssh authorized keys' do
block do
node.run_state.each do |user|
d = Chef::Resource::Directory.new(node.run_state[user]['homedir'], run_context)
d.owner node.run_state[user]['uid']
d.group node.run_state[user]['gid']
d.mode '0700'
d.run_action :create
d = Chef::Resource::Directory.new("#{node.run_state[user]['homedir']}/.ssh", run_context)
d.owner node.run_state[user]['uid']
d.group node.run_state[user]['gid']
d.mode '0700'
d.run_action :create
t = Chef::Resource::Template.new("#{node.run_state[user]['homedir']}/.ssh/authorized_keys", run_context)
t.owner node.run_state[user]['uid']
t.group node.run_state[user]['gid']
t.mode '0600'
t.source 'authorized_keys.erb'
t.variables(sshkeys: base_attr['ssh_keys'][user])
t.run_action :create
end
end
end
今天早上我的潜意识告诉我拉目录资源里面的路径,然后在上面使用 lazy。所以我有可行的解决方案。 node.run_state 在 ruby_block 中,并在使用 node.run_state 的后续资源中围绕必要属性进行惰性块。感谢您对此问题的反馈。