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 2 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
9 changes: 8 additions & 1 deletion 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 @@ -26,7 +28,8 @@ func printHelpTool() {

Commands:
aggregate aggregate IPs, IP ranges, and CIDRs.

lower lower IPs, IP ranges, and CIDRs.
upper upper 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 +59,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
66 changes: 66 additions & 0 deletions ipinfo/cmd_tool_lower.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
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 | ip | ip-range | filepath>
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved

Description:
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
Accepts IPs, IP ranges, and CIDRs, aggregating them efficiently.
Input can be IPs, IP ranges, CIDRs, and/or filepath to a file
containing any of these. Works for both IPv4 and IPv6.

If input contains single IPs, it tries to merge them into the input CIDRs,
otherwise they are printed to the output as they are.

IP range can be of format <start-ip><SEP><end-ip>, where <SEP> can either
be a ',' or a '-'.

Examples:
# Lower two CIDRs.
$ %[1]s tool lower 1.1.1.0/30 1.1.1.0/28

# Lower IP range and CIDR.
$ %[1]s tool lower 1.1.1.0-1.1.1.244 1.1.1.0/28

# Lower enteries from 2 files.
$ %[1]s tool lower /path/to/file1.txt /path/to/file2.txt

# Lower enteries from stdin.
$ cat /path/to/file1.txt | %[1]s tool lower

# Lower enteries from stdin and a file.
$ cat /path/to/file1.txt | %[1]s tool lower /path/to/file2.txt

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)
}
68 changes: 68 additions & 0 deletions ipinfo/cmd_tool_upper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// cmd_tool_upper.go

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 | ip | ip-range | filepath>
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved

Description:
Calculates the upper IP address (end address of a network) for the given inputs.
Input can be IPs, IP ranges, CIDRs, and/or filepath to a file containing any of these.
Works for both IPv4 and IPv6.

If input contains CIDRs, it calculates the upper IP address for each CIDR.
If input contains single IPs, it calculates the upper IP address for each IP.

IP range can be of format <start-ip><SEP><end-ip>, where <SEP> can either
be a ',' or a '-'.

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

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

# Calculate upper IPs for a range and a CIDR.
$ %[1]s tool upper 192.168.1.10-192.168.1.20 10.0.0.0/16

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

# 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)
}
Binary file added ipinfo/ipinfo
Copy link
Contributor

Choose a reason for hiding this comment

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

same, no binaries

Binary file not shown.
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"

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

"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
}

processCIDR := func(cidrStr string) error {
startIP, err := findStartIP(cidrStr)
if err != nil {
if !f.Quiet {
fmt.Printf("Error parsing CIDR: %v\n", err)
}
return nil
}

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
fmt.Println(startIP)
return nil
}
UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved

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

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

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

func findStartIP(cidrStr string) (string, error) {
ipRange, err := IPRangeStrFromCIDR(cidrStr)
if err != nil {
return "", err
}
return ipRange.Start, nil
}
77 changes: 77 additions & 0 deletions lib/cmd_tool_upper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package lib

import (
"fmt"
"os"

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

type CmdToolUpperFlags struct {
Help bool
Quiet bool
}

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
}

processCIDR := func(cidrStr string) error {
endIP, err := findEndIP(cidrStr)
if err != nil {
if !f.Quiet {
fmt.Printf("Error parsing CIDR: %v\n", err)
}
return nil
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't we return the error instead of nil?

}
fmt.Println(endIP)
return nil
}

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

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

UmanShahzad marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

// Functions
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 findEndIP(cidrStr string) (string, error) {
ipRange, err := IPRangeStrFromCIDR(cidrStr)
if err != nil {
return "", err
}
return ipRange.End, nil
}
35 changes: 35 additions & 0 deletions lib/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package lib
Copy link
Contributor

Choose a reason for hiding this comment

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

Please rename this file. You might name it utils.go. we can add more utility functions there in future.

Copy link
Contributor

Choose a reason for hiding this comment

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

As these functions are tool related So its better to move them in cmd_tool.go
(Please ignore above)


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

type CIDRProcessor func(string) error

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
}
}

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

return nil
}