package main import ( "encoding/json" "flag" "fmt" "log" "strings" ) func cmdClearServices(args []string) error { fs := flag.NewFlagSet("clear-services", flag.ExitOnError) dryRun := fs.Bool("dry-run", false, "list what would be deleted without deleting") confirm := fs.Bool("confirm", false, "actually delete (required)") accountFilter := fs.String("account", "", "only clear services for this account ID") if err := fs.Parse(args); err != nil { return err } if !*dryRun && !*confirm { return fmt.Errorf("clear-services requires --confirm to actually delete, or --dry-run to preview") } c, err := NewClient() if err != nil { return err } // Fetch all services. items, _, err := c.listAll("/services", 1000, decodeListPage) if err != nil { return fmt.Errorf("list services: %w", err) } // Filter by account if requested. var toDelete []Service for _, rm := range items { var s Service if err := json.Unmarshal(rm, &s); err != nil { log.Printf("skip unparseable service: %v", err) continue } if *accountFilter != "" && s.Account != *accountFilter { continue } toDelete = append(toDelete, s) } if len(toDelete) == 0 { fmt.Println("no services to delete") return nil } fmt.Printf("%d services to delete", len(toDelete)) if *accountFilter != "" { fmt.Printf(" for account %q", *accountFilter) } fmt.Println() if *dryRun { for _, s := range toDelete { macs := attachmentMACs(s) fmt.Printf(" %s account=%s macs=%s up=%d down=%d\n", s.ID, s.Account, strings.Join(macs, ","), s.UpSpeed, s.DownSpeed) } fmt.Println("--dry-run: no services were deleted") return nil } // Actually delete. var deleted, failed int for _, s := range toDelete { path := apiPrefix + "/services/" + pathID(s.ID) if err := c.del(path); err != nil { log.Printf("FAIL %s: %v", s.ID, err) failed++ } else { macs := attachmentMACs(s) fmt.Printf("deleted %s account=%s macs=%s\n", s.ID, s.Account, strings.Join(macs, ",")) deleted++ } } fmt.Printf("\n%d deleted, %d failed\n", deleted, failed) if failed > 0 { return fmt.Errorf("%d deletions failed", failed) } return nil } func attachmentMACs(s Service) []string { var macs []string for _, a := range s.Attachments { if a.CPEMac != "" { macs = append(macs, a.CPEMac) } else if a.CPESerial != "" { macs = append(macs, "sn:"+a.CPESerial) } else if a.CPEIMSI != "" { macs = append(macs, "imsi:"+a.CPEIMSI) } else if a.Username != "" { macs = append(macs, "u:"+a.Username) } else if len(a.NetworkPrefixes) > 0 { macs = append(macs, "pfx:"+a.NetworkPrefixes[0]) } } return macs }