I am working in Chef, trying to create/populate a ruby
hash with networking device information, as populated by nmcli
. I think the code is correct, as VS Code
isn't complaining, and it seems to run just fine in chef-shell -z
but I'm not able to query the Ruby Hash as I would expect, and I'm really starting to lose my mind.
Fresh eyes and any expert help here are appreciated, thank you!
interfaces = Hash.new
#DEVICE,TYPE
dev = Mixlib::ShellOut.new("nmcli -terse -field device,type device").run_command.stdout.split(/\n/)
dev.each do |output|
if "#{output.split(":")[1]}" == 'ethernet'
interfaces["ethernet" => "#{output.split(":")[0]}"]
elsif "#{output.split(":")[1]}" == 'wifi'
interfaces["wifi" => "#{output.split(":")[0]}"]
else
Chef::Log.debug("Interface #{output.split(":")} is not supported")
end
end
chef (17.6.18)>
=> ["wlp61s0:wifi", "enp0s31f6:ethernet", "lo:loopback"]
node[interfaces] #nil
node[:interfaces] #nil
node['interfaces'] #nil
node["interfaces"] #nil
When I attempt to edit the code, as suggested by BroiSatse
This line
interfaces["wifi" => "#{output.split(":")[0]}"]
returns the value stored in the hash under the key{"wifi" => "#>{output.split(":")[0]}"}
. It does not perform any assignment and most > likely returns nil.What you need is:
interfaces["wifi"] ="#{output.split(":")[0]}"
So I tried that, but I still get a nil response from the Hash. Here is the Chef output/error:
chef (17.6.18)> interfaces = Hash.new
chef > #DEVICE,TYPE
chef (17.6.18)> dev = Mixlib::ShellOut.new("nmcli -terse -field device,type device").run_command.stdout.split(/\n/)
=> ["wlp61s0:wifi", "enp0s31f6:ethernet", "lo:loopback"]
chef > dev.each do |output|
chef > if "#{output.split(":")[1]}" == 'ethernet'
chef > interfaces["ethernet"] = "#{output.split(":")[0]}"
chef > elsif "#{output.split(":")[1]}" == 'wifi'
chef > interfaces["wifi"] = "#{output.split(":")[0]}"
chef > else
chef > Chef::Log.debug("Interface #{output.split(":")} is not supported")
chef > end
chef (17.6.18)> end
=> ["wlp61s0:wifi", "enp0s31f6:ethernet", "lo:loopback"]
chef (17.6.18)> node[interfaces] #nil
=> nil
chef (17.6.18)> node[:interfaces][:ethernet] #nil
(irb):95:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
from /opt/chef/embedded/lib/ruby/gems/3.0.0/gems/chef-17.6.18/lib/chef/shell.rb:93:in `block in start'
from /opt/chef/embedded/lib/ruby/gems/3.0.0/gems/chef-17.6.18/lib/chef/shell.rb:92:in `catch'
from /opt/chef/embedded/lib/ruby/gems/3.0.0/gems/chef-17.6.18/lib/chef/shell.rb:92:in `start'
from /opt/chef/embedded/lib/ruby/gems/3.0.0/gems/chef-bin-17.6.18/bin/chef-shell:31:in `<top (required)>'
from /usr/bin/chef-shell:158:in `load'
from /usr/bin/chef-shell:158:in `<main>'
chef (17.6.18)> node['interfaces'] #nil
chef (17.6.18)> node["interfaces"] #nil
=> nil
chef (17.6.18)>
UPDATE: Monday May 2, 2022 12:08 PST
When I do this command I can see that there is data in the Hash ... but all attempts to actually query the data fail ... I don't know what I'm doing wrong:
chef (17.6.18)> puts "#{interfaces}"
{"wifi"=>"wlp61s0", "ethernet"=>"enp0s31f6"}
=> nil
chef (17.6.18)>
Since you are running this in Chef, you can use automatic attributes collected by Ohai, instead of running command to get its
stdout
.Comprehensive details about the machine's network configuration are stored under
node['network']['interfaces']
hash.Try this in your recipe to see what details are captured:
We can use these automatic attributes in combination with the
select
filter to get the network device names without looping.The above code will get the "first" device that matches
en
orwl
respectively. If there are multiple devices of a type, then.first
can be removed and the entire list of devices will be available.