Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower & upper IP tool #155

Merged
merged 11 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ipinfo/cmd_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
var completionsTool = &complete.Command{
Sub: map[string]*complete.Command{
"aggregate": completionsToolAggregate,
"lower": completionsToolLower,
"upper": completionsToolUpper,
},
Flags: map[string]complete.Predictor{
"-h": predict.Nothing,
Expand All @@ -27,6 +29,8 @@ func printHelpTool() {
Commands:
aggregate aggregate IPs, IP ranges, and CIDRs.

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
lower get start IP of IP, IP ranges, and CIDRs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lower get start IP of IP, IP ranges, and CIDRs.
lower get start IP of IPs, IP ranges, and CIDRs.

upper get end IP of IP, IP ranges, and CIDRs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
upper get end IP of IP, IP ranges, and CIDRs.
upper get end IP of IPs, IP ranges, and CIDRs.

Options:
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
--help, -h
show help.
Expand Down Expand Up @@ -56,6 +60,10 @@ func cmdTool() error {
switch {
case cmd == "aggregate":
err = cmdToolAggregate()
case cmd == "lower":
err = cmdToolLower()
case cmd == "upper":
err = cmdToolUpper()
default:
err = toolHelp()
}
Expand Down
56 changes: 56 additions & 0 deletions ipinfo/cmd_tool_lower.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"fmt"

"github.com/ipinfo/cli/lib"
"github.com/ipinfo/cli/lib/complete"
"github.com/ipinfo/cli/lib/complete/predict"
"github.com/spf13/pflag"
)

var completionsToolLower = &complete.Command{
Flags: map[string]complete.Predictor{
"-h": predict.Nothing,
"--help": predict.Nothing,
"-q": predict.Nothing,
"--quiet": predict.Nothing,
},
}

func printHelpToolLower() {
fmt.Printf(
`Usage: %s tool lower [<opts>] <cidr>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not just <cidr> now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also we allow files too now right?


Description:
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
Calculates the lower IP address (start address of a network) for the given inputs.
Input can be IP, IP range or CIDR.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Input can be IP, IP range or CIDR.
Inputs can be a mixture of IPs, IP ranges or CIDRs.


If input contains CIDRs, it calculates the lower IP address for each CIDR.
If input contains IP ranges, it calculates the lower IP address for each Ip range.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove these above 2 description lines, they're redundant


Examples:
# Calculate lower IP for IP, IP range and CIDR.
$ %[1]s tool lower 192.168.1.0/24

# Calculate lower IPs for IPs, IP ranges and CIDRs.
$ %[1]s tool lower 192.168.1.0/24 10.0.0.0/16

# Calculate lower IPs from stdin.
$ cat /path/to/file.txt | %[1]s tool lower

Options:
--help, -h
show help.
--quiet, -q
quiet mode; suppress additional output.
`, progBase)
}

func cmdToolLower() (err error) {
f := lib.CmdToolLowerFlags{}
f.Init()
pflag.Parse()

return lib.CmdToolLower(f, pflag.Args()[2:], printHelpToolLower)
}
55 changes: 55 additions & 0 deletions ipinfo/cmd_tool_upper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"fmt"

"github.com/ipinfo/cli/lib"
"github.com/ipinfo/cli/lib/complete"
"github.com/ipinfo/cli/lib/complete/predict"
"github.com/spf13/pflag"
)

var completionsToolUpper = &complete.Command{
Flags: map[string]complete.Predictor{
"-h": predict.Nothing,
"--help": predict.Nothing,
"-q": predict.Nothing,
"--quiet": predict.Nothing,
},
}

func printHelpToolUpper() {
fmt.Printf(
`Usage: %s tool upper [<opts>] <cidr>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not just <cidr> now


Description:
Calculates the upper IP address (end address of a network) for the given inputs.
Input can be Ip, IP range or CIDR.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Input can be Ip, IP range or CIDR.
Inputs can be a mixture of IPs, IP ranges or CIDRs.


If input contains CIDRs, it calculates the upper IP address for each CIDR.
If input contains Ip ranges, it calculates the upper IP address for each IP range.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove these above 2 description lines, they're redundant

Examples:
# Calculate upper IP for IP, IP range and CIDR.
$ %[1]s tool upper 192.168.1.0/24

# Calculate upper IPs for IPs, IP ranges and CIDRs.
$ %[1]s tool upper 192.168.1.0/24 10.0.0.0/16

# Calculate upper IPs from stdin.
$ cat /path/to/file.txt | %[1]s tool upper

Options:
--help, -h
Show help.
--quiet, -q
Quiet mode; suppress additional output.
`, progBase)
}

func cmdToolUpper() (err error) {
f := lib.CmdToolUpperFlags{}
f.Init()
pflag.Parse()

return lib.CmdToolUpper(f, pflag.Args()[2:], printHelpToolUpper)
}
79 changes: 79 additions & 0 deletions lib/cmd_tool_lower.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package lib

import (
"fmt"
"net"
"os"

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
"github.com/spf13/pflag"
)

type CmdToolLowerFlags struct {
Help bool
Quiet bool
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
}

func (f *CmdToolLowerFlags) Init() {
pflag.BoolVarP(
&f.Help,
"help", "h", false,
"show help.",
)
pflag.BoolVarP(
&f.Quiet,
"quiet", "q", false,
"quiet mode; suppress additional output.",
)
}

func CmdToolLower(
f CmdToolLowerFlags,
args []string,
printHelp func(),
) error {
if f.Help {
printHelp()
return nil
}
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved

stat, _ := os.Stdin.Stat()
isStdin := (stat.Mode() & os.ModeCharDevice) == 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

if len(args) == 0 && !isStdin {
printHelp()
return nil
}

if isStdin {
return scanrdr(os.Stdin, processIPRangeOrCIDRLower)
}

for _, input := range args {
if err := processIPRangeOrCIDRLower(input); err != nil {
return err
}
}
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
func processIPRangeOrCIDRLower(input string) error {
if ipRange, err := IPRangeStrFromStr(input); err == nil {
// If it's an IP range, print the starting IP in the range.
fmt.Printf("%s\n", ipRange.Start)
return nil
}

if ip := net.ParseIP(input); ip != nil {
// If it's a simple IP address, print the IP itself.
fmt.Printf("%s\n", ip)
return nil
}

if _, ipnet, err := net.ParseCIDR(input); err == nil {
// If it's a CIDR, print the Starting IP address of the CIDR.
fmt.Printf("%s\n", ipnet.IP)
return nil
}

return fmt.Errorf("invalid input: %s", input)
}
81 changes: 81 additions & 0 deletions lib/cmd_tool_upper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package lib

import (
"fmt"
"net"
"os"

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
"github.com/spf13/pflag"
)

type CmdToolUpperFlags struct {
Help bool
Quiet bool
}

func (f *CmdToolUpperFlags) Init() {
pflag.BoolVarP(
&f.Help,
"help", "h", false,
"show help.",
)
pflag.BoolVarP(
&f.Quiet,
"quiet", "q", false,
"quiet mode; suppress additional output.",
)
}

func CmdToolUpper(
f CmdToolUpperFlags,
args []string,
printHelp func(),
) error {
if f.Help {
printHelp()
return nil
}
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved

stat, _ := os.Stdin.Stat()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
stat, _ := os.Stdin.Stat()
stat, _ := os.Stdin.Stat()

isStdin := (stat.Mode() & os.ModeCharDevice) == 0

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
if len(args) == 0 && !isStdin {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(args) == 0 && !isStdin {
if len(args) == 0 && !isStdin {

printHelp()
return nil
}

if isStdin {
return scanrdr(os.Stdin, processIPRangeOrCIDRUpper)
}
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved

for _, input := range args {
if err := processIPRangeOrCIDRUpper(input); err != nil {
return err
}
}
return nil
}

func processIPRangeOrCIDRUpper(input string) error {
ipRange, err := IPRangeStrFromStr(input)
if err == nil {
fmt.Println(ipRange.End)
return nil
}

if ip := net.ParseIP(input); ip != nil {
fmt.Println(input)
return nil
}

if _, ipnet, err := net.ParseCIDR(input); err == nil {
ipRange, err := IPRangeStrFromCIDR(ipnet.String())
if err == nil {
fmt.Println(ipRange.End)
return nil
}
}

fmt.Printf("Error parsing input: %v\n", err)
return err
}
36 changes: 36 additions & 0 deletions lib/cmd_tool_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package lib

import (
"bufio"
"io"
"strings"
)

// Function type for the callback used in scanrdr
type CIDRProcessor func(string) error

// Function to read lines from the io.Reader and process each line as a CIDR using the provided callback function
func scanrdr(r io.Reader, processCIDR CIDRProcessor) error {
buf := bufio.NewReader(r)
for {
d, err := buf.ReadString('\n')
if err == io.EOF {
if len(d) == 0 {
break
}
} else if err != nil {
return err
}

sepIdx := strings.IndexAny(d, "\n")
if sepIdx == -1 {
sepIdx = len(d)
}

cidrStr := d[:sepIdx]
if err := processCIDR(cidrStr); err != nil {
return err
}
}
return nil
}