Search code examples
loopsattributeschef-infraohai-gem

Iterating over a Chef array and using key in Ohai lookup


I'm iterating over an array, and would like to use the key as part of the logic to lookup an Ohai value. In my particular case, I'm attempting to source each defined user's .bashrc if triggered from a previous resource.

Ohai structure:

"etc": { "passwd": { "root": { "dir": "/root", "gid": 0, "uid": 0, "shell": "/bin/bash", "gecos": "root" }, ... "foo": { "dir": "/home/foo", "gid": 501, "uid": 501, "shell": "/bin/bash", "gecos": "" }, ...

So as I loop through, I am trying to do something like:

node['my_cookbook']['managed_users'].each do |usr| bash 'reload_shell' do code "source #{node['etc']['passwd'][usr]['dir']}/.bashrc" action :nothing end end

I've tried also using ['usr'], [#{usr}], and ["usr"] notations, as well as escaping quotes.


Solution

  • To iterate over a hash in ruby and access the key you can do:

    node['my_cookbook']['managed_users'].each do |usr,props|
      bash 'reload_shell' do
        code "source #{node['etc']['passwd'][usr]['dir']}/.bashrc"
        action :nothing
      end
    end
    

    If you don't care about the key or the values under it, replace the corresponding variable by _ i.e. in your case:

    node['my_cookbook']['managed_users'].each do |usr,_|
      bash 'reload_shell' do
        code "source #{node['etc']['passwd'][usr]['dir']}/.bashrc"
        action :nothing
      end
    end
    

    Without doing this, you get the full underlying hash, so your usr var is

    {
      "root": {
        "dir": "/root",
        "gid": 0,
        "uid": 0,
        "shell": "/bin/bash",
        "gecos": "root"
    }
    

    instead of being just "root".

    Side note: sourcing works for the current shell, within a bash resource the shell is spawned, command executed and the shell is closed. Sourcing a file will have no effect (unless there's a complex processus inside the .bash_rc doing something, this won't affect the system nor the chef run)