diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eaee9f553..0d308f13d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,10 +50,10 @@ jobs: with: go-version-file: 'go.mod' cache: false - - name: run install-tools - run: make install-tools - - name: run lint - run: make lint + - name: Lint Go + uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 + with: + version: v2.4.0 unit-test: name: Unit Tests diff --git a/.golangci.yml b/.golangci.yml index c364617dd..65923d74e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -122,7 +122,6 @@ linters: - G110 - G111 - G112 - - G113 - G114 - G201 - G202 diff --git a/Makefile b/Makefile index 19467116d..307b209a0 100644 --- a/Makefile +++ b/Makefile @@ -125,6 +125,7 @@ build: ## Build agent executable lint: ## Run linter @$(GOVET) ./... + @$(GORUN) $(GOLANGCILINT) config verify -c ./.golangci.yml @$(GORUN) $(GOLANGCILINT) run -c ./.golangci.yml @cd api/grpc && $(GORUN) $(BUF) generate @echo "🏯 Linting Done" diff --git a/Makefile.tools b/Makefile.tools index 512a729a2..e850a1d02 100644 --- a/Makefile.tools +++ b/Makefile.tools @@ -1,6 +1,6 @@ OAPICODEGEN = github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@v2.1.0 LEFTHOOK = github.com/evilmartians/lefthook@v1.6.9 -GOLANGCILINT = github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1 +GOLANGCILINT = github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0 PROTOCGENGO = google.golang.org/protobuf/cmd/protoc-gen-go@v1.32.0 GOFUMPT = mvdan.cc/gofumpt@v0.6.0 COUNTERFEITER = github.com/maxbrunsfeld/counterfeiter/v6@v6.8.1 diff --git a/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu.go b/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu.go index 2d398868f..a750f0104 100644 --- a/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu.go +++ b/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu.go @@ -7,6 +7,7 @@ package cgroup import ( "bytes" + "context" "errors" "os/exec" "path" @@ -63,8 +64,8 @@ func NewCPUSource(basePath string) *CPUSource { } } -func (cs *CPUSource) Collect() (ContainerCPUStats, error) { - cpuStats, err := cs.collectCPUStats() +func (cs *CPUSource) Collect(ctx context.Context) (ContainerCPUStats, error) { + cpuStats, err := cs.collectCPUStats(ctx) if err != nil { return ContainerCPUStats{}, err } @@ -73,8 +74,8 @@ func (cs *CPUSource) Collect() (ContainerCPUStats, error) { } // nolint: mnd -func (cs *CPUSource) collectCPUStats() (ContainerCPUStats, error) { - clockTicks, err := clockTicks() +func (cs *CPUSource) collectCPUStats(ctx context.Context) (ContainerCPUStats, error) { + clockTicks, err := clockTicks(ctx) if err != nil { return ContainerCPUStats{}, err } @@ -191,8 +192,8 @@ func systemCPUUsage(clockTicks int) (float64, error) { return 0, errors.New("unable to process " + CPUStatsPath + ". No cpu found") } -func clockTicks() (int, error) { - cmd := exec.Command("getconf", "CLK_TCK") +func clockTicks(ctx context.Context) (int, error) { + cmd := exec.CommandContext(ctx, "getconf", "CLK_TCK") out := new(bytes.Buffer) cmd.Stdout = out diff --git a/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu_test.go b/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu_test.go index 1c9327ac3..be277af85 100644 --- a/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu_test.go +++ b/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/internal/cgroup/cpu_test.go @@ -6,6 +6,7 @@ package cgroup import ( + "context" "os" "path" "runtime" @@ -19,6 +20,8 @@ func TestCollectCPUStats(t *testing.T) { _, filename, _, _ := runtime.Caller(0) localDirectory := path.Dir(filename) + ctx := context.Background() + tests := []struct { errorType error name string @@ -73,7 +76,7 @@ func TestCollectCPUStats(t *testing.T) { for _, test := range tests { t.Run(test.name, func(tt *testing.T) { cgroupCPUSource := NewCPUSource(test.basePath) - cpuStat, err := cgroupCPUSource.collectCPUStats() + cpuStat, err := cgroupCPUSource.collectCPUStats(ctx) // Assert error assert.IsType(tt, test.errorType, err) diff --git a/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/scraper.go b/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/scraper.go index 47b91c337..ccf2297e4 100644 --- a/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/scraper.go +++ b/internal/collector/containermetricsreceiver/internal/scraper/cpuscraper/scraper.go @@ -57,12 +57,12 @@ func (s *CPUScraper) Start(_ context.Context, _ component.Host) error { return nil } -func (s *CPUScraper) Scrape(context.Context) (pmetric.Metrics, error) { +func (s *CPUScraper) Scrape(ctx context.Context) (pmetric.Metrics, error) { s.settings.Logger.Debug("Scraping container CPU metrics") now := pcommon.NewTimestampFromTime(time.Now()) - stats, err := s.cpuSource.Collect() + stats, err := s.cpuSource.Collect(ctx) if err != nil { return pmetric.NewMetrics(), err } diff --git a/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper.go b/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper.go index 384be6ba4..f908d022d 100644 --- a/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper.go +++ b/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper.go @@ -92,8 +92,9 @@ func (s *NginxStubStatusScraper) Start(_ context.Context, _ component.Host) erro if strings.HasPrefix(s.cfg.APIDetails.Listen, "unix:") { httpClient.Transport = &http.Transport{ - DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", strings.TrimPrefix(s.cfg.APIDetails.Listen, "unix:")) + DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { + dialer := &net.Dialer{} + return dialer.DialContext(ctx, "unix", strings.TrimPrefix(s.cfg.APIDetails.Listen, "unix:")) }, } } diff --git a/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper_tls_test.go b/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper_tls_test.go index b36db092c..a8cb64b00 100644 --- a/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper_tls_test.go +++ b/internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper_tls_test.go @@ -94,6 +94,7 @@ Reading: 6 Writing: 179 Waiting: 106 func TestStubStatusScraperUnixSocket(t *testing.T) { // Create a test server with a Unix domain socket + ctx := context.Background() handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { if req.URL.Path == "/status" { rw.WriteHeader(http.StatusOK) @@ -115,7 +116,8 @@ Reading: 6 Writing: 179 Waiting: 106 os.Remove(socketPath) // Create a listener for the Unix socket - listener, err := net.Listen("unix", socketPath) + listenConfig := &net.ListenConfig{} + listener, err := listenConfig.Listen(ctx, "unix", socketPath) require.NoError(t, err, "Failed to create Unix socket listener") // Create a test server with our custom listener diff --git a/internal/collector/nginxplusreceiver/scraper.go b/internal/collector/nginxplusreceiver/scraper.go index 9f11b607c..c6dba8bc3 100644 --- a/internal/collector/nginxplusreceiver/scraper.go +++ b/internal/collector/nginxplusreceiver/scraper.go @@ -82,7 +82,7 @@ func (nps *NginxPlusScraper) ID() component.ID { return component.NewID(metadata.Type) } -func (nps *NginxPlusScraper) Start(_ context.Context, _ component.Host) error { +func (nps *NginxPlusScraper) Start(ctx context.Context, _ component.Host) error { endpoint := strings.TrimPrefix(nps.cfg.APIDetails.URL, "unix:") httpClient := http.DefaultClient caCertLocation := nps.cfg.APIDetails.Ca @@ -110,7 +110,7 @@ func (nps *NginxPlusScraper) Start(_ context.Context, _ component.Host) error { httpClient.Timeout = nps.cfg.ClientConfig.Timeout if strings.HasPrefix(nps.cfg.APIDetails.Listen, "unix:") { - httpClient = socketClient(strings.TrimPrefix(nps.cfg.APIDetails.Listen, "unix:")) + httpClient = socketClient(ctx, strings.TrimPrefix(nps.cfg.APIDetails.Listen, "unix:")) } plusClient, err := plusapi.NewNginxClient(endpoint, @@ -1208,11 +1208,12 @@ func (nps *NginxPlusScraper) recordCacheMetrics(stats *plusapi.Stats, now pcommo } } -func socketClient(socketPath string) *http.Client { +func socketClient(ctx context.Context, socketPath string) *http.Client { return &http.Client{ Transport: &http.Transport{ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", socketPath) + dialer := &net.Dialer{} + return dialer.DialContext(ctx, "unix", socketPath) }, }, } diff --git a/internal/collector/otel_collector_plugin.go b/internal/collector/otel_collector_plugin.go index 121d7ae2e..7bf31be8f 100644 --- a/internal/collector/otel_collector_plugin.go +++ b/internal/collector/otel_collector_plugin.go @@ -436,7 +436,7 @@ func (oc *Collector) checkForNewReceivers(ctx context.Context, nginxConfigContex } if oc.config.IsFeatureEnabled(pkgConfig.FeatureLogsNap) { - tcplogReceiversFound := oc.updateNginxAppProtectTcplogReceivers(nginxConfigContext) + tcplogReceiversFound := oc.updateNginxAppProtectTcplogReceivers(ctx, nginxConfigContext) if tcplogReceiversFound { reloadCollector = true } @@ -546,14 +546,16 @@ func (oc *Collector) updateExistingNginxOSSReceiver( return nginxReceiverFound, reloadCollector } -func (oc *Collector) updateNginxAppProtectTcplogReceivers(nginxConfigContext *model.NginxConfigContext) bool { +func (oc *Collector) updateNginxAppProtectTcplogReceivers( + ctx context.Context, nginxConfigContext *model.NginxConfigContext, +) bool { newTcplogReceiverAdded := false if oc.config.Collector.Receivers.TcplogReceivers == nil { oc.config.Collector.Receivers.TcplogReceivers = make(map[string]*config.TcplogReceiver) } - napSysLogServer := oc.findAvailableSyslogServers(nginxConfigContext.NAPSysLogServers) + napSysLogServer := oc.findAvailableSyslogServers(ctx, nginxConfigContext.NAPSysLogServers) if napSysLogServer != "" { if !oc.doesTcplogReceiverAlreadyExist(napSysLogServer) { @@ -680,7 +682,7 @@ func (oc *Collector) updateResourceAttributes( return actionUpdated } -func (oc *Collector) findAvailableSyslogServers(napSyslogServers []string) string { +func (oc *Collector) findAvailableSyslogServers(ctx context.Context, napSyslogServers []string) string { napSyslogServersMap := make(map[string]bool) for _, server := range napSyslogServers { napSyslogServersMap[server] = true @@ -693,19 +695,20 @@ func (oc *Collector) findAvailableSyslogServers(napSyslogServers []string) strin } for _, napSyslogServer := range napSyslogServers { - ln, err := net.Listen("tcp", napSyslogServer) + listenConfig := &net.ListenConfig{} + ln, err := listenConfig.Listen(ctx, "tcp", napSyslogServer) if err != nil { - slog.Debug("NAP syslog server is not reachable", "address", napSyslogServer, + slog.DebugContext(ctx, "NAP syslog server is not reachable", "address", napSyslogServer, "error", err) continue } closeError := ln.Close() if closeError != nil { - slog.Debug("Failed to close syslog server", "address", napSyslogServer, "error", closeError) + slog.DebugContext(ctx, "Failed to close syslog server", "address", napSyslogServer, "error", closeError) } - slog.Debug("Found valid NAP syslog server", "address", napSyslogServer) + slog.DebugContext(ctx, "Found valid NAP syslog server", "address", napSyslogServer) return napSyslogServer } diff --git a/internal/collector/otel_collector_plugin_test.go b/internal/collector/otel_collector_plugin_test.go index 59b71e990..5fcb9d3e1 100644 --- a/internal/collector/otel_collector_plugin_test.go +++ b/internal/collector/otel_collector_plugin_test.go @@ -729,6 +729,7 @@ func TestCollector_updateResourceAttributes(t *testing.T) { } func TestCollector_updateNginxAppProtectTcplogReceivers(t *testing.T) { + ctx := context.Background() conf := types.OTelConfig(t) conf.Collector.Log.Path = "" conf.Collector.Processors.Batch = nil @@ -745,7 +746,7 @@ func TestCollector_updateNginxAppProtectTcplogReceivers(t *testing.T) { assert.Empty(t, conf.Collector.Receivers.TcplogReceivers) t.Run("Test 1: NewCollector TcplogReceiver added", func(tt *testing.T) { - tcplogReceiverAdded := collector.updateNginxAppProtectTcplogReceivers(nginxConfigContext) + tcplogReceiverAdded := collector.updateNginxAppProtectTcplogReceivers(ctx, nginxConfigContext) assert.True(tt, tcplogReceiverAdded) assert.Len(tt, conf.Collector.Receivers.TcplogReceivers, 1) @@ -756,7 +757,7 @@ func TestCollector_updateNginxAppProtectTcplogReceivers(t *testing.T) { // Calling updateNginxAppProtectTcplogReceivers shouldn't update the TcplogReceivers slice // since there is already a receiver with the same ListenAddress t.Run("Test 2: TcplogReceiver already exists", func(tt *testing.T) { - tcplogReceiverAdded := collector.updateNginxAppProtectTcplogReceivers(nginxConfigContext) + tcplogReceiverAdded := collector.updateNginxAppProtectTcplogReceivers(ctx, nginxConfigContext) assert.False(t, tcplogReceiverAdded) assert.Len(t, conf.Collector.Receivers.TcplogReceivers, 1) assert.Equal(t, "localhost:15632", conf.Collector.Receivers.TcplogReceivers["nginx_app_protect"].ListenAddress) @@ -764,13 +765,13 @@ func TestCollector_updateNginxAppProtectTcplogReceivers(t *testing.T) { }) t.Run("Test 3: TcplogReceiver deleted", func(tt *testing.T) { - tcplogReceiverDeleted := collector.updateNginxAppProtectTcplogReceivers(&model.NginxConfigContext{}) + tcplogReceiverDeleted := collector.updateNginxAppProtectTcplogReceivers(ctx, &model.NginxConfigContext{}) assert.True(t, tcplogReceiverDeleted) assert.Empty(t, conf.Collector.Receivers.TcplogReceivers) }) t.Run("Test 4: NewCollector tcplogReceiver added and deleted another", func(tt *testing.T) { - tcplogReceiverDeleted := collector.updateNginxAppProtectTcplogReceivers( + tcplogReceiverDeleted := collector.updateNginxAppProtectTcplogReceivers(ctx, &model.NginxConfigContext{ NAPSysLogServers: []string{"localhost:1555"}, }, @@ -784,6 +785,7 @@ func TestCollector_updateNginxAppProtectTcplogReceivers(t *testing.T) { } func TestCollector_findAvailableSyslogServers(t *testing.T) { + ctx := context.Background() conf := types.OTelConfig(t) conf.Collector.Log.Path = "" conf.Collector.Processors.Batch = nil @@ -840,12 +842,13 @@ func TestCollector_findAvailableSyslogServers(t *testing.T) { for _, test := range tests { t.Run(test.name, func(tt *testing.T) { if test.portInUse { - ln, listenError := net.Listen("tcp", "localhost:15632") + listenConfig := &net.ListenConfig{} + ln, listenError := listenConfig.Listen(ctx, "tcp", "localhost:15632") require.NoError(t, listenError) defer ln.Close() } - actual := collector.findAvailableSyslogServers(test.syslogServers) + actual := collector.findAvailableSyslogServers(ctx, test.syslogServers) assert.Equal(tt, test.expectedSyslogServer, actual) }) } diff --git a/internal/datasource/config/nginx_config_parser.go b/internal/datasource/config/nginx_config_parser.go index 4eedff370..1d9c6bc92 100644 --- a/internal/datasource/config/nginx_config_parser.go +++ b/internal/datasource/config/nginx_config_parser.go @@ -801,8 +801,9 @@ func (ncp *NginxConfigParser) socketClient(socketPath string) *http.Client { return &http.Client{ Timeout: ncp.agentConfig.Client.Grpc.KeepAlive.Timeout, Transport: &http.Transport{ - DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", socketPath) + DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { + dialer := &net.Dialer{} + return dialer.DialContext(ctx, "unix", socketPath) }, }, } diff --git a/internal/resource/resource_service.go b/internal/resource/resource_service.go index 634e920f1..52c4cf3e0 100644 --- a/internal/resource/resource_service.go +++ b/internal/resource/resource_service.go @@ -236,7 +236,7 @@ func (r *ResourceService) ApplyConfig(ctx context.Context, instanceID string) (* func (r *ResourceService) GetHTTPUpstreamServers(ctx context.Context, instance *mpi.Instance, upstream string, ) ([]client.UpstreamServer, error) { - plusClient, err := r.createPlusClient(instance) + plusClient, err := r.createPlusClient(ctx, instance) if err != nil { slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) return nil, err @@ -251,7 +251,7 @@ func (r *ResourceService) GetHTTPUpstreamServers(ctx context.Context, instance * func (r *ResourceService) GetUpstreams(ctx context.Context, instance *mpi.Instance, ) (*client.Upstreams, error) { - plusClient, err := r.createPlusClient(instance) + plusClient, err := r.createPlusClient(ctx, instance) if err != nil { slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) return nil, err @@ -266,7 +266,7 @@ func (r *ResourceService) GetUpstreams(ctx context.Context, instance *mpi.Instan func (r *ResourceService) GetStreamUpstreams(ctx context.Context, instance *mpi.Instance, ) (*client.StreamUpstreams, error) { - plusClient, err := r.createPlusClient(instance) + plusClient, err := r.createPlusClient(ctx, instance) if err != nil { slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) return nil, err @@ -284,7 +284,7 @@ func (r *ResourceService) GetStreamUpstreams(ctx context.Context, instance *mpi. func (r *ResourceService) UpdateStreamServers(ctx context.Context, instance *mpi.Instance, upstream string, upstreams []*structpb.Struct, ) (added, updated, deleted []client.StreamUpstreamServer, err error) { - plusClient, err := r.createPlusClient(instance) + plusClient, err := r.createPlusClient(ctx, instance) if err != nil { slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) return nil, nil, nil, err @@ -304,7 +304,7 @@ func (r *ResourceService) UpdateStreamServers(ctx context.Context, instance *mpi func (r *ResourceService) UpdateHTTPUpstreamServers(ctx context.Context, instance *mpi.Instance, upstream string, upstreams []*structpb.Struct, ) (added, updated, deleted []client.UpstreamServer, err error) { - plusClient, err := r.createPlusClient(instance) + plusClient, err := r.createPlusClient(ctx, instance) if err != nil { slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) return nil, nil, nil, err @@ -349,7 +349,7 @@ func convertToStreamUpstreamServer(streamUpstreams []*structpb.Struct) []client. return servers } -func (r *ResourceService) createPlusClient(instance *mpi.Instance) (*client.NginxClient, error) { +func (r *ResourceService) createPlusClient(ctx context.Context, instance *mpi.Instance) (*client.NginxClient, error) { plusAPI := instance.GetInstanceRuntime().GetNginxPlusRuntimeInfo().GetPlusApi() var endpoint string @@ -357,7 +357,6 @@ func (r *ResourceService) createPlusClient(instance *mpi.Instance) (*client.Ngin return nil, errors.New("failed to preform API action, NGINX Plus API is not configured") } - slog.Info("location", "", plusAPI.GetListen()) if strings.HasPrefix(plusAPI.GetListen(), "unix:") { endpoint = fmt.Sprintf(unixPlusAPIFormat, plusAPI.GetLocation()) } else { @@ -367,7 +366,7 @@ func (r *ResourceService) createPlusClient(instance *mpi.Instance) (*client.Ngin httpClient := http.DefaultClient caCertLocation := plusAPI.GetCa() if caCertLocation != "" { - slog.Debug("Reading CA certificate", "file_path", caCertLocation) + slog.DebugContext(ctx, "Reading CA certificate", "file_path", caCertLocation) caCert, err := os.ReadFile(caCertLocation) if err != nil { return nil, err @@ -385,7 +384,7 @@ func (r *ResourceService) createPlusClient(instance *mpi.Instance) (*client.Ngin } } if strings.HasPrefix(plusAPI.GetListen(), "unix:") { - httpClient = socketClient(strings.TrimPrefix(plusAPI.GetListen(), "unix:")) + httpClient = socketClient(ctx, strings.TrimPrefix(plusAPI.GetListen(), "unix:")) } return client.NewNginxClient(endpoint, @@ -408,11 +407,12 @@ func (r *ResourceService) updateResourceInfo(ctx context.Context) { } } -func socketClient(socketPath string) *http.Client { +func socketClient(ctx context.Context, socketPath string) *http.Client { return &http.Client{ Transport: &http.Transport{ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", socketPath) + dialer := &net.Dialer{} + return dialer.DialContext(ctx, "unix", socketPath) }, }, } diff --git a/internal/resource/resource_service_test.go b/internal/resource/resource_service_test.go index eb77767ad..a3eb71074 100644 --- a/internal/resource/resource_service_test.go +++ b/internal/resource/resource_service_test.go @@ -302,7 +302,7 @@ func TestResourceService_createPlusClient(t *testing.T) { protos.NginxPlusInstance([]string{}), } - _, clientErr := resourceService.createPlusClient(test.instance) + _, clientErr := resourceService.createPlusClient(ctx, test.instance) if test.err != nil { require.Error(tt, clientErr) assert.Contains(tt, clientErr.Error(), test.err.Error()) diff --git a/test/helpers/network_utils.go b/test/helpers/network_utils.go index f5a1c38b0..22e09c933 100644 --- a/test/helpers/network_utils.go +++ b/test/helpers/network_utils.go @@ -5,6 +5,7 @@ package helpers import ( + "context" "crypto/rand" "errors" "fmt" @@ -14,7 +15,7 @@ import ( ) // RandomPort generates a random port for testing and checks if a port is available by attempting to bind to it -func RandomPort(t *testing.T) (int, error) { +func RandomPort(t *testing.T, ctx context.Context) (int, error) { t.Helper() // Define the range for dynamic ports (49152–65535 as per IANA recommendation) @@ -33,7 +34,7 @@ func RandomPort(t *testing.T) (int, error) { portNumber := int(port.Int64()) + minPort - if isPortAvailable(portNumber) { + if isPortAvailable(ctx, portNumber) { return portNumber, nil } } @@ -42,9 +43,10 @@ func RandomPort(t *testing.T) (int, error) { } // isPortAvailable checks if a port is available by attempting to bind to it -func isPortAvailable(port int) bool { +func isPortAvailable(ctx context.Context, port int) bool { address := fmt.Sprintf("127.0.0.1:%d", port) - conn, err := net.Dial("tcp", address) + dialer := &net.Dialer{} + conn, err := dialer.DialContext(ctx, "tcp", address) if conn != nil { conn.Close() } diff --git a/test/integration/utils/grpc_management_plane_utils.go b/test/integration/utils/grpc_management_plane_utils.go index b79ef5de2..2ce2d5c74 100644 --- a/test/integration/utils/grpc_management_plane_utils.go +++ b/test/integration/utils/grpc_management_plane_utils.go @@ -184,6 +184,7 @@ func setupNginxContainer( func setupLocalEnvironment(tb testing.TB) { tb.Helper() tb.Log("Running tests on local machine") + ctx := context.Background() requestChan := make(chan *mpi.ManagementPlaneRequest) server := mockGrpc.NewCommandService(requestChan, os.TempDir()) @@ -191,7 +192,8 @@ func setupLocalEnvironment(tb testing.TB) { go func(tb testing.TB) { tb.Helper() - listener, err := net.Listen("tcp", "localhost:0") + listenConfig := &net.ListenConfig{} + listener, err := listenConfig.Listen(ctx, "tcp", "localhost:0") assert.NoError(tb, err) MockManagementPlaneAPIAddress = listener.Addr().String() @@ -202,7 +204,8 @@ func setupLocalEnvironment(tb testing.TB) { go func(tb testing.TB) { tb.Helper() - listener, err := net.Listen("tcp", "localhost:0") + listenConfig := &net.ListenConfig{} + listener, err := listenConfig.Listen(ctx, "tcp", "localhost:0") assert.NoError(tb, err) var opts []grpc.ServerOption diff --git a/test/mock/grpc/cmd/main.go b/test/mock/grpc/cmd/main.go index 11c833bd4..250e476fa 100644 --- a/test/mock/grpc/cmd/main.go +++ b/test/mock/grpc/cmd/main.go @@ -76,7 +76,7 @@ func main() { slog.DebugContext(ctx, "Config directory", "directory", *configDirectory) - _, err = grpc.NewMockManagementServer(*apiAddress, agentConfig, configDirectory) + _, err = grpc.NewMockManagementServer(ctx, *apiAddress, agentConfig, configDirectory) if err != nil { slog.ErrorContext(ctx, "Failed to start mock management server", "error", err) os.Exit(1) diff --git a/test/mock/grpc/mock_management_server.go b/test/mock/grpc/mock_management_server.go index aff397395..155c267fe 100644 --- a/test/mock/grpc/mock_management_server.go +++ b/test/mock/grpc/mock_management_server.go @@ -64,6 +64,7 @@ type MockManagementServer struct { } func NewMockManagementServer( + ctx context.Context, apiAddress string, agentConfig *config.Config, configDirectory *string, @@ -71,7 +72,7 @@ func NewMockManagementServer( var err error requestChan := make(chan *v1.ManagementPlaneRequest) - commandService := serveCommandService(apiAddress, agentConfig, requestChan, *configDirectory) + commandService := serveCommandService(ctx, apiAddress, agentConfig, requestChan, *configDirectory) var fileServer *FileService @@ -82,10 +83,11 @@ func NewMockManagementServer( fileServiceLock.Lock() defer fileServiceLock.Unlock() - grpcListener, err := net.Listen(connectionType, + listenConfig := &net.ListenConfig{} + grpcListener, err := listenConfig.Listen(ctx, connectionType, fmt.Sprintf("%s:%d", agentConfig.Command.Server.Host, agentConfig.Command.Server.Port)) if err != nil { - slog.Error("Failed to listen", "error", err) + slog.ErrorContext(ctx, "Failed to listen", "error", err) return nil, err } @@ -179,6 +181,7 @@ func serverOptions(agentConfig *config.Config) []grpc.ServerOption { } func serveCommandService( + ctx context.Context, apiAddress string, agentConfig *config.Config, requestChan chan *v1.ManagementPlaneRequest, @@ -187,7 +190,7 @@ func serveCommandService( commandServer := NewCommandService(requestChan, configDirectory) go func() { - cmdListener, listenerErr := createListener(apiAddress, agentConfig) + cmdListener, listenerErr := createListener(ctx, apiAddress, agentConfig) if listenerErr != nil { return } @@ -202,12 +205,12 @@ func serveCommandService( return commandServer } -func createListener(apiAddress string, agentConfig *config.Config) (net.Listener, error) { +func createListener(ctx context.Context, apiAddress string, agentConfig *config.Config) (net.Listener, error) { if agentConfig.Command.TLS != nil { cert, keyPairErr := tls.LoadX509KeyPair(agentConfig.Command.TLS.Cert, agentConfig.Command.TLS.Key) if keyPairErr == nil { - slog.Error("Failed to load key and cert pair", "error", keyPairErr) + slog.ErrorContext(ctx, "Failed to load key and cert pair", "error", keyPairErr) return tls.Listen(connectionType, apiAddress, &tls.Config{ Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12, @@ -215,7 +218,9 @@ func createListener(apiAddress string, agentConfig *config.Config) (net.Listener } } - return net.Listen(connectionType, apiAddress) + listenConfig := &net.ListenConfig{} + + return listenConfig.Listen(ctx, connectionType, apiAddress) } func reportHealth(healthcheck *health.Server, agentConfig *config.Config) { diff --git a/test/types/config.go b/test/types/config.go index 04dec87e5..73d7e15ac 100644 --- a/test/types/config.go +++ b/test/types/config.go @@ -6,6 +6,7 @@ package types import ( + "context" "path/filepath" "testing" "time" @@ -184,23 +185,24 @@ func AgentConfig() *config.Config { // Produces a populated Agent Config with a temp Collector config path for testing usage. func OTelConfig(t *testing.T) *config.Config { t.Helper() + ctx := context.Background() ac := AgentConfig() ac.Collector.ConfigPath = filepath.Join(t.TempDir(), "otel-collector-config.yaml") - exporterPort, expErr := helpers.RandomPort(t) + exporterPort, expErr := helpers.RandomPort(t, ctx) require.NoError(t, expErr) ac.Collector.Exporters.OtlpExporters["default"].Server.Port = exporterPort - receiverPort, recErr := helpers.RandomPort(t) + receiverPort, recErr := helpers.RandomPort(t, ctx) require.NoError(t, recErr) ac.Collector.Receivers.OtlpReceivers["default"].Server.Port = receiverPort - healthPort, healthErr := helpers.RandomPort(t) + healthPort, healthErr := helpers.RandomPort(t, ctx) require.NoError(t, healthErr) ac.Collector.Extensions.Health.Server.Port = healthPort - commandPort, commandErr := helpers.RandomPort(t) + commandPort, commandErr := helpers.RandomPort(t, ctx) require.NoError(t, commandErr) ac.Command.Server.Port = commandPort