From 9918cf040c5dc11fb65f1d2b305872f013931895 Mon Sep 17 00:00:00 2001 From: lauralani Date: Fri, 24 Mar 2023 16:27:45 +0100 Subject: [PATCH] add export and import function --- cmd/export.go | 83 +++++++++++++++++++++++++++++++++++++++++++-------- cmd/import.go | 71 +++++++++++++++++++++++++++++++++---------- 2 files changed, 126 insertions(+), 28 deletions(-) diff --git a/cmd/export.go b/cmd/export.go index f6628ec..e5afe6f 100644 --- a/cmd/export.go +++ b/cmd/export.go @@ -5,7 +5,12 @@ Copyright © 2023 Laura Kalb package cmd import ( + "encoding/json" "fmt" + "net/netip" + "os" + "path" + "time" "github.com/spf13/cobra" ) @@ -15,23 +20,77 @@ var exportCmd = &cobra.Command{ Use: "export", Short: "Export current ipam configuration (not implemented)", Long: `Export current ipam contents to importable data format. - - Not implemented yet.`, +You can either export a single subnet or all subnets.`, + Example: "ipam export\nipam export 192.168.0.0/24", + Args: cobra.RangeArgs(0, 1), + Aliases: []string{"ex"}, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Not implemented") + var jsonoutput []Subnet + if len(args) == 1 { + prefix, parseerr := netip.ParsePrefix(args[0]) + if parseerr != nil { + fmt.Println("[ERROR]", parseerr) + os.Exit(1) + } + + subnet, geterr := GetSubnet(prefix) + if geterr != nil { + fmt.Println("[ERROR]", geterr) + os.Exit(1) + } + jsonoutput = append(jsonoutput, subnet) + } else { + subnetlist := ListSubnets() + for _, net := range subnetlist { + prefix, parseerr := netip.ParsePrefix(net) + if parseerr != nil { + fmt.Println("[ERROR]", parseerr) + os.Exit(1) + } + subnet, geterr := GetSubnet(prefix) + if geterr != nil { + fmt.Println("[ERROR]", geterr) + os.Exit(1) + } + jsonoutput = append(jsonoutput, subnet) + } + } + + //workingdir, _ := os.Getwd() + //timestamp := time.Now().Format("2006-01-02_15-04") + //exportfilename := workingdir + "/ipam_export_" + timestamp + ".json" + + var exportname string + + flagpath, _ := cmd.Flags().GetString("file") + if path.IsAbs(flagpath) { + exportname = flagpath + } else { + wd, _ := os.Getwd() + exportname = path.Join(wd, flagpath) + } + + data, _ := json.MarshalIndent(jsonoutput, "", " ") + + file, fileerr := os.Create(exportname) + if fileerr != nil { + fmt.Println("[ERROR]", fileerr) + os.Exit(1) + } + defer file.Close() + + _, writeerr := file.Write(data) + if writeerr != nil { + fmt.Println("[ERROR]", writeerr) + os.Exit(1) + } + fmt.Printf("[INFO] Data was exported to file %v\n", exportname) }, } func init() { rootCmd.AddCommand(exportCmd) - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // exportCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // exportCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + timestamp := time.Now().Format("2006-01-02_15-04") + exportCmd.Flags().StringP("file", "f", "./ipam_export_"+timestamp+".json", "File name for exported data.\nCan be both absolute or relative path.") } diff --git a/cmd/import.go b/cmd/import.go index edebe9c..d4b63a2 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -5,33 +5,72 @@ Copyright © 2023 Laura Kalb package cmd import ( + "encoding/json" "fmt" + "os" + "path" + "time" "github.com/spf13/cobra" ) -// importCmd represents the import command var importCmd = &cobra.Command{ - Use: "import", - Short: "Import ipam configuration (not implemented)", - Long: `Import ips and subnets to ipam. - - Not implemented yet.`, + Use: "import", + Short: "Import ipam configuration (not implemented)", + Long: `Import subnets to ipam.`, + Example: "ipam import --file import.json", + Args: cobra.NoArgs, + Aliases: []string{"im"}, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Not implemented") + var importname string + var subnets []Subnet + + flagpath, _ := cmd.Flags().GetString("file") + if path.IsAbs(flagpath) { + importname = flagpath + } else { + wd, _ := os.Getwd() + importname = path.Join(wd, flagpath) + } + + file, readerr := os.ReadFile(importname) + if readerr != nil { + fmt.Printf("[ERROR] Can't read file %v\n", importname) + fmt.Println(readerr) + } + + marsherr := json.Unmarshal(file, &subnets) + if marsherr != nil { + fmt.Printf("[ERROR] Invalid format for file %v\n", importname) + fmt.Println(marsherr) + } + + for _, subnet := range subnets { + fmt.Printf("[INFO] Start import of %v\n", subnet.Subnet.String()) + subnet.ChangedBy = "ipam import" + subnet.ChangedAt = time.Now() + + for _, addr := range subnet.Addresses { + addr.ChangedBy = "ipam import" + addr.ChangedAt = time.Now() + if addr.FQDN != "" { + AddDNSFqdn(addr.FQDN, addr.IP) + } + } + + suberr := subnet.WriteSubnet() + if suberr != nil { + fmt.Printf("[ERROR] Can't write subnet to file %v\n", subnet.Subnet.String()) + fmt.Println(suberr) + } + fmt.Printf("[INFO] Imported subnet %v successfully\n", subnet.Subnet.String()) + + } }, } func init() { rootCmd.AddCommand(importCmd) - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // importCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // importCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + importCmd.Flags().StringP("file", "f", "import.json", "File to use for import operation") }