Search code examples
rubychef-infrachef-recipe

How can I retrieve the netmask attribute from OHAI?


I need to be able to grab the netmask for an instance's interface when bootstrapping the instance. After running ohai on the instance, I have the following output that will supply the netmask:

 "network": {
    "interfaces": {
      "lo": {
        "mtu": "65536",
        "flags": [
          "LOOPBACK",
          "UP",
          "LOWER_UP"
        ],
        "encapsulation": "Loopback",
        "addresses": {
          "127.0.0.1": {
            "family": "inet",
            "prefixlen": "8",
            "netmask": "255.0.0.0",
            "scope": "Node"
          }
        },
        "state": "unknown"
      },
      "ens5": {
        "type": "ens",
        "number": "5",
        "mtu": "9001",
        "flags": [
          "BROADCAST",
          "MULTICAST",
          "UP",
          "LOWER_UP"
        ],
        "encapsulation": "Ethernet",
        "addresses": {
          "0E:D6:03:1B:8D:42": {
            "family": "lladdr"
          },
          "10.191.196.213": {
            "family": "inet",
            "prefixlen": "24",
            "netmask": "255.255.255.0",
             "broadcast": "10.191.196.255",
            "scope": "Global"
          }
         },...

I'm not getting the correct syntax, but I have found that I can get the IP address with this:

node[:network][:interfaces][:eth0][:addresses].detect{|k,v| v[:family] == "inet" }.first

Using this however, will not get the netmask:

node[:network][:interfaces][:ens192][:addresses][:netmask]

Any ideas on the correct ruby to get this value?

*Edit - using:

node["network"]["interfaces"]["ens192"]["addresses"].values.find { |i| i["family"] == "inet" }["netmask"]

I get this error:

    [2018-04-24T17:06:45-04:00] ERROR:

   Chef::Mixin::Template::TemplateError (undefined method `[]' for nil:NilClass) on line #9:
     7: DNS2=<%= node['dns_dtbg']['dns_servers_dtbg'][1] %>
     8: PEERDNS=no
     9: NETMASK=<%= node["network"]["interfaces"]["ens192"]["addresses"].values.find { |i| i["family"] == "inet" }["netmask"] %>
    10: TYPE=Ethernet

Solution

  • node[:network][:interfaces][:ens5][:addresses].detect do |k,v|
      v[:family]=='inet'
    end.last[:netmask]
    

    You could find out it by pasting your json to pry or irb, and check the result every time after adding another nested key fetch. Also, you can probably improve this answer by using Hash#dig.