2

有没有办法遍历 node.run_state 数据?这是在具有 Active Directory 用户的 RHEL 环境中。我有一个填充 node.run_state 的红宝石块。我必须在收敛时间运行这个,因为整个食谱将用于构建自动化。在第一次运行时,cookbook 会安装 Centrify,然后需要运行 adquery 来收集用户信息,以便使用 SSH 密钥填充主目录。

在厨师客户端运行时,我看到了这个:

       Compiling Cookbooks...
       {}

显然,这是针对空哈希在编译时运行的 put。在收敛时间,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

任何想法如何使这项工作?

4

3 回答 3

1

在你使用它的 node.run_state 周围添加惰性 {} 块。所以在你的目录和模板资源中。lazy {} 确保资源在 Chef Infra Client 运行的执行阶段(而不是在编译阶段)进行评估。您可以在此处阅读有关惰性块的更多信息

于 2020-05-28T17:34:37.220 回答
0

由于您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
于 2020-05-29T11:24:00.833 回答
0

今天早上我的潜意识告诉我要拉目录资源里面的路径,然后用lazy就可以了。所以我有工作解决方案。ruby_block 中的 node.run_state,以及使用 node.run_state 的后续资源中的必要属性周围的惰性块。感谢您对此问题的反馈。

于 2020-05-29T13:46:38.707 回答