package unifi import ( "fmt" "github.com/host-uk/core/pkg/cli" "github.com/host-uk/core/pkg/log" uf "github.com/host-uk/core/pkg/unifi" ) // Networks command flags. var ( networksSite string ) // addNetworksCommand adds the 'networks' subcommand for listing network segments. func addNetworksCommand(parent *cli.Command) { cmd := &cli.Command{ Use: "networks", Short: "List network segments", Long: "List all network segments configured on the UniFi controller, showing VLANs, subnets, isolation, and DHCP.", RunE: func(cmd *cli.Command, args []string) error { return runNetworks() }, } cmd.Flags().StringVar(&networksSite, "site", "", "Site name (default: \"default\")") parent.AddCommand(cmd) } func runNetworks() error { client, err := uf.NewFromConfig("", "", "", "", nil) if err != nil { return log.E("unifi.networks", "failed to initialise client", err) } networks, err := client.GetNetworks(networksSite) if err != nil { return log.E("unifi.networks", "failed to fetch networks", err) } if len(networks) == 0 { cli.Text("No networks found.") return nil } // Separate WANs, LANs, and VPNs var wans, lans, vpns []uf.NetworkConf for _, n := range networks { switch n.Purpose { case "wan": wans = append(wans, n) case "remote-user-vpn": vpns = append(vpns, n) default: lans = append(lans, n) } } cli.Blank() // WANs if len(wans) > 0 { cli.Print(" %s\n\n", infoStyle.Render("WAN Interfaces")) wanTable := cli.NewTable("Name", "Type", "Group", "Status") for _, w := range wans { status := successStyle.Render("enabled") if !w.Enabled { status = errorStyle.Render("disabled") } wanTable.AddRow( valueStyle.Render(w.Name), dimStyle.Render(w.WANType), dimStyle.Render(w.WANNetworkGroup), status, ) } wanTable.Render() cli.Blank() } // LANs if len(lans) > 0 { cli.Print(" %s\n\n", infoStyle.Render("LAN Networks")) lanTable := cli.NewTable("Name", "Subnet", "VLAN", "Isolated", "Internet", "DHCP", "mDNS") for _, n := range lans { vlan := dimStyle.Render("-") if n.VLANEnabled { vlan = numberStyle.Render(fmt.Sprintf("%d", n.VLAN)) } isolated := successStyle.Render("no") if n.NetworkIsolationEnabled { isolated = warningStyle.Render("yes") } internet := successStyle.Render("yes") if !n.InternetAccessEnabled { internet = errorStyle.Render("no") } dhcp := dimStyle.Render("off") if n.DHCPEnabled { dhcp = fmt.Sprintf("%s - %s", n.DHCPStart, n.DHCPStop) } mdns := dimStyle.Render("off") if n.MDNSEnabled { mdns = successStyle.Render("on") } lanTable.AddRow( valueStyle.Render(n.Name), n.IPSubnet, vlan, isolated, internet, dhcp, mdns, ) } lanTable.Render() cli.Blank() } // VPNs if len(vpns) > 0 { cli.Print(" %s\n\n", infoStyle.Render("VPN Networks")) vpnTable := cli.NewTable("Name", "Subnet", "Type") for _, v := range vpns { vpnTable.AddRow( valueStyle.Render(v.Name), v.IPSubnet, dimStyle.Render(v.VPNType), ) } vpnTable.Render() cli.Blank() } cli.Print(" %s\n\n", dimStyle.Render(fmt.Sprintf("%d networks total", len(networks)))) return nil }