Skip to content

Commit

Permalink
added list command to cli, along with new hosts methods ListHostsByIP…
Browse files Browse the repository at this point in the history
…, ListHostsByCIDR and ListAddressesByHost
  • Loading branch information
cjimti committed Jul 23, 2023
1 parent 171fcae commit fd6fec4
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 3 deletions.
49 changes: 48 additions & 1 deletion txeh.go
Expand Up @@ -267,7 +267,54 @@ func (h *Hosts) AddHost(addressRaw string, hostRaw string) {
h.Unlock()
}

// HostAddressLookup returns true is the host is found, a string
// ListHostsByIP returns a list of hostnames associated with a given IP address
func (h *Hosts) ListHostsByIP(address string) []string {
var hosts []string

for _, hsl := range h.hostFileLines {
if hsl.Address == address {
hosts = append(hosts, hsl.Hostnames...)
}
}

return hosts
}

// ListAddressesByHost returns a list of IPs associated with a given hostname
func (h *Hosts) ListAddressesByHost(hostname string, exact bool) [][]string {
var addresses [][]string

for _, hsl := range h.hostFileLines {
for _, hst := range hsl.Hostnames {
if hst == hostname {
addresses = append(addresses, []string{hsl.Address, hst})
}
if exact == false && hst != hostname && strings.Contains(hst, hostname) {
addresses = append(addresses, []string{hsl.Address, hst})
}
}
}

return addresses
}

// ListHostsByCIDR returns a list of IPs and hostnames associated with a given CIDR
func (h *Hosts) ListHostsByCIDR(cidr string) [][]string {
var ipHosts [][]string

_, subnet, _ := net.ParseCIDR(cidr)
for _, hsl := range h.hostFileLines {
if subnet.Contains(net.ParseIP(hsl.Address)) {
for _, hst := range hsl.Hostnames {
ipHosts = append(ipHosts, []string{hsl.Address, hst})
}
}
}

return ipHosts
}

// HostAddressLookup returns true if the host is found, a string
// containing the address and the index of the hfl
func (h *Hosts) HostAddressLookup(host string, ipFamily IPFamily) (bool, string, int) {
h.Lock()
Expand Down
28 changes: 28 additions & 0 deletions util/cmd/list.go
@@ -0,0 +1,28 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(listCmd)
}

var listCmd = &cobra.Command{
Use: "list [BY_TYPE] [IP|CIDR] [IP|CIDR] [IP|CIDR] ...",
Short: "List hostnames for a IP addresses or CIDRs",
Long: `List hostnames for a IP addresses or CIDRs present in /etc/hosts`,
Run: func(cmd *cobra.Command, args []string) {
err := cmd.Help()
if err != nil {
fmt.Printf("Error: can not display help, reason: %s\n", err.Error())
os.Exit(1)
}

fmt.Println("Please specify a sub-command such as \"ip\" or \"cidr\"")
os.Exit(1)
},
}
40 changes: 40 additions & 0 deletions util/cmd/list_cidr.go
@@ -0,0 +1,40 @@
package cmd

import (
"errors"
"fmt"
"github.com/spf13/cobra"
)

func init() {
listCmd.AddCommand(listByCidrCmd)
}

var listByCidrCmd = &cobra.Command{
Use: "cidr [CIDR] [CIDR] [CIDR]...",
Short: "List hosts for one or more CIDRs",
Long: `List hosts for one or more CIDRs from /etc/hosts`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("the \"list cidr\" command requires at least one CIDR address")
}

if ok, cidr := validateCIDRs(args); !ok {
return errors.New(fmt.Sprintf("\"%s\" is not a valid CIDR", cidr))
}

return nil
},
Run: func(cmd *cobra.Command, args []string) {
ListByCIDRs(args)
},
}

func ListByCIDRs(cidrs []string) {
for _, cidr := range cidrs {
ipHosts := etcHosts.ListHostsByCIDR(cidr)
for _, ih := range ipHosts {
fmt.Printf("%s %s %s\n", cidr, ih[0], ih[1])
}
}
}
43 changes: 43 additions & 0 deletions util/cmd/list_hosts.go
@@ -0,0 +1,43 @@
package cmd

import (
"errors"
"fmt"
"github.com/spf13/cobra"
)

var exactHost bool

func init() {
listCmd.AddCommand(listByHostsCmd)
listByHostsCmd.PersistentFlags().BoolVarP(&exactHost, "exact", "e", false, "use -e for exact match")
}

var listByHostsCmd = &cobra.Command{
Use: "host [hostname] [hostname] [hostname]...",
Short: "List IP for one or more hostnames",
Long: `List IP for one or more hostnames from /etc/hosts`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("the \"list host\" command requires at least one hostname")
}

if ok, cidr := validateHostnames(args); !ok {
return errors.New(fmt.Sprintf("\"%s\" is not a valid hostname", cidr))
}

return nil
},
Run: func(cmd *cobra.Command, args []string) {
ListByHostnames(args)
},
}

func ListByHostnames(hostnames []string) {
for _, hn := range hostnames {
addrHosts := etcHosts.ListAddressesByHost(hn, exactHost)
for _, addrHost := range addrHosts {
fmt.Printf("%s %s\n", addrHost[0], addrHost[1])
}
}
}
40 changes: 40 additions & 0 deletions util/cmd/list_ip.go
@@ -0,0 +1,40 @@
package cmd

import (
"errors"
"fmt"
"github.com/spf13/cobra"
)

func init() {
listCmd.AddCommand(listByIpCmd)
}

var listByIpCmd = &cobra.Command{
Use: "ip [IP] [IP] [IP]...",
Short: "List hosts for one or more IP addresses",
Long: `List hosts for one or more IP addresses from /etc/hosts`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("the \"list ip\" command requires at least one IP address")
}

if ok, ip := validateIPAddresses(args); !ok {
return errors.New(fmt.Sprintf("\"%s\" is not a valid ip address", ip))
}

return nil
},
Run: func(cmd *cobra.Command, args []string) {
ListByIPs(args)
},
}

func ListByIPs(ips []string) {
for _, ip := range ips {
hosts := etcHosts.ListHostsByIP(ip)
for _, h := range hosts {
fmt.Printf("%s %s\n", ip, h)
}
}
}
4 changes: 2 additions & 2 deletions util/cmd/remove_cidr.go
Expand Up @@ -23,8 +23,8 @@ var removeCidrCmd = &cobra.Command{
return errors.New("the \"remove cidr\" command requires at least one CIDR range to remove")
}

if ok, ip := validateCIDRs(args); !ok {
return errors.New(fmt.Sprintf("\"%s\" is not a valid CIDR", ip))
if ok, cidr := validateCIDRs(args); !ok {
return errors.New(fmt.Sprintf("\"%s\" is not a valid CIDR", cidr))
}

return nil
Expand Down

0 comments on commit fd6fec4

Please sign in to comment.