Hi,
I've just started using Ruby last week and have a somewhat complex task to
complete in a short amount of time and nobody local to ask.
Here is what I'm trying to find:
Given two arrays containing IP addresses like the ones below, how would I
search for the first element in 'servers' that pattern matches and element
in 'nics' where only the first 2 parts of the IP addresses need to match,
like 192.168.*.* or 10.14.*.* or 98.139.*.*
I've got some kind of beginning with the code below but I'm stuck. Any
hints?
···
----------------
log_server = "nothing"
until log_server != "nothing" servers.each |thisip| do
# Consider only the first two parts of the 'thisip' IP address (192.168.*.*
or 10.14.*.* or 98.139.*.*)
# Compare it with each element in 'nics'
# Set 'log_server' equal to the first value of 'thisip' that pattern
matches an element in 'nics'
log_server = thisip
On Mon, Dec 12, 2011 at 3:41 PM, Chaim Keren-Tzion <chaim@intercomp.co.il> wrote:
Hi,
I've just started using Ruby last week and have a somewhat complex task to
complete in a short amount of time and nobody local to ask.
Here is what I'm trying to find:
Given two arrays containing IP addresses like the ones below, how would I
search for the first element in 'servers' that pattern matches and element
in 'nics' where only the first 2 parts of the IP addresses need to match,
like 192.168.*.* or 10.14.*.* or 98.139.*.*
I've got some kind of beginning with the code below but I'm stuck. Any
hints?
----------------
log_server = "nothing"
until log_server != "nothing" servers.each |thisip| do
# Consider only the first two parts of the 'thisip' IP address (192.168.*.*
or 10.14.*.* or 98.139.*.*)
# Compare it with each element in 'nics'
# Set 'log_server' equal to the first value of 'thisip' that pattern
matches an element in 'nics'
log_server = thisip
1. Write a method which receives two arguments (servers and nics of course).
2. Let the method start by preparing the data, i.e. #map both arrays
into something which is quicker to match.
3. iterate by doing servers_converted.each or maybe
servers_converted.each_with_index and returning from the method on
first match.
4. return nil at the end of the method (nothing found) or raise an
exception depending on the wanted semantics
Now, how to do the matching? I would not use regular expressions for
the matching as you really want to match numeric values. Conversion
could use ip.scan(/\d+/).map(&:to_i). You could use Array# to
obtain a two element Array from a four element Array.
You could as well search for a gem which deals with IP addresses.
Since the problem is so common chances are that such a beast exists.
Kind regards
robert
···
On Tue, Dec 13, 2011 at 12:41 AM, Chaim Keren-Tzion <chaim@intercomp.co.il> wrote:
Hi,
I've just started using Ruby last week and have a somewhat complex task to
complete in a short amount of time and nobody local to ask.
Here is what I'm trying to find:
Given two arrays containing IP addresses like the ones below, how would I
search for the first element in 'servers' that pattern matches and element
in 'nics' where only the first 2 parts of the IP addresses need to match,
like 192.168.*.* or 10.14.*.* or 98.139.*.*
I've got some kind of beginning with the code below but I'm stuck. Any
hints?
----------------
log_server = "nothing"
until log_server != "nothing" servers.each |thisip| do
# Consider only the first two parts of the 'thisip' IP address (192.168.*.*
or 10.14.*.* or 98.139.*.*)
# Compare it with each element in 'nics'
# Set 'log_server' equal to the first value of 'thisip' that pattern
matches an element in 'nics'
log_server = thisip
Rather than search for a gem, look no further than the standard library and you'll come across the IPAddr library. (It's been in there long before 1.9.3 so you're almost certain to have it.)
The /16 added to the mapping of nics is the number of bits in the network mask.
So translating Robert's approach:
1. Write a methods that receives two arguments, servers and nics (as arrays of IP strings). (Optionally, a third argument that gives the bits in the netmask, perhaps defaulting to 16.)
2. map the Strings to IPAddrs
3. detect (find) the first server having an IPAddr that is included in the nic's network.
4. (there is no step 4
-Rob
···
On Dec 13, 2011, at 5:12 AM, Robert Klemme wrote:
On Tue, Dec 13, 2011 at 12:41 AM, Chaim Keren-Tzion > <chaim@intercomp.co.il> wrote:
Hi,
I've just started using Ruby last week and have a somewhat complex task to
complete in a short amount of time and nobody local to ask.
Here is what I'm trying to find:
Given two arrays containing IP addresses like the ones below, how would I
search for the first element in 'servers' that pattern matches and element
in 'nics' where only the first 2 parts of the IP addresses need to match,
like 192.168.*.* or 10.14.*.* or 98.139.*.*
I've got some kind of beginning with the code below but I'm stuck. Any
hints?
----------------
log_server = "nothing"
until log_server != "nothing" servers.each |thisip| do
# Consider only the first two parts of the 'thisip' IP address (192.168.*.*
or 10.14.*.* or 98.139.*.*)
# Compare it with each element in 'nics'
# Set 'log_server' equal to the first value of 'thisip' that pattern
matches an element in 'nics'
log_server = thisip
end
----------------
I would approach this like this:
1. Write a method which receives two arguments (servers and nics of course).
2. Let the method start by preparing the data, i.e. #map both arrays
into something which is quicker to match.
3. iterate by doing servers_converted.each or maybe
servers_converted.each_with_index and returning from the method on
first match.
4. return nil at the end of the method (nothing found) or raise an
exception depending on the wanted semantics
Now, how to do the matching? I would not use regular expressions for
the matching as you really want to match numeric values. Conversion
could use ip.scan(/\d+/).map(&:to_i). You could use Array# to
obtain a two element Array from a four element Array.
You could as well search for a gem which deals with IP addresses.
Since the problem is so common chances are that such a beast exists.
I must say that Ruby is very elegant! I've been scripting in bash for years
but haven't used oop languages nearly as much and this is beyond!
The code was needed for a chef cookbook that will set the servers in our
network to use the preferred connection to our syslog server. (Can't
utilize DNS for this)
The three lines below will do all the decision making.
Note: "node[:syslogserver][:ip]" are attributes that I define in a "role"
"node.network.interfaces.map { |p, f| f[:addresses].keys }.flatten" will
get me the mac addresses and ips on the client that chef is running on
then I clean it up by removing the mac addresses (and perhaps the IPV6
addresses that will show up one day?) with "delete_if{|x| x =~ /(.*):(.*)/
}"
Thanks guys!!
Chaim
···
On Tue, Dec 13, 2011 at 3:13 PM, Rob Biedenharn <rob@agileconsultingllc.com>wrote:
On Dec 13, 2011, at 5:12 AM, Robert Klemme wrote:
> On Tue, Dec 13, 2011 at 12:41 AM, Chaim Keren-Tzion > > <chaim@intercomp.co.il> wrote:
>> Hi,
>> I've just started using Ruby last week and have a somewhat complex task
to
>> complete in a short amount of time and nobody local to ask.
>>
>> Here is what I'm trying to find:
>> Given two arrays containing IP addresses like the ones below, how would
I
>> search for the first element in 'servers' that pattern matches and
element
>> in 'nics' where only the first 2 parts of the IP addresses need to
match,
>> like 192.168.*.* or 10.14.*.* or 98.139.*.*
>>
>> servers = Array["192.168.0.251","10.14.0.142","98.139.180.149"]
>> nics = Array["10.10.0.255","173.194.37.16","10.14.0.170"]
>>
>> I've got some kind of beginning with the code below but I'm stuck. Any
>> hints?
>>
>> ----------------
>> log_server = "nothing"
>>
>> until log_server != "nothing" servers.each |thisip| do
>>
>> # Consider only the first two parts of the 'thisip' IP address
(192.168.*.*
>> or 10.14.*.* or 98.139.*.*)
>> # Compare it with each element in 'nics'
>> # Set 'log_server' equal to the first value of 'thisip' that pattern
>> matches an element in 'nics'
>> log_server = thisip
>>
>> end
>> ----------------
>
> I would approach this like this:
>
> 1. Write a method which receives two arguments (servers and nics of
course).
> 2. Let the method start by preparing the data, i.e. #map both arrays
> into something which is quicker to match.
> 3. iterate by doing servers_converted.each or maybe
> servers_converted.each_with_index and returning from the method on
> first match.
> 4. return nil at the end of the method (nothing found) or raise an
> exception depending on the wanted semantics
>
> Now, how to do the matching? I would not use regular expressions for
> the matching as you really want to match numeric values. Conversion
> could use ip.scan(/\d+/).map(&:to_i). You could use Array# to
> obtain a two element Array from a four element Array.
>
> You could as well search for a gem which deals with IP addresses.
> Since the problem is so common chances are that such a beast exists.
>
> Kind regards
>
> robert
>
> --
> remember.guy do |as, often| as.you_can - without end
> http://blog.rubybestpractices.com/
>
Rather than search for a gem, look no further than the standard library
and you'll come across the IPAddr library. (It's been in there long before
1.9.3 so you're almost certain to have it.)
The /16 added to the mapping of nics is the number of bits in the network
mask.
So translating Robert's approach:
1. Write a methods that receives two arguments, servers and nics (as
arrays of IP strings). (Optionally, a third argument that gives the bits in
the netmask, perhaps defaulting to 16.)
2. map the Strings to IPAddrs
3. detect (find) the first server having an IPAddr that is included in the
nic's network.
4. (there is no step 4