hashicorp / go-sockaddr

IP Address/UNIX Socket convenience functions for Go
Mozilla Public License 2.0
266 stars 53 forks source link

Add math operation. #8

Closed sean- closed 7 years ago

sean- commented 7 years ago

Add the math operation to perform calculations on IPs and networks. … math takes two arguments: an operation and a string value. The two initial operations are address and network.

The address operation's value is a decimal encoded string with a mandatory sign. The value is added or subtracted from the IP address of the IfAddr. Values will overflow or underflow, and if necessary, wrap at the underlying fundamental type.

The network operation's value is a decimal encoded string with a mandatory sign. If the value is positive it is added to the network address of the IfAddr. If the value overflows the network size, the value is wrapped at the network boundary (i.e. 257 will wrap in a /24 to be the same as +1). If the value is negative it is subtracted from the broadcast address of the IfAddr. If the value underflows the network size, the value will wrap.

The network operation is intended to address the concern raised in #7 but in a more generic way and with IPv6 support, thereby superseding #7. For instance, to get the DNS resolver, one would simply use:

{{GetPrivateIP | math "network" "+2"}}

Thank you @taylorchu for the feature request. Can you let me know if this PR meets your needs? I know it scratches my back in terms of something that I've needed for a while now.

jwreagor commented 7 years ago

The ability to have this kind of IP math within a template is extremely helpful, especially the sorting and maps plus math. Template format can get a little unwieldy (when parsing) but totally forgiving given the derived behavior.

👍

taylorchu commented 7 years ago

nice! Originally I thought about doing this, but math is really a feature for more work.

{{GetPrivateIP | math "network" "+2"}} should not work because the type does not match.

sean- commented 7 years ago

@taylorchu That's correct, it doesn't work (GetPrivateIP returns a string not an IfAddrs). You have to do the following:

{{ GetPrivateInterfaces | math "network" "+2" }}

Does that work for you?

sean- commented 7 years ago

@cheapRoc Yeah, I don't like the Go template language, but I do like that "it just works" and pseudo-standard. I wish it had type support and all arguments didn't need to get passed in as strings, but I digress. There are helper functions along the way that help do the right or sane things. A GetPrivateInterface that only returns an IfAddr (vs IfAddrs) would be a nice addition, but you can get that with a GetPrivateInterfaces | sort ... | limit "1" | math "network" "+2". If there was a different way of doing this that addressed the necessary site complexities inherent in networking, I'd be all for it. LMK if you come up w/ anything. :)

taylorchu commented 7 years ago

sockaddr eval 'GetPrivateInterfaces | math "network" "+2" | attr "address"'

this works perfectly.

taylorchu commented 7 years ago

I will be nice if more helper functions work in the space of "IfAddrs/IfAddr" instead of "string" because string is simply not chainable. If we need string, we could use attr. my 2c.

sean- commented 7 years ago

@taylorchu This is one of the rubs of text/template. IfAddr/IfAddrs is a container of sorts. There should be top-level Parse, ParseIP, ParseIPv4, ParseIPv6, and ParseUNIXSocket functions that emit an IfAddr so that you could do something like:

{{ GetPrivateIP | ParseIP | Attr "address" }}

Where the chain is string -> IfAddr -> string, and the following would now work:

{{ ParseIP "127.0.0.1" | Attr "address" }}

Which would emit 127.0.0.1.