@@ -619,3 +619,147 @@ func getResultText(r *mcp.CallToolResult) string {
619619 }
620620 return ""
621621}
622+
623+ type ciliumHandler func (context.Context , mcp.CallToolRequest ) (* mcp.CallToolResult , error )
624+
625+ // TestCiliumDbgHandlers exercises the success path of every cilium-dbg based handler.
626+ func TestCiliumDbgHandlers (t * testing.T ) {
627+ cases := []struct {
628+ name string
629+ handler ciliumHandler
630+ args map [string ]any
631+ dbgArgs []string
632+ expect string
633+ }{
634+ {"manage_endpoint_labels" , handleManageEndpointLabels , map [string ]any {"endpoint_id" : "34" , "labels" : "key=val" }, []string {"endpoint" , "labels" , "34" , "--add" , "key=val" }, "ok" },
635+ {"manage_endpoint_configuration" , handleManageEndpointConfiguration , map [string ]any {"endpoint_id" : "34" , "config" : "Debug=true" }, []string {"endpoint" , "config" , "34" , "Debug=true" }, "ok" },
636+ {"disconnect_endpoint" , handleDisconnectEndpoint , map [string ]any {"endpoint_id" : "34" }, []string {"endpoint" , "disconnect" , "34" }, "ok" },
637+ {"get_identity_details" , handleGetIdentityDetails , map [string ]any {"identity_id" : "123" }, []string {"identity" , "get" , "123" }, "ok" },
638+ {"flush_ipsec_state" , handleFlushIPsecState , map [string ]any {}, []string {"encrypt" , "flush" , "-f" }, "ok" },
639+ {"list_envoy_config" , handleListEnvoyConfig , map [string ]any {"resource_name" : "clusters" }, []string {"envoy" , "admin" , "clusters" }, "ok" },
640+ {"show_ipcache_cidr" , handleShowIPCacheInformation , map [string ]any {"cidr" : "10.0.0.0/24" }, []string {"ip" , "get" , "10.0.0.0/24" }, "ok" },
641+ {"show_ipcache_labels" , handleShowIPCacheInformation , map [string ]any {"labels" : "app=foo" }, []string {"ip" , "get" , "--labels" , "app=foo" }, "ok" },
642+ {"delete_kvstore_key" , handleDeleteKeyFromKVStore , map [string ]any {"key" : "foo" }, []string {"kvstore" , "delete" , "foo" }, "ok" },
643+ {"get_kvstore_key" , handleGetKVStoreKey , map [string ]any {"key" : "foo" }, []string {"kvstore" , "get" , "foo" }, "ok" },
644+ {"set_kvstore_key" , handleSetKVStoreKey , map [string ]any {"key" : "foo" , "value" : "bar" }, []string {"kvstore" , "set" , "foo=bar" }, "ok" },
645+ {"show_load_information" , handleShowLoadInformation , map [string ]any {}, []string {"loadinfo" }, "ok" },
646+ {"display_policy_node_info" , handleDisplayPolicyNodeInformation , map [string ]any {}, []string {"policy" , "get" }, "ok" },
647+ {"display_policy_node_info_labels" , handleDisplayPolicyNodeInformation , map [string ]any {"labels" : "k=v" }, []string {"policy" , "get" , "k=v" }, "ok" },
648+ {"delete_policy_rules_all" , handleDeletePolicyRules , map [string ]any {"all" : "true" }, []string {"policy" , "delete" , "--all" }, "ok" },
649+ {"delete_policy_rules_labels" , handleDeletePolicyRules , map [string ]any {"labels" : "k=v" }, []string {"policy" , "delete" , "k=v" }, "ok" },
650+ {"update_xdp_cidr" , handleUpdateXDPCIDRFilters , map [string ]any {"cidr_prefixes" : "10.0.0.0/8" }, []string {"prefilter" , "update" , "--cidr" , "10.0.0.0/8" }, "ok" },
651+ {"update_xdp_cidr_rev" , handleUpdateXDPCIDRFilters , map [string ]any {"cidr_prefixes" : "10.0.0.0/8" , "revision" : "2" }, []string {"prefilter" , "update" , "--cidr" , "10.0.0.0/8" , "--revision" , "2" }, "ok" },
652+ {"delete_xdp_cidr" , handleDeleteXDPCIDRFilters , map [string ]any {"cidr_prefixes" : "10.0.0.0/8" }, []string {"prefilter" , "delete" , "--cidr" , "10.0.0.0/8" }, "ok" },
653+ {"delete_xdp_cidr_rev" , handleDeleteXDPCIDRFilters , map [string ]any {"cidr_prefixes" : "10.0.0.0/8" , "revision" : "2" }, []string {"prefilter" , "delete" , "--cidr" , "10.0.0.0/8" , "--revision" , "2" }, "ok" },
654+ {"validate_cnp" , handleValidateCiliumNetworkPolicies , map [string ]any {"enable_k8s" : "true" , "enable_k8s_api_discovery" : "true" }, []string {"preflight" , "validate-cnp" , "--enable-k8s" , "--enable-k8s-api-discovery" }, "ok" },
655+ {"list_pcap_recorders" , handleListPCAPRecorders , map [string ]any {}, []string {"recorder" , "list" }, "ok" },
656+ {"get_pcap_recorder" , handleGetPCAPRecorder , map [string ]any {"recorder_id" : "1" }, []string {"recorder" , "get" , "1" }, "ok" },
657+ {"delete_pcap_recorder" , handleDeletePCAPRecorder , map [string ]any {"recorder_id" : "1" }, []string {"recorder" , "delete" , "1" }, "ok" },
658+ {"update_pcap_recorder" , handleUpdatePCAPRecorder , map [string ]any {"recorder_id" : "1" , "filters" : "f" }, []string {"recorder" , "update" , "1" , "--filters" , "f" , "--caplen" , "0" , "--id" , "0" }, "ok" },
659+ {"get_service_information" , handleGetServiceInformation , map [string ]any {"service_id" : "5" }, []string {"service" , "get" , "5" }, "ok" },
660+ {"delete_service_all" , handleDeleteService , map [string ]any {"all" : "true" }, []string {"service" , "delete" , "--all" }, "ok" },
661+ {"delete_service_id" , handleDeleteService , map [string ]any {"service_id" : "5" }, []string {"service" , "delete" , "5" }, "ok" },
662+ {"update_service" , handleUpdateService , map [string ]any {"backends" : "b" , "frontend" : "f" , "id" : "1" }, []string {"service" , "update" , "1" , "--backends" , "b" , "--frontend" , "f" , "--protocol" , "TCP" , "--states" , "active" }, "ok" },
663+ }
664+
665+ for _ , tc := range cases {
666+ t .Run (tc .name , func (t * testing.T ) {
667+ mock := cmd .NewMockShellExecutor ()
668+ mockCiliumDbgCommand (mock , tc .dbgArgs , tc .expect , nil )
669+ ctx := cmd .WithShellExecutor (context .Background (), mock )
670+
671+ tc .args ["node_name" ] = "test-node"
672+ result , err := tc .handler (ctx , newRequestWithArgs (tc .args ))
673+ require .NoError (t , err )
674+ assert .False (t , result .IsError , "handler returned error result: %s" , getResultText (result ))
675+ assert .Contains (t , getResultText (result ), tc .expect )
676+ })
677+ }
678+ }
679+
680+ // TestCiliumDbgHandlersMissingParams covers required-parameter validation branches.
681+ func TestCiliumDbgHandlersMissingParams (t * testing.T ) {
682+ cases := []struct {
683+ name string
684+ handler ciliumHandler
685+ args map [string ]any
686+ }{
687+ {"manage_endpoint_labels" , handleManageEndpointLabels , map [string ]any {}},
688+ {"manage_endpoint_configuration_no_id" , handleManageEndpointConfiguration , map [string ]any {}},
689+ {"manage_endpoint_configuration_no_config" , handleManageEndpointConfiguration , map [string ]any {"endpoint_id" : "34" }},
690+ {"disconnect_endpoint" , handleDisconnectEndpoint , map [string ]any {}},
691+ {"get_identity_details" , handleGetIdentityDetails , map [string ]any {}},
692+ {"list_envoy_config" , handleListEnvoyConfig , map [string ]any {}},
693+ {"show_ipcache_none" , handleShowIPCacheInformation , map [string ]any {}},
694+ {"delete_kvstore_key" , handleDeleteKeyFromKVStore , map [string ]any {}},
695+ {"get_kvstore_key" , handleGetKVStoreKey , map [string ]any {}},
696+ {"set_kvstore_key" , handleSetKVStoreKey , map [string ]any {"key" : "foo" }},
697+ {"delete_policy_rules_none" , handleDeletePolicyRules , map [string ]any {}},
698+ {"update_xdp_cidr" , handleUpdateXDPCIDRFilters , map [string ]any {}},
699+ {"delete_xdp_cidr" , handleDeleteXDPCIDRFilters , map [string ]any {}},
700+ {"get_pcap_recorder" , handleGetPCAPRecorder , map [string ]any {}},
701+ {"delete_pcap_recorder" , handleDeletePCAPRecorder , map [string ]any {}},
702+ {"update_pcap_recorder" , handleUpdatePCAPRecorder , map [string ]any {"recorder_id" : "1" }},
703+ {"get_service_information" , handleGetServiceInformation , map [string ]any {}},
704+ {"delete_service_none" , handleDeleteService , map [string ]any {}},
705+ {"update_service" , handleUpdateService , map [string ]any {"backends" : "b" }},
706+ }
707+
708+ for _ , tc := range cases {
709+ t .Run (tc .name , func (t * testing.T ) {
710+ mock := cmd .NewMockShellExecutor ()
711+ ctx := cmd .WithShellExecutor (context .Background (), mock )
712+ result , err := tc .handler (ctx , newRequestWithArgs (tc .args ))
713+ require .NoError (t , err )
714+ assert .True (t , result .IsError )
715+ assert .Empty (t , mock .GetCallLog ())
716+ })
717+ }
718+ }
719+
720+ // TestCiliumCliHandlers covers the cilium-CLI based handlers.
721+ func TestCiliumCliHandlers (t * testing.T ) {
722+ cases := []struct {
723+ name string
724+ handler ciliumHandler
725+ args map [string ]any
726+ cliArgs []string
727+ }{
728+ {"show_cluster_mesh_status" , handleShowClusterMeshStatus , map [string ]any {}, []string {"clustermesh" , "status" }},
729+ {"show_features_status" , handleShowFeaturesStatus , map [string ]any {}, []string {"features" , "status" }},
730+ {"toggle_cluster_mesh_enable" , handleToggleClusterMesh , map [string ]any {"enable" : "true" }, []string {"clustermesh" , "enable" }},
731+ {"toggle_cluster_mesh_disable" , handleToggleClusterMesh , map [string ]any {"enable" : "false" }, []string {"clustermesh" , "disable" }},
732+ }
733+
734+ for _ , tc := range cases {
735+ t .Run (tc .name , func (t * testing.T ) {
736+ mock := cmd .NewMockShellExecutor ()
737+ mock .AddCommandString ("cilium" , tc .cliArgs , "cli-ok" , nil )
738+ ctx := cmd .WithShellExecutor (context .Background (), mock )
739+ result , err := tc .handler (ctx , newRequestWithArgs (tc .args ))
740+ require .NoError (t , err )
741+ assert .False (t , result .IsError )
742+ assert .Contains (t , getResultText (result ), "cli-ok" )
743+ })
744+ }
745+ }
746+
747+ func TestCiliumCliHandlersError (t * testing.T ) {
748+ mock := cmd .NewMockShellExecutor ()
749+ mock .AddCommandString ("cilium" , []string {"clustermesh" , "status" }, "" , assert .AnError )
750+ ctx := cmd .WithShellExecutor (context .Background (), mock )
751+ result , err := handleShowClusterMeshStatus (ctx , newRequestWithArgs (map [string ]any {}))
752+ require .NoError (t , err )
753+ assert .True (t , result .IsError )
754+ assert .Contains (t , getResultText (result ), "Error getting cluster mesh status" )
755+ }
756+
757+ // TestCiliumDbgHandlerError covers the error path shared by dbg handlers.
758+ func TestCiliumDbgHandlerError (t * testing.T ) {
759+ mock := cmd .NewMockShellExecutor ()
760+ mockCiliumDbgCommand (mock , []string {"loadinfo" }, "" , assert .AnError )
761+ ctx := cmd .WithShellExecutor (context .Background (), mock )
762+ result , err := handleShowLoadInformation (ctx , newRequestWithArgs (map [string ]any {"node_name" : "test-node" }))
763+ require .NoError (t , err )
764+ assert .True (t , result .IsError )
765+ }
0 commit comments