Skip to content

Commit e9a0a8b

Browse files
committed
Use --json for ip command output
1 parent 5204709 commit e9a0a8b

File tree

1 file changed

+25
-33
lines changed

1 file changed

+25
-33
lines changed

lib/linux_admin/network_interface.rb

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
require 'ipaddr'
2-
31
module LinuxAdmin
42
class NetworkInterface
3+
require "ipaddr"
4+
require "json"
5+
56
# Cached class instance variable for what distro we are running on
67
@dist_class = nil
78

@@ -60,14 +61,16 @@ def reload
6061
return false
6162
end
6263

63-
parse_ip4(ip_output)
64-
parse_ip6(ip_output, :global)
65-
parse_ip6(ip_output, :link)
64+
addr_info = ip_output["addr_info"]
65+
66+
parse_ip4(addr_info)
67+
parse_ip6(addr_info, "global")
68+
parse_ip6(addr_info, "link")
6669

67-
@network_conf[:mac] = parse_ip_output(ip_output, %r{link/ether}, 1)
70+
@network_conf[:mac] = ip_output["address"]
6871

6972
[4, 6].each do |version|
70-
@network_conf["gateway#{version}".to_sym] = parse_ip_output(ip_route(version), /^default/, 2)
73+
@network_conf["gateway#{version}".to_sym] = ip_route(version, "default")&.dig("gateway")
7174
end
7275
true
7376
end
@@ -168,23 +171,13 @@ def stop
168171

169172
private
170173

171-
# Parses the output of `ip addr show`
172-
#
173-
# @param output [String] The command output
174-
# @param regex [Regexp] Regular expression to match the desired output line
175-
# @param col [Fixnum] The whitespace delimited column to be returned
176-
# @return [String] The parsed data
177-
def parse_ip_output(output, regex, col)
178-
the_line = output.split("\n").detect { |l| l =~ regex }
179-
the_line.nil? ? nil : the_line.strip.split(' ')[col]
180-
end
181-
182174
# Runs the command `ip addr show <interface>`
183175
#
184176
# @return [String] The command output
185177
# @raise [NetworkInterfaceError] if the command fails
186178
def ip_show
187-
Common.run!(Common.cmd("ip"), :params => ["addr", "show", @interface]).output
179+
output = Common.run!(Common.cmd("ip"), :params => ["--json", "addr", "show", @interface]).output
180+
JSON.parse(output).first
188181
rescue AwesomeSpawn::CommandResultError => e
189182
raise NetworkInterfaceError.new(e.message, e.result)
190183
end
@@ -194,35 +187,34 @@ def ip_show
194187
# @param version [Fixnum] Version of IP protocol (4 or 6)
195188
# @return [String] The command output
196189
# @raise [NetworkInterfaceError] if the command fails
197-
def ip_route(version)
198-
Common.run!(Common.cmd("ip"), :params => ["-#{version}", 'route']).output
190+
def ip_route(version, route = "default")
191+
output = Common.run!(Common.cmd("ip"), :params => ["--json", "-#{version}", "route", "show", route]).output
192+
JSON.parse(output).first
199193
rescue AwesomeSpawn::CommandResultError => e
200194
raise NetworkInterfaceError.new(e.message, e.result)
201195
end
202196

203197
# Parses the IPv4 information from the output of `ip addr show <device>`
204198
#
205199
# @param ip_output [String] The command output
206-
def parse_ip4(ip_output)
207-
cidr_ip = parse_ip_output(ip_output, /inet /, 1)
208-
return unless cidr_ip
200+
def parse_ip4(addr_info)
201+
inet = addr_info.detect { |addr| addr["family"] == "inet" }
202+
return if inet.nil?
209203

210-
parts = cidr_ip.split('/')
211-
@network_conf[:address] = parts[0]
212-
@network_conf[:prefix] = parts[1].to_i
204+
@network_conf[:address] = inet["local"]
205+
@network_conf[:prefix] = inet["prefixlen"]
213206
end
214207

215208
# Parses the IPv6 information from the output of `ip addr show <device>`
216209
#
217210
# @param ip_output [String] The command output
218211
# @param scope [Symbol] The IPv6 scope (either `:global` or `:local`)
219-
def parse_ip6(ip_output, scope)
220-
cidr_ip = parse_ip_output(ip_output, /inet6 .* scope #{scope}/, 1)
221-
return unless cidr_ip
212+
def parse_ip6(addr_info, scope)
213+
inet6 = addr_info.detect { |addr| addr["family"] == "inet6" && addr["scope"] == scope }
214+
return if inet6.nil?
222215

223-
parts = cidr_ip.split('/')
224-
@network_conf["address6_#{scope}".to_sym] = parts[0]
225-
@network_conf["prefix6_#{scope}".to_sym] = parts[1].to_i
216+
@network_conf["address6_#{scope}".to_sym] = inet6["local"]
217+
@network_conf["prefix6_#{scope}".to_sym] = inet6["prefixlen"]
226218
end
227219
end
228220
end

0 commit comments

Comments
 (0)