mirror of
https://codeberg.org/lauralani/ipam.git
synced 2024-11-23 20:20:39 +01:00
add a whole lot of functionality :3
This commit is contained in:
parent
5af155dfc7
commit
6154f16e11
7 changed files with 129 additions and 36 deletions
43
cmd/classes.go
Normal file
43
cmd/classes.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2023 Laura Kalb <dev@lauka.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Subnet struct {
|
||||||
|
Subnet netip.Prefix
|
||||||
|
Name string
|
||||||
|
Vlan string
|
||||||
|
Addresses []Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasIP checks if a Subnet already contains given netip.Addr.
|
||||||
|
// Returns true if the IP already is present, false otherwise.
|
||||||
|
func (s Subnet) HasIP(ip netip.Addr) bool {
|
||||||
|
iscontained := false
|
||||||
|
|
||||||
|
for _, element := range s.Addresses {
|
||||||
|
if element.IP.Compare(ip) == 0 {
|
||||||
|
iscontained = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return iscontained
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Subnet) RemoveIP(ip netip.Addr) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Subnet) GetIP(ip netip.Addr) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type Address struct {
|
||||||
|
IP netip.Addr
|
||||||
|
FQDN string
|
||||||
|
}
|
|
@ -52,6 +52,11 @@ var ipaddCmd = &cobra.Command{
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if subnet.HasIP(ip) {
|
||||||
|
fmt.Printf("[ERROR] IP %v already exists in subnet %v\n", ip.String(), subnet.Subnet.String())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
subnet.Addresses = append(subnet.Addresses, Address{ip, hostname})
|
subnet.Addresses = append(subnet.Addresses, Address{ip, hostname})
|
||||||
|
|
||||||
writeerr := WriteSubnet(subnet)
|
writeerr := WriteSubnet(subnet)
|
||||||
|
|
|
@ -4,8 +4,6 @@ Copyright © 2023 Laura Kalb <dev@lauka.net>
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,8 +14,8 @@ var ipdeleteCmd = &cobra.Command{
|
||||||
Long: `Delete an IP address`,
|
Long: `Delete an IP address`,
|
||||||
Aliases: []string{"d"},
|
Aliases: []string{"d"},
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
|
Example: "ipam ip delete 192.168.0.1",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("ip delete called")
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,6 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Subnet struct {
|
|
||||||
Subnet netip.Prefix
|
|
||||||
Name string
|
|
||||||
Vlan string
|
|
||||||
Addresses []Address
|
|
||||||
}
|
|
||||||
|
|
||||||
type Address struct {
|
|
||||||
IP netip.Addr
|
|
||||||
FQDN string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchBestSubnet tries to load the most fitting IP subnet file
|
// SearchBestSubnet tries to load the most fitting IP subnet file
|
||||||
// on disk. It takes an IP object and tries to get the best subnet
|
// on disk. It takes an IP object and tries to get the best subnet
|
||||||
// (meaning the subnet with the smallest subnet size).
|
// (meaning the subnet with the smallest subnet size).
|
||||||
|
@ -218,3 +206,19 @@ func SortAddresses(list []Address) []Address {
|
||||||
})
|
})
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteSubnet deletes the subnet file on disk for netip.Prefix
|
||||||
|
// net.
|
||||||
|
//
|
||||||
|
// Returns nil on success, or a *PathError on failure
|
||||||
|
func DeleteSubnet(net netip.Prefix) error {
|
||||||
|
var datadir string = viper.GetString("DataPath")
|
||||||
|
filename := datadir + strings.Replace(net.String(), "/", "_", 1)
|
||||||
|
|
||||||
|
removeerr := os.Remove(filename)
|
||||||
|
if removeerr != nil {
|
||||||
|
return removeerr
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ var subnetaddCmd = &cobra.Command{
|
||||||
|
|
||||||
// Parse subnet into ParseCIDR to test if it's a valid subnet
|
// Parse subnet into ParseCIDR to test if it's a valid subnet
|
||||||
// _, ipnet, err := net.ParseCIDR(subnet)
|
// _, ipnet, err := net.ParseCIDR(subnet)
|
||||||
ipnet, err := netip.ParsePrefix(subnet)
|
ipnet, parseerr := netip.ParsePrefix(subnet)
|
||||||
|
|
||||||
// Exit if subnet already exists, no need to add it then
|
// Exit if subnet already exists, no need to add it then
|
||||||
if SubnetExists(ipnet) {
|
if SubnetExists(ipnet) {
|
||||||
|
@ -47,8 +47,8 @@ var subnetaddCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit if parsed value is no valid IP
|
// Exit if parsed value is no valid IP
|
||||||
if err != nil {
|
if parseerr != nil {
|
||||||
fmt.Println("[ERROR]", err)
|
fmt.Println("[ERROR]", parseerr)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,15 +67,11 @@ var subnetaddCmd = &cobra.Command{
|
||||||
writeerr := WriteSubnet(subnetobject)
|
writeerr := WriteSubnet(subnetobject)
|
||||||
|
|
||||||
if writeerr != nil {
|
if writeerr != nil {
|
||||||
fmt.Println("[ERROR]", err)
|
fmt.Println("[ERROR]", writeerr)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vlanid == "-" {
|
fmt.Printf("added subnet:\nnet: %v\nname: %v\nvlan: %v\n", subnet, netname, vlanid)
|
||||||
fmt.Printf("added subnet:\nnet: %v\nname: %v\n", subnet, netname)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("added subnet:\nnet: %v\nname: %v\nvlan: %v\n", subnet, netname, vlanid)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -17,20 +18,27 @@ var subnetdeleteCmd = &cobra.Command{
|
||||||
Long: `Delete a subnet from the ipam.`,
|
Long: `Delete a subnet from the ipam.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
Aliases: []string{"d"},
|
Aliases: []string{"d"},
|
||||||
|
Example: "ipam subnet delete 192.168.0.0/24",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if len(args) < 1 {
|
subnet, parseerr := netip.ParsePrefix(args[0])
|
||||||
fmt.Println("Error: Too few arguments!")
|
if parseerr != nil {
|
||||||
fmt.Print("Usage:\n ipam subnet delete [subnet]")
|
fmt.Println("[ERROR]", parseerr)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if len(args) > 1 {
|
|
||||||
fmt.Println("Error: Too many arguments!")
|
|
||||||
fmt.Print("Usage:\n ipam subnet delete [subnet]")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
subnet := args[0]
|
|
||||||
|
|
||||||
fmt.Printf("Deleting %v\n", subnet)
|
var confirmation string
|
||||||
|
fmt.Printf("[WARNING] Do you really want to delete subnet %v? [y/N] ", subnet.String())
|
||||||
|
fmt.Scan(&confirmation)
|
||||||
|
|
||||||
|
if (confirmation == "y") || (confirmation == "Y") {
|
||||||
|
deleteerr := DeleteSubnet(subnet)
|
||||||
|
if deleteerr != nil {
|
||||||
|
fmt.Println("[ERROR]", deleteerr)
|
||||||
|
os.Exit(1)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("deleted subnet %v\n", subnet.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -16,8 +20,43 @@ var subnetlistCmd = &cobra.Command{
|
||||||
Long: `List all subnets`,
|
Long: `List all subnets`,
|
||||||
Aliases: []string{"l"},
|
Aliases: []string{"l"},
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
|
Example: "cmdb subnet list",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("subnet list called")
|
verbose, _ := cmd.Flags().GetBool("verbose")
|
||||||
|
subnetlist := ListSubnets()
|
||||||
|
var subnets []Subnet
|
||||||
|
|
||||||
|
for _, subnet := range subnetlist {
|
||||||
|
prefix, _ := netip.ParsePrefix(subnet)
|
||||||
|
net, err := GetSubnet(prefix)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
subnets = append(subnets, net)
|
||||||
|
}
|
||||||
|
sort.Slice(subnets, func(i, j int) bool {
|
||||||
|
return subnets[i].Subnet.Addr().Less(subnets[j].Subnet.Addr())
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, subnet := range subnets {
|
||||||
|
if verbose {
|
||||||
|
var numip, freeip int
|
||||||
|
|
||||||
|
if subnet.Subnet.Addr().Is4() {
|
||||||
|
hostbits := float64(32 - subnet.Subnet.Bits())
|
||||||
|
numip = int(math.Pow(2, hostbits)) - 2
|
||||||
|
freeip = numip - len(subnet.Addresses)
|
||||||
|
|
||||||
|
fmt.Printf("%v:\t%v\t(vl: %v)\tfree: %v\n", subnet.Subnet, subnet.Name, subnet.Vlan, freeip)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%v:\t%v\t(vl: %v)\n", subnet.Subnet, subnet.Name, subnet.Vlan)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%v:\t%v\t(vl: %v)\n", subnet.Subnet, subnet.Name, subnet.Vlan)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,5 +71,5 @@ func init() {
|
||||||
|
|
||||||
// Cobra supports local flags which will only run when this command
|
// Cobra supports local flags which will only run when this command
|
||||||
// is called directly, e.g.:
|
// is called directly, e.g.:
|
||||||
// listCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
subnetlistCmd.Flags().BoolP("verbose", "v", false, "Show verbose output like free IPs")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue