@@ -849,3 +849,164 @@ func TestFleetConfigManager_OnReadyHook_SkipsInitializationOnReconnect(t *testin
849849 _ = fleetManager .otlpBridge .Stop (context .Background ())
850850 }
851851}
852+
853+ func TestFleetConfigManager_OnReadyHook_UsesConfiguredGRPCPort (t * testing.T ) {
854+ // Test that OnReadyHook uses the configured gRPC port from config
855+ logger := slog .New (slog .NewTextHandler (os .Stderr , & slog.HandlerOptions {Level : slog .LevelError }))
856+ mockPMgr := & mockPolicyManagerForFleet {}
857+ mockPMgr .On ("GetRepo" ).Return (nil )
858+ fleetManager := newFleetConfigManager (logger , mockPMgr , & mockBackendState {})
859+
860+ // Create config with custom gRPC port
861+ customPort := 9999
862+ cfg := config.Config {
863+ OrbAgent : config.OrbAgent {
864+ ConfigManager : config.ManagerConfig {
865+ Sources : config.Sources {
866+ Fleet : config.FleetManager {
867+ OTLPBridgeGRPCPort : & customPort ,
868+ },
869+ },
870+ },
871+ },
872+ }
873+ fleetManager .config = cfg
874+
875+ // Create the hook function that uses config (simulating what Start does)
876+ hookFunc := func (cm * autopaho.ConnectionManager , topics fleet.TokenResponseTopics ) {
877+ if fleetManager .otlpBridge == nil {
878+ fleetManager .logger .Info ("MQTT connection ready, initializing OTLP bridge" )
879+ // Get gRPC port from config, defaulting to 4318 if not specified
880+ grpcPort := 4318
881+ if fleetManager .config .OrbAgent .ConfigManager .Sources .Fleet .OTLPBridgeGRPCPort != nil {
882+ grpcPort = * fleetManager .config .OrbAgent .ConfigManager .Sources .Fleet .OTLPBridgeGRPCPort
883+ }
884+ bridgeConfig := otlpbridge.BridgeConfig {
885+ ListenAddr : fmt .Sprintf (":%d" , grpcPort ),
886+ Encoding : "json" ,
887+ }
888+ var err error
889+ fleetManager .otlpBridge , err = otlpbridge .NewBridgeServer (bridgeConfig , fleetManager .policyManager .GetRepo (), fleetManager .logger )
890+ if err != nil {
891+ fleetManager .logger .Error ("failed to create OTLP bridge" , slog .Any ("error" , err ))
892+ return
893+ }
894+ if err := fleetManager .otlpBridge .Start (context .Background ()); err != nil {
895+ fleetManager .logger .Error ("failed to start OTLP bridge" , slog .Any ("error" , err ))
896+ return
897+ }
898+ } else {
899+ fleetManager .logger .Info ("OTLP bridge already initialized, skipping initialization" )
900+ }
901+
902+ pub := otlpbridge .NewCMAdapterPublisher (cm )
903+ fleetManager .otlpBridge .SetPublisher (pub )
904+ fleetManager .otlpBridge .SetIngestTopic (topics .Ingest )
905+ fleetManager .otlpBridge .SetTelemetryTopic (topics .Telemetry )
906+ fleetManager .logger .Info ("OTLP bridge bound to Fleet MQTT" ,
907+ slog .String ("ingest_topic" , topics .Ingest ),
908+ slog .String ("telemetry_topic" , topics .Telemetry ))
909+ }
910+
911+ // Register the hook
912+ fleetManager .connection .AddOnReadyHook (hookFunc )
913+
914+ // Simulate connection ready event
915+ topics := fleet.TokenResponseTopics {
916+ Ingest : "test/otlp/topic" ,
917+ Telemetry : "test/telemetry/topic" ,
918+ }
919+
920+ // Call the hook manually
921+ hookFunc (nil , topics )
922+
923+ // Verify bridge was initialized
924+ require .NotNil (t , fleetManager .otlpBridge , "bridge should be initialized" )
925+ // Verify the bridge is listening on the configured port
926+ // We can't directly check the port, but we can verify the bridge started successfully
927+ // The actual port verification would require inspecting the listener, which is not exposed
928+ // So we just verify the bridge exists and started without error
929+
930+ // Cleanup
931+ if fleetManager .otlpBridge != nil {
932+ _ = fleetManager .otlpBridge .Stop (context .Background ())
933+ }
934+ }
935+
936+ func TestFleetConfigManager_OnReadyHook_UsesDefaultGRPCPort (t * testing.T ) {
937+ // Test that OnReadyHook uses the default gRPC port (4318) when not configured
938+ logger := slog .New (slog .NewTextHandler (os .Stderr , & slog.HandlerOptions {Level : slog .LevelError }))
939+ mockPMgr := & mockPolicyManagerForFleet {}
940+ mockPMgr .On ("GetRepo" ).Return (nil )
941+ fleetManager := newFleetConfigManager (logger , mockPMgr , & mockBackendState {})
942+
943+ // Create config without gRPC port configured (should use default)
944+ cfg := config.Config {
945+ OrbAgent : config.OrbAgent {
946+ ConfigManager : config.ManagerConfig {
947+ Sources : config.Sources {
948+ Fleet : config.FleetManager {
949+ // OTLPBridgeGRPCPort is nil, should use default 4318
950+ },
951+ },
952+ },
953+ },
954+ }
955+ fleetManager .config = cfg
956+
957+ // Create the hook function that uses config (simulating what Start does)
958+ hookFunc := func (cm * autopaho.ConnectionManager , topics fleet.TokenResponseTopics ) {
959+ if fleetManager .otlpBridge == nil {
960+ fleetManager .logger .Info ("MQTT connection ready, initializing OTLP bridge" )
961+ // Get gRPC port from config, defaulting to 4318 if not specified
962+ grpcPort := 4318
963+ if fleetManager .config .OrbAgent .ConfigManager .Sources .Fleet .OTLPBridgeGRPCPort != nil {
964+ grpcPort = * fleetManager .config .OrbAgent .ConfigManager .Sources .Fleet .OTLPBridgeGRPCPort
965+ }
966+ bridgeConfig := otlpbridge.BridgeConfig {
967+ ListenAddr : fmt .Sprintf (":%d" , grpcPort ),
968+ Encoding : "json" ,
969+ }
970+ var err error
971+ fleetManager .otlpBridge , err = otlpbridge .NewBridgeServer (bridgeConfig , fleetManager .policyManager .GetRepo (), fleetManager .logger )
972+ if err != nil {
973+ fleetManager .logger .Error ("failed to create OTLP bridge" , slog .Any ("error" , err ))
974+ return
975+ }
976+ if err := fleetManager .otlpBridge .Start (context .Background ()); err != nil {
977+ fleetManager .logger .Error ("failed to start OTLP bridge" , slog .Any ("error" , err ))
978+ return
979+ }
980+ } else {
981+ fleetManager .logger .Info ("OTLP bridge already initialized, skipping initialization" )
982+ }
983+
984+ pub := otlpbridge .NewCMAdapterPublisher (cm )
985+ fleetManager .otlpBridge .SetPublisher (pub )
986+ fleetManager .otlpBridge .SetIngestTopic (topics .Ingest )
987+ fleetManager .otlpBridge .SetTelemetryTopic (topics .Telemetry )
988+ fleetManager .logger .Info ("OTLP bridge bound to Fleet MQTT" ,
989+ slog .String ("ingest_topic" , topics .Ingest ),
990+ slog .String ("telemetry_topic" , topics .Telemetry ))
991+ }
992+
993+ // Register the hook
994+ fleetManager .connection .AddOnReadyHook (hookFunc )
995+
996+ // Simulate connection ready event
997+ topics := fleet.TokenResponseTopics {
998+ Ingest : "test/otlp/topic" ,
999+ Telemetry : "test/telemetry/topic" ,
1000+ }
1001+
1002+ // Call the hook manually
1003+ hookFunc (nil , topics )
1004+
1005+ // Verify bridge was initialized (should use default port 4318)
1006+ require .NotNil (t , fleetManager .otlpBridge , "bridge should be initialized with default port" )
1007+
1008+ // Cleanup
1009+ if fleetManager .otlpBridge != nil {
1010+ _ = fleetManager .otlpBridge .Stop (context .Background ())
1011+ }
1012+ }
0 commit comments