@@ -18,6 +18,7 @@ import (
1818 "github.com/krakenkey/cli/internal/cert"
1919 "github.com/krakenkey/cli/internal/config"
2020 "github.com/krakenkey/cli/internal/domain"
21+ "github.com/krakenkey/cli/internal/endpoint"
2122 "github.com/krakenkey/cli/internal/output"
2223)
2324
@@ -113,6 +114,8 @@ func run() int {
113114 cmdErr = runAccount (ctx , client , printer , subArgs )
114115 case "cert" :
115116 cmdErr = runCert (ctx , client , printer , cfg , subArgs )
117+ case "endpoint" :
118+ cmdErr = runEndpoint (ctx , client , printer , subArgs )
116119 default :
117120 fmt .Fprintf (os .Stderr , "error: unknown command %q — run 'krakenkey help'\n " , cmd )
118121 return 1
@@ -636,6 +639,180 @@ func runCert(ctx context.Context, client *api.Client, printer *output.Printer, c
636639 }
637640}
638641
642+ // ── endpoint ──────────────────────────────────────────────────────────────────
643+
644+ func runEndpoint (ctx context.Context , client * api.Client , printer * output.Printer , args []string ) error {
645+ if len (args ) == 0 || args [0 ] == "--help" || args [0 ] == "-h" {
646+ fmt .Print (endpointUsage )
647+ return nil
648+ }
649+
650+ sub := args [0 ]
651+ subArgs := args [1 :]
652+
653+ switch sub {
654+ case "add" :
655+ fs := flag .NewFlagSet ("endpoint add" , flag .ContinueOnError )
656+ fs .SetOutput (os .Stderr )
657+ var (
658+ port int
659+ sniFlag string
660+ labelFlag string
661+ probes stringsFlag
662+ )
663+ fs .IntVar (& port , "port" , 443 , "Port to monitor (default: 443)" )
664+ fs .StringVar (& sniFlag , "sni" , "" , "SNI override (optional)" )
665+ fs .StringVar (& labelFlag , "label" , "" , "Label (optional)" )
666+ fs .Var (& probes , "probe" , "Connected probe ID to assign (repeat for multiple)" )
667+ fs .Usage = func () {
668+ fmt .Fprint (os .Stderr , "Usage: krakenkey endpoint add <host> [--port 443] [--sni host] [--label name] [--probe id]\n " )
669+ }
670+ if err := fs .Parse (subArgs ); err != nil {
671+ return err
672+ }
673+ if fs .NArg () == 0 {
674+ return & api.ErrConfig {Message : "hostname is required" }
675+ }
676+ var sni , label * string
677+ if sniFlag != "" {
678+ sni = & sniFlag
679+ }
680+ if labelFlag != "" {
681+ label = & labelFlag
682+ }
683+ return endpoint .RunAdd (ctx , client , printer , fs .Arg (0 ), port , sni , label , []string (probes ))
684+
685+ case "probes" :
686+ return endpoint .RunListProbes (ctx , client , printer )
687+
688+ case "list" :
689+ return endpoint .RunList (ctx , client , printer )
690+
691+ case "show" :
692+ fs := flag .NewFlagSet ("endpoint show" , flag .ContinueOnError )
693+ fs .SetOutput (os .Stderr )
694+ fs .Usage = func () { fmt .Fprint (os .Stderr , "Usage: krakenkey endpoint show <id>\n " ) }
695+ if err := fs .Parse (subArgs ); err != nil {
696+ return err
697+ }
698+ if fs .NArg () == 0 {
699+ return & api.ErrConfig {Message : "endpoint ID is required" }
700+ }
701+ return endpoint .RunShow (ctx , client , printer , fs .Arg (0 ))
702+
703+ case "enable" :
704+ fs := flag .NewFlagSet ("endpoint enable" , flag .ContinueOnError )
705+ fs .SetOutput (os .Stderr )
706+ fs .Usage = func () { fmt .Fprint (os .Stderr , "Usage: krakenkey endpoint enable <id>\n " ) }
707+ if err := fs .Parse (subArgs ); err != nil {
708+ return err
709+ }
710+ if fs .NArg () == 0 {
711+ return & api.ErrConfig {Message : "endpoint ID is required" }
712+ }
713+ return endpoint .RunEnable (ctx , client , printer , fs .Arg (0 ))
714+
715+ case "disable" :
716+ fs := flag .NewFlagSet ("endpoint disable" , flag .ContinueOnError )
717+ fs .SetOutput (os .Stderr )
718+ fs .Usage = func () { fmt .Fprint (os .Stderr , "Usage: krakenkey endpoint disable <id>\n " ) }
719+ if err := fs .Parse (subArgs ); err != nil {
720+ return err
721+ }
722+ if fs .NArg () == 0 {
723+ return & api.ErrConfig {Message : "endpoint ID is required" }
724+ }
725+ return endpoint .RunDisable (ctx , client , printer , fs .Arg (0 ))
726+
727+ case "delete" :
728+ fs := flag .NewFlagSet ("endpoint delete" , flag .ContinueOnError )
729+ fs .SetOutput (os .Stderr )
730+ fs .Usage = func () { fmt .Fprint (os .Stderr , "Usage: krakenkey endpoint delete <id>\n " ) }
731+ if err := fs .Parse (subArgs ); err != nil {
732+ return err
733+ }
734+ if fs .NArg () == 0 {
735+ return & api.ErrConfig {Message : "endpoint ID is required" }
736+ }
737+ return endpoint .RunDelete (ctx , client , printer , fs .Arg (0 ))
738+
739+ case "scan" :
740+ fs := flag .NewFlagSet ("endpoint scan" , flag .ContinueOnError )
741+ fs .SetOutput (os .Stderr )
742+ fs .Usage = func () { fmt .Fprint (os .Stderr , "Usage: krakenkey endpoint scan <id>\n " ) }
743+ if err := fs .Parse (subArgs ); err != nil {
744+ return err
745+ }
746+ if fs .NArg () == 0 {
747+ return & api.ErrConfig {Message : "endpoint ID is required" }
748+ }
749+ return endpoint .RunScan (ctx , client , printer , fs .Arg (0 ))
750+
751+ case "region" :
752+ return runEndpointRegion (ctx , client , printer , subArgs )
753+
754+ case "probe" :
755+ return runEndpointProbe (ctx , client , printer , subArgs )
756+
757+ default :
758+ return fmt .Errorf ("unknown endpoint subcommand %q — run 'krakenkey endpoint --help'" , sub )
759+ }
760+ }
761+
762+ func runEndpointRegion (ctx context.Context , client * api.Client , printer * output.Printer , args []string ) error {
763+ if len (args ) == 0 || args [0 ] == "--help" || args [0 ] == "-h" {
764+ fmt .Print ("Usage: krakenkey endpoint region <add|remove> <endpoint-id> <region>\n " )
765+ return nil
766+ }
767+
768+ sub := args [0 ]
769+ subArgs := args [1 :]
770+
771+ switch sub {
772+ case "add" :
773+ if len (subArgs ) < 2 {
774+ return & api.ErrConfig {Message : "endpoint ID and region are required" }
775+ }
776+ return endpoint .RunAddRegion (ctx , client , printer , subArgs [0 ], subArgs [1 ])
777+
778+ case "remove" :
779+ if len (subArgs ) < 2 {
780+ return & api.ErrConfig {Message : "endpoint ID and region are required" }
781+ }
782+ return endpoint .RunRemoveRegion (ctx , client , printer , subArgs [0 ], subArgs [1 ])
783+
784+ default :
785+ return fmt .Errorf ("unknown region subcommand %q — use 'add' or 'remove'" , sub )
786+ }
787+ }
788+
789+ func runEndpointProbe (ctx context.Context , client * api.Client , printer * output.Printer , args []string ) error {
790+ if len (args ) == 0 || args [0 ] == "--help" || args [0 ] == "-h" {
791+ fmt .Print ("Usage: krakenkey endpoint probe <add|remove> <endpoint-id> <probe-id>\n " )
792+ return nil
793+ }
794+
795+ sub := args [0 ]
796+ subArgs := args [1 :]
797+
798+ switch sub {
799+ case "add" :
800+ if len (subArgs ) < 2 {
801+ return & api.ErrConfig {Message : "endpoint ID and probe ID are required" }
802+ }
803+ return endpoint .RunAssignProbe (ctx , client , printer , subArgs [0 ], subArgs [1 ])
804+
805+ case "remove" :
806+ if len (subArgs ) < 2 {
807+ return & api.ErrConfig {Message : "endpoint ID and probe ID are required" }
808+ }
809+ return endpoint .RunUnassignProbe (ctx , client , printer , subArgs [0 ], subArgs [1 ])
810+
811+ default :
812+ return fmt .Errorf ("unknown probe subcommand %q — use 'add' or 'remove'" , sub )
813+ }
814+ }
815+
639816// ── usage strings ─────────────────────────────────────────────────────────────
640817
641818func printUsage () {
@@ -648,6 +825,7 @@ Commands:
648825 auth Manage authentication and API keys
649826 cert Certificate lifecycle management
650827 domain Domain registration and verification
828+ endpoint Endpoint monitoring management
651829 account Account and subscription info
652830 version Print version and exit
653831
@@ -735,3 +913,31 @@ Examples:
735913 krakenkey cert download 42 --out ./example.crt
736914 krakenkey cert update 42 --auto-renew=true
737915`
916+
917+ const endpointUsage = `Manage monitored endpoints.
918+
919+ Usage:
920+ krakenkey endpoint <subcommand> [flags]
921+
922+ Subcommands:
923+ add <host> Add a monitored endpoint
924+ list List all endpoints
925+ show <id> Show endpoint details
926+ scan <id> Request an on-demand scan
927+ probes List your connected probes
928+ enable <id> Enable a disabled endpoint
929+ disable <id> Disable an endpoint
930+ delete <id> Delete an endpoint
931+ probe add <id> <probe-id> Assign a connected probe
932+ probe remove <id> <probe-id> Remove a connected probe
933+ region add <id> <region> Add a hosted probe region
934+ region remove <id> <region> Remove a hosted probe region
935+
936+ Examples:
937+ krakenkey endpoint probes
938+ krakenkey endpoint add example.com --port 443 --label "Production" --probe <probe-id>
939+ krakenkey endpoint scan <id>
940+ krakenkey endpoint probe add <id> <probe-id>
941+ krakenkey endpoint region add <id> us-east-1
942+ krakenkey endpoint list
943+ `
0 commit comments