how do I convert int32 IP address into octets in ruby? - ruby

I'm looking for the opposite to this:
require 'ipaddr'
ip = IPAddr.new "10.0.2.15"
ip.to_i # 167772687
I need to pass something like 167772687, and want to get back "10.0.2.15".
This:
ip = IPAddr.new 167772687
returns the error:
IPAddr::AddressFamilyError: address family must be specified
How to I specify that I'm passing int32?

OK, found the answer:
require 'ipaddr'
ip = IPAddr.new(167772687, family = Socket::AF_INET)
ip.to_s # "10.0.2.15"

Related

Getting domain host name in ruby

Is there a possible way to get the domain's hostname in ruby?
For example:
$ host api.heroku.com
api.heroku.com is an alias for api-default.herokussl.com.
api-default.herokussl.com is an alias for elb027033-298234319.us-east-1.elb.amazonaws.com.
elb027033-298234319.us-east-1.elb.amazonaws.com has address 23.23.76.65
elb027033-298234319.us-east-1.elb.amazonaws.com has address 23.21.240.208
elb027033-298234319.us-east-1.elb.amazonaws.com has address 107.22.242.236
host would be the best example, because it'll also show if the domain/subdomain is pointing to another host like amazonAWS or etc.
not as useful as executing host domain.com command from ruby
I beg to differ... (but it does involve knowing what data you want, and how DNS works).
require 'resolv'
def host(address)
Resolv::DNS.open do |dns|
loop do
ress = dns.getresources address, Resolv::DNS::Resource::IN::CNAME
break if ress.empty?
canonical_name = ress.first.name.to_s
puts "#{address} is an alias for #{canonical_name}"
address = canonical_name
end
ress = dns.getresources address, Resolv::DNS::Resource::IN::A
addresses = ress.each do |r|
puts "#{address} has address #{r.address.to_s}"
end
end
return
end
host("api.heroku.com")

Extracting individual IP addresses

How can I extract each individual IP address from the array below?
strList = ["10.5.5.5 - 10.5.5.8"]
The end result should look like this:
newList = ["10.5.5.5","10.5.5.6","10.5.5.7","10.5.5.8"]
Do you guys have any ideas?
You can do that as follows:
require 'ipaddr'
(IPAddr.new("10.5.5.5")..IPAddr.new("10.5.5.8")).map(&:to_s)
#=> ["10.5.5.5", "10.5.5.6", "10.5.5.7", "10.5.5.8]

search to return list of nodes ip in specific format in chef

I need to do a search in a chef recipe that returns the IP's of all nodes in this specific format
'IP','IP',etc
so far by searching I've come up with this but the output is not exactly in the format that I want and I don't know how to change it.
ip = Array.new
search(:node, "name:chef-node*") do |n|
n["network"]["interfaces"]["eth1"]["addresses"].each_pair do |address,value|
ip << address if value.has_key?("broadcast")
end if n["network"]["interfaces"]["eth1"]
end
the output is like this:
["10.22.33.33", "10.22.33.38", "10.21.33.24"]
and I need it like this:
'10.210.39.231','10.209.161.18','10.210.66.240'
How would I achieve that?
ip = ["10.22.33.33", "10.22.33.38", "10.21.33.24"]
ip.map { |x| "'#{x}'" }.join(',')
# => "'10.22.33.33','10.22.33.38','10.21.33.24'"
You have a nice Array or IPs. Just use method join over it.
ip = ["10.22.33.33", "10.22.33.38", "10.21.33.24"]
ip.join(",")

Creating a sequence of IP addresses if given a starting address

I need to write code to ping a sequence of 20 IP addresses if given a starting IP address (e.g 192.168.0.1). Each successive IP address should be one digit larger than the previous.
That's what IPAddr#succ is for:
require 'ipaddr'
ipaddr = IPAddr.new('192.168.0.1')
20.times do
ping ipaddr
ipaddr = ipaddr.succ
end
ip = "192.168.0.1"
ips = []
(0..20).each do |n|
temp = ip.split('.').map(&:to_i)
temp[3] = temp[3] + n
ips << temp.join('.')
end
puts ips

Ruby: get local IP (nix)

I need to get my IP (that is DHCP). I use this in my environment.rb:
LOCAL_IP = `ifconfig wlan0`.match(/inet addr:(\d*\.\d*\.\d*\.\d*)/)[1] || "localhost"
But is there rubyway or more clean solution?
A server typically has more than one interface, at least one private and one public.
Since all the answers here deal with this simple scenario, a cleaner way is to ask Socket for the current ip_address_list() as in:
require 'socket'
def my_first_private_ipv4
Socket.ip_address_list.detect{|intf| intf.ipv4_private?}
end
def my_first_public_ipv4
Socket.ip_address_list.detect{|intf| intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast? and !intf.ipv4_private?}
end
Both returns an Addrinfo object, so if you need a string you can use the ip_address() method, as in:
ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?
You can easily work out the more suitable solution to your case changing Addrinfo methods used to filter the required interface address.
require 'socket'
def local_ip
orig = Socket.do_not_reverse_lookup
Socket.do_not_reverse_lookup =true # turn off reverse DNS resolution temporarily
UDPSocket.open do |s|
s.connect '64.233.187.99', 1 #google
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
puts local_ip
Found here.
Here is a small modification of steenslag's solution
require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}

Resources