From 7357465ea6c088bd9f0afe0d4a2fb155cac9f84d Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Mon, 29 Sep 2025 20:20:53 +0200 Subject: [PATCH] chore: enable noctx linter (#24765) Signed-off-by: Matthieu MOREL --- .golangci.yaml | 1 + applicationset/metrics/metrics_test.go | 4 +- .../services/github_metrics_test.go | 22 ++- .../services/scm_provider/bitbucket_cloud.go | 2 +- .../commands/argocd_commit_server.go | 6 +- cmd/argocd-dex/commands/argocd_dex.go | 2 +- .../commands/argocd_repo_server.go | 3 +- cmd/argocd/commands/headless/headless.go | 3 +- cmpserver/server.go | 4 +- controller/metrics/metrics_test.go | 20 +- gitops-engine/agent/main.go | 9 +- gitops-engine/pkg/diff/diff_test.go | 48 ++--- hack/gen-crd-spec/main.go | 7 +- .../generators/repo_generator.go | 10 +- .../get-previous-version-for-release-notes.go | 10 +- hack/k8s/main.go | 2 +- pkg/apiclient/apiclient.go | 32 ++- pkg/apiclient/grpcproxy.go | 9 +- reposerver/repository/repository_test.go | 22 ++- server/badge/badge_test.go | 30 +-- server/extension/extension_test.go | 16 +- server/logout/logout_test.go | 11 +- server/server.go | 3 +- server/server_norace_test.go | 18 +- test/e2e/applicationset_test.go | 3 +- test/e2e/fixture/applicationsets/utils/cmd.go | 3 +- test/e2e/fixture/cmd.go | 5 +- test/e2e/fixture/http.go | 3 +- test/e2e/helm_test.go | 3 +- test/e2e/metrics_test.go | 10 +- test/testutil.go | 6 +- util/askpass/server.go | 3 +- util/cli/cli.go | 5 +- util/cli/cli_test.go | 2 +- util/config/reader.go | 7 +- util/config/reader_test.go | 3 +- util/dex/dex_test.go | 13 +- util/exec/exec.go | 3 +- util/exec/exec_test.go | 15 +- util/git/client.go | 85 ++++---- util/git/client_test.go | 185 ++++++++++-------- util/git/git_test.go | 16 +- util/gpg/gpg.go | 21 +- util/gpg/gpg_test.go | 2 +- util/healthz/healthz_test.go | 14 +- util/helm/client.go | 13 +- util/helm/cmd.go | 25 +-- util/helm/creds.go | 20 +- util/helm/creds_test.go | 16 +- util/helm/helm.go | 3 +- util/http/http_test.go | 2 +- util/kube/portforwarder.go | 4 +- util/kustomize/kustomize.go | 49 ++--- util/kustomize/kustomize_test.go | 8 +- util/oidc/oidc.go | 2 +- util/profile/profile_test.go | 12 +- util/proxy/proxy_test.go | 4 +- util/session/sessionmanager_test.go | 2 +- util/settings/settings_test.go | 20 +- util/swagger/swagger_test.go | 9 +- 60 files changed, 507 insertions(+), 383 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 72bfe0f257..3219d361f6 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -22,6 +22,7 @@ linters: - govet - importas - misspell + - noctx - perfsprint - revive - staticcheck diff --git a/applicationset/metrics/metrics_test.go b/applicationset/metrics/metrics_test.go index 5b68ae7da0..7ede7b4bcb 100644 --- a/applicationset/metrics/metrics_test.go +++ b/applicationset/metrics/metrics_test.go @@ -174,7 +174,7 @@ func TestApplicationsetCollector(t *testing.T) { appsetCollector := newAppsetCollector(utils.NewAppsetLister(client), collectedLabels, filter) metrics.Registry.MustRegister(appsetCollector) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{}) @@ -216,7 +216,7 @@ func TestObserveReconcile(t *testing.T) { appsetMetrics := NewApplicationsetMetrics(utils.NewAppsetLister(client), collectedLabels, filter) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{}) diff --git a/applicationset/services/github_metrics_test.go b/applicationset/services/github_metrics_test.go index 6f35556996..d20c198705 100644 --- a/applicationset/services/github_metrics_test.go +++ b/applicationset/services/github_metrics_test.go @@ -97,7 +97,9 @@ func TestGitHubMetrics_CollectorApproach_Success(t *testing.T) { ), } - req, _ := http.NewRequest(http.MethodGet, ts.URL+URL, http.NoBody) + ctx := t.Context() + + req, _ := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+URL, http.NoBody) resp, err := client.Do(req) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -109,7 +111,11 @@ func TestGitHubMetrics_CollectorApproach_Success(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err = http.Get(server.URL) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, server.URL, http.NoBody) + if err != nil { + t.Fatalf("failed to create request: %v", err) + } + resp, err = http.DefaultClient.Do(req) if err != nil { t.Fatalf("failed to scrape metrics: %v", err) } @@ -151,15 +157,23 @@ func TestGitHubMetrics_CollectorApproach_NoRateLimitMetricsOnNilResponse(t *test metrics: metrics, }, } + ctx := t.Context() - req, _ := http.NewRequest(http.MethodGet, URL, http.NoBody) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, URL, http.NoBody) + if err != nil { + t.Fatalf("failed to create request: %v", err) + } _, _ = client.Do(req) handler := promhttp.HandlerFor(reg, promhttp.HandlerOpts{}) server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, server.URL, http.NoBody) + if err != nil { + t.Fatalf("failed to create request: %v", err) + } + resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatalf("failed to scrape metrics: %v", err) } diff --git a/applicationset/services/scm_provider/bitbucket_cloud.go b/applicationset/services/scm_provider/bitbucket_cloud.go index 518200855a..214c39156a 100644 --- a/applicationset/services/scm_provider/bitbucket_cloud.go +++ b/applicationset/services/scm_provider/bitbucket_cloud.go @@ -30,7 +30,7 @@ func (c *ExtendedClient) GetContents(repo *Repository, path string) (bool, error urlStr += fmt.Sprintf("/repositories/%s/%s/src/%s/%s?format=meta", c.owner, repo.Repository, repo.SHA, path) body := strings.NewReader("") - req, err := http.NewRequest(http.MethodGet, urlStr, body) + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, urlStr, body) if err != nil { return false, err } diff --git a/cmd/argocd-commit-server/commands/argocd_commit_server.go b/cmd/argocd-commit-server/commands/argocd_commit_server.go index 7feed03381..8ecbaf36af 100644 --- a/cmd/argocd-commit-server/commands/argocd_commit_server.go +++ b/cmd/argocd-commit-server/commands/argocd_commit_server.go @@ -38,7 +38,7 @@ func NewCommand() *cobra.Command { Use: "argocd-commit-server", Short: "Run Argo CD Commit Server", Long: "Argo CD Commit Server is an internal service which commits and pushes hydrated manifests to git. This command runs Commit Server in the foreground.", - RunE: func(_ *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { vers := common.GetVersion() vers.LogStartupInfo( "Argo CD Commit Server", @@ -59,8 +59,10 @@ func NewCommand() *cobra.Command { server := commitserver.NewServer(askPassServer, metricsServer) grpc := server.CreateGRPC() + ctx := cmd.Context() - listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", listenHost, listenPort)) + lc := &net.ListenConfig{} + listener, err := lc.Listen(ctx, "tcp", fmt.Sprintf("%s:%d", listenHost, listenPort)) errors.CheckError(err) healthz.ServeHealthCheck(http.DefaultServeMux, func(r *http.Request) error { diff --git a/cmd/argocd-dex/commands/argocd_dex.go b/cmd/argocd-dex/commands/argocd_dex.go index 9735d997bd..b27aed6b7b 100644 --- a/cmd/argocd-dex/commands/argocd_dex.go +++ b/cmd/argocd-dex/commands/argocd_dex.go @@ -115,7 +115,7 @@ func NewRunDexCommand() *cobra.Command { err = os.WriteFile("/tmp/dex.yaml", dexCfgBytes, 0o644) errors.CheckError(err) log.Debug(redactor(string(dexCfgBytes))) - cmd = exec.Command("dex", "serve", "/tmp/dex.yaml") + cmd = exec.CommandContext(ctx, "dex", "serve", "/tmp/dex.yaml") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Start() diff --git a/cmd/argocd-repo-server/commands/argocd_repo_server.go b/cmd/argocd-repo-server/commands/argocd_repo_server.go index 50eafe1a33..1a227d1d63 100644 --- a/cmd/argocd-repo-server/commands/argocd_repo_server.go +++ b/cmd/argocd-repo-server/commands/argocd_repo_server.go @@ -169,7 +169,8 @@ func NewCommand() *cobra.Command { } grpc := server.CreateGRPC() - listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", listenHost, listenPort)) + lc := &net.ListenConfig{} + listener, err := lc.Listen(ctx, "tcp", fmt.Sprintf("%s:%d", listenHost, listenPort)) errors.CheckError(err) healthz.ServeHealthCheck(http.DefaultServeMux, func(r *http.Request) error { diff --git a/cmd/argocd/commands/headless/headless.go b/cmd/argocd/commands/headless/headless.go index da084fb848..f9a744423b 100644 --- a/cmd/argocd/commands/headless/headless.go +++ b/cmd/argocd/commands/headless/headless.go @@ -213,7 +213,8 @@ func MaybeStartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOpti } if port == nil || *port == 0 { addr := *address + ":0" - ln, err := net.Listen("tcp", addr) + lc := &net.ListenConfig{} + ln, err := lc.Listen(ctx, "tcp", addr) if err != nil { return nil, fmt.Errorf("failed to listen on %q: %w", addr, err) } diff --git a/cmpserver/server.go b/cmpserver/server.go index 9b9ead7b1c..f8f66f3bd6 100644 --- a/cmpserver/server.go +++ b/cmpserver/server.go @@ -1,6 +1,7 @@ package cmpserver import ( + "context" "fmt" "net" "os" @@ -85,7 +86,8 @@ func (a *ArgoCDCMPServer) Run() { // Listen on the socket address _ = os.Remove(config.Address()) - listener, err := net.Listen("unix", config.Address()) + lc := &net.ListenConfig{} + listener, err := lc.Listen(context.Background(), "unix", config.Address()) errors.CheckError(err) log.Infof("argocd-cmp-server %s serving on %s", common.GetVersion(), listener.Addr()) diff --git a/controller/metrics/metrics_test.go b/controller/metrics/metrics_test.go index fa98a6d685..c63d777d11 100644 --- a/controller/metrics/metrics_test.go +++ b/controller/metrics/metrics_test.go @@ -333,7 +333,7 @@ func runTest(t *testing.T, cfg TestMetricServerConfig) { metricsServ.registry.MustRegister(collector) } - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -493,7 +493,7 @@ argocd_app_sync_total{dest_server="https://localhost:6443",dry_run="false",name= metricsServ.IncSync(fakeApp, "https://localhost:6443", &argoappv1.OperationState{Phase: common.OperationSucceeded}) metricsServ.IncSync(fakeApp, "https://localhost:6443", &argoappv1.OperationState{Phase: common.OperationSucceeded}) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -536,7 +536,7 @@ func TestMetricsSyncDuration(t *testing.T) { fakeAppOperationRunning := newFakeApp(fakeAppOperationRunning) metricsServ.IncAppSyncDuration(fakeAppOperationRunning, "https://localhost:6443", fakeAppOperationRunning.Status.OperationState) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -550,7 +550,7 @@ func TestMetricsSyncDuration(t *testing.T) { fakeAppOperationFinished := newFakeApp(fakeAppOperationFinished) metricsServ.IncAppSyncDuration(fakeAppOperationFinished, "https://localhost:6443", fakeAppOperationFinished.Status.OperationState) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -590,7 +590,7 @@ argocd_app_reconcile_count{dest_server="https://localhost:6443",namespace="argoc fakeApp := newFakeApp(fakeApp) metricsServ.IncReconcile(fakeApp, "https://localhost:6443", 5*time.Second) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -616,7 +616,7 @@ argocd_app_orphaned_resources_count{name="my-app-4",namespace="argocd",project=" numOrphanedResources := 1 metricsServ.SetOrphanedResourcesMetric(app, numOrphanedResources) - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -641,7 +641,7 @@ argocd_app_sync_total{dest_server="https://localhost:6443",dry_run="false",name= argocd_app_sync_total{dest_server="https://localhost:6443",dry_run="false",name="my-app",namespace="argocd",phase="Succeeded",project="important-project"} 2 ` - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -652,7 +652,7 @@ argocd_app_sync_total{dest_server="https://localhost:6443",dry_run="false",name= err = metricsServ.SetExpiration(time.Second) require.NoError(t, err) time.Sleep(2 * time.Second) - req, err = http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err = http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr = httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -685,7 +685,7 @@ workqueue_unfinished_work_seconds{controller="test",name="test"} ` workqueue.NewNamed("test") - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) @@ -718,7 +718,7 @@ go_memstats_sys_bytes go_threads ` - req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() metricsServ.Handler.ServeHTTP(rr, req) diff --git a/gitops-engine/agent/main.go b/gitops-engine/agent/main.go index b325e94143..1fa7d9d6f6 100644 --- a/gitops-engine/agent/main.go +++ b/gitops-engine/agent/main.go @@ -59,8 +59,8 @@ func (s *settings) getGCMark(key kube.ResourceKey) string { return "sha256." + base64.RawURLEncoding.EncodeToString(h.Sum(nil)) } -func (s *settings) parseManifests() ([]*unstructured.Unstructured, string, error) { - cmd := exec.Command("git", "rev-parse", "HEAD") +func (s *settings) parseManifests(ctx context.Context) ([]*unstructured.Unstructured, string, error) { + cmd := exec.CommandContext(ctx, "git", "rev-parse", "HEAD") cmd.Dir = s.repoPath revision, err := cmd.CombinedOutput() if err != nil { @@ -134,6 +134,7 @@ func newCmd(log logr.Logger) *cobra.Command { os.Exit(1) } s := settings{args[0], paths} + ctx := cmd.Context() config, err := clientConfig.ClientConfig() checkError(err, log) if namespace == "" { @@ -184,13 +185,13 @@ func newCmd(log logr.Logger) *cobra.Command { }() for ; true; <-resync { - target, revision, err := s.parseManifests() + target, revision, err := s.parseManifests(ctx) if err != nil { log.Error(err, "Failed to parse target state") continue } - result, err := gitOpsEngine.Sync(context.Background(), target, func(r *cache.Resource) bool { + result, err := gitOpsEngine.Sync(ctx, target, func(r *cache.Resource) bool { return r.Info.(*resourceInfo).gcMark == s.getGCMark(r.ResourceKey()) }, revision, namespace, sync.WithPrune(prune), sync.WithLogr(log)) if err != nil { diff --git a/gitops-engine/pkg/diff/diff_test.go b/gitops-engine/pkg/diff/diff_test.go index cf2c3c30c9..7f0019c07c 100644 --- a/gitops-engine/pkg/diff/diff_test.go +++ b/gitops-engine/pkg/diff/diff_test.go @@ -31,7 +31,7 @@ import ( "github.com/argoproj/gitops-engine/pkg/diff/testdata" ) -func printDiff(result *DiffResult) (string, error) { +func printDiff(ctx context.Context, result *DiffResult) (string, error) { var live unstructured.Unstructured if err := json.Unmarshal(result.NormalizedLive, &live); err != nil { return "", fmt.Errorf("failed to unmarshal live object: %w", err) @@ -40,12 +40,12 @@ func printDiff(result *DiffResult) (string, error) { if err := json.Unmarshal(result.PredictedLive, &target); err != nil { return "", fmt.Errorf("failed to unmarshal target object: %w", err) } - out, _ := printDiffInternal("diff", &live, &target) + out, _ := printDiffInternal(ctx, "diff", &live, &target) return string(out), nil } // printDiffInternal prints a diff between two unstructured objects using an external diff utility and returns the output. -func printDiffInternal(name string, live *unstructured.Unstructured, target *unstructured.Unstructured) ([]byte, error) { +func printDiffInternal(ctx context.Context, name string, live *unstructured.Unstructured, target *unstructured.Unstructured) ([]byte, error) { tempDir, err := os.MkdirTemp("", "argocd-diff") if err != nil { return nil, fmt.Errorf("failed to create temp directory: %w", err) @@ -74,7 +74,7 @@ func printDiffInternal(name string, live *unstructured.Unstructured, target *uns if err != nil { return nil, fmt.Errorf("failed to write live object: %w", err) } - cmd := exec.Command("diff", liveFile, targetFile) + cmd := exec.CommandContext(ctx, "diff", liveFile, targetFile) out, err := cmd.Output() if err != nil { // return output even if there's an error @@ -168,7 +168,7 @@ func TestDiff(t *testing.T) { diffRes := diff(t, leftUn, leftUn, diffOptionsForTest()...) assert.False(t, diffRes.Modified) - ascii, err := printDiff(diffRes) + ascii, err := printDiff(t.Context(), diffRes) require.NoError(t, err) if ascii != "" { t.Log(ascii) @@ -183,7 +183,7 @@ func TestDiff_KnownTypeInvalidValue(t *testing.T) { t.Run("NoDifference", func(t *testing.T) { diffRes := diff(t, leftUn, leftUn, diffOptionsForTest()...) assert.False(t, diffRes.Modified) - ascii, err := printDiff(diffRes) + ascii, err := printDiff(t.Context(), diffRes) require.NoError(t, err) if ascii != "" { t.Log(ascii) @@ -294,7 +294,7 @@ func TestThreeWayDiff(t *testing.T) { liveUn := mustToUnstructured(liveDep) res := diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.False(t, res.Modified) { - ascii, err := printDiff(res) + ascii, err := printDiff(t.Context(), res) require.NoError(t, err) t.Log(ascii) } @@ -308,7 +308,7 @@ func TestThreeWayDiff(t *testing.T) { liveUn = mustToUnstructured(liveDep) res = diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.False(t, res.Modified) { - ascii, err := printDiff(res) + ascii, err := printDiff(t.Context(), res) require.NoError(t, err) t.Log(ascii) } @@ -329,7 +329,7 @@ func TestThreeWayDiff(t *testing.T) { configUn = mustToUnstructured(configDep) liveUn = mustToUnstructured(liveDep) res = diff(t, configUn, liveUn, diffOptionsForTest()...) - ascii, err := printDiff(res) + ascii, err := printDiff(t.Context(), res) require.NoError(t, err) if ascii != "" { t.Log(ascii) @@ -388,7 +388,7 @@ func TestThreeWayDiffExample1(t *testing.T) { require.NoError(t, err) dr := diff(t, &configUn, &liveUn, diffOptionsForTest()...) assert.False(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) if ascii != "" { t.Log(ascii) @@ -403,7 +403,7 @@ func TestDiffOptionIgnoreAggregateRoles(t *testing.T) { liveUn := unmarshalFile("testdata/aggr-clusterrole-live.json") dr := diff(t, configUn, liveUn, IgnoreAggregatedRoles(true)) assert.False(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -413,7 +413,7 @@ func TestDiffOptionIgnoreAggregateRoles(t *testing.T) { liveUn := unmarshalFile("testdata/aggr-clusterrole-live.json") dr := diff(t, configUn, liveUn, IgnoreAggregatedRoles(false)) assert.True(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -424,7 +424,7 @@ func TestThreeWayDiffExample2(t *testing.T) { liveUn := unmarshalFile("testdata/elasticsearch-live.json") dr := diff(t, configUn, liveUn, diffOptionsForTest()...) assert.False(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -436,7 +436,7 @@ func TestThreeWayDiffExample3(t *testing.T) { dr := diff(t, configUn, liveUn, diffOptionsForTest()...) assert.False(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) if ascii != "" { t.Log(ascii) @@ -449,7 +449,7 @@ func TestThreeWayDiffExample4(t *testing.T) { dr := diff(t, configUn, liveUn, diffOptionsForTest()...) assert.False(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) if ascii != "" { t.Log(ascii) @@ -471,7 +471,7 @@ func TestThreeWayDiffExample2WithDifference(t *testing.T) { dr := diff(t, configUn, liveUn, diffOptionsForTest()...) assert.True(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err, ascii) t.Log(ascii) @@ -503,7 +503,7 @@ func TestThreeWayDiffExplicitNamespace(t *testing.T) { liveUn := unmarshalFile("testdata/spinnaker-sa-live.json") dr := diff(t, configUn, liveUn, diffOptionsForTest()...) assert.False(t, dr.Modified) - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -530,7 +530,7 @@ func TestDiffResourceWithInvalidField(t *testing.T) { diffRes := diff(t, &leftUn, rightUn, diffOptionsForTest()...) assert.True(t, diffRes.Modified) - ascii, err := printDiff(diffRes) + ascii, err := printDiff(t.Context(), diffRes) require.NoError(t, err) assert.Contains(t, ascii, "invalidKey") @@ -646,7 +646,7 @@ func TestSecretStringData(t *testing.T) { dr := diff(t, &configUn, &liveUn, diffOptionsForTest()...) if !assert.False(t, dr.Modified) { - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -697,7 +697,7 @@ func TestNullSecretData(t *testing.T) { liveUn := unmarshalFile("testdata/wordpress-live.json") dr := diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.False(t, dr.Modified) { - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -716,7 +716,7 @@ func TestRedactedSecretData(t *testing.T) { liveData["smtp-password"] = "++++++++++++" dr := diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.True(t, dr.Modified) { - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -727,7 +727,7 @@ func TestNullRoleRule(t *testing.T) { liveUn := unmarshalFile("testdata/grafana-clusterrole-live.json") dr := diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.False(t, dr.Modified) { - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -738,7 +738,7 @@ func TestNullCreationTimestamp(t *testing.T) { liveUn := unmarshalFile("testdata/sealedsecret-live.json") dr := diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.False(t, dr.Modified) { - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } @@ -749,7 +749,7 @@ func TestUnsortedEndpoints(t *testing.T) { liveUn := unmarshalFile("testdata/endpoints-live.json") dr := diff(t, configUn, liveUn, diffOptionsForTest()...) if !assert.False(t, dr.Modified) { - ascii, err := printDiff(dr) + ascii, err := printDiff(t.Context(), dr) require.NoError(t, err) t.Log(ascii) } diff --git a/hack/gen-crd-spec/main.go b/hack/gen-crd-spec/main.go index c102e9b2f6..cd700fb535 100644 --- a/hack/gen-crd-spec/main.go +++ b/hack/gen-crd-spec/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "errors" "fmt" @@ -22,8 +23,8 @@ var kindToCRDPath = map[string]string{ application.ApplicationSetFullName: "manifests/crds/applicationset-crd.yaml", } -func getCustomResourceDefinitions() map[string]*apiextensionsv1.CustomResourceDefinition { - crdYamlBytes, err := exec.Command( +func getCustomResourceDefinitions(ctx context.Context) map[string]*apiextensionsv1.CustomResourceDefinition { + crdYamlBytes, err := exec.CommandContext(ctx, "controller-gen", "paths=./pkg/apis/application/...", "crd:crdVersions=v1", @@ -124,7 +125,7 @@ func checkErr(err error) { } func main() { - crdsapp := getCustomResourceDefinitions() + crdsapp := getCustomResourceDefinitions(context.Background()) for kind, path := range kindToCRDPath { crd := crdsapp[kind] if crd == nil { diff --git a/hack/gen-resources/generators/repo_generator.go b/hack/gen-resources/generators/repo_generator.go index 55057f7a0a..c409e96d2d 100644 --- a/hack/gen-resources/generators/repo_generator.go +++ b/hack/gen-resources/generators/repo_generator.go @@ -31,11 +31,10 @@ func NewRepoGenerator(clientSet *kubernetes.Clientset) Generator { return &RepoGenerator{clientSet: clientSet, bar: &util.Bar{}} } -func fetchRepos(token string, page int) ([]Repo, error) { - client := &http.Client{} - req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("https://api.github.com/repos/argoproj/argocd-example-apps/forks?per_page=100&page=%v", page), http.NoBody) +func fetchRepos(ctx context.Context, token string, page int) ([]Repo, error) { + req, _ := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://api.github.com/repos/argoproj/argocd-example-apps/forks?per_page=100&page=%v", page), http.NoBody) req.Header.Set("Authorization", token) - resp, err := client.Do(req) + resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } @@ -54,6 +53,7 @@ func fetchRepos(token string, page int) ([]Repo, error) { func FetchRepos(token string, samples int) ([]Repo, error) { log.Print("Fetch repos started") var ( + ctx = context.Background() repos []Repo page = 1 ) @@ -62,7 +62,7 @@ func FetchRepos(token string, samples int) ([]Repo, error) { if page%10 == 0 { log.Printf("Fetch repos, page: %v", page) } - fetchedRepos, err := fetchRepos(token, page) + fetchedRepos, err := fetchRepos(ctx, token, page) if err != nil { return nil, err } diff --git a/hack/get-previous-release/get-previous-version-for-release-notes.go b/hack/get-previous-release/get-previous-version-for-release-notes.go index 1118357324..4e43236aec 100644 --- a/hack/get-previous-release/get-previous-version-for-release-notes.go +++ b/hack/get-previous-release/get-previous-version-for-release-notes.go @@ -1,12 +1,14 @@ package main import ( + "context" "fmt" - "golang.org/x/mod/semver" "os" "os/exec" "regexp" "strings" + + "golang.org/x/mod/semver" ) /** @@ -22,7 +24,7 @@ func main() { proposedTag := os.Args[1] - tags, err := getGitTags() + tags, err := getGitTags(context.Background()) if err != nil { fmt.Printf("Error getting git tags: %v\n", err) return @@ -110,8 +112,8 @@ func findPreviousTag(proposedTag string, tags []string) (string, error) { return previousTag, nil } -func getGitTags() ([]string, error) { - cmd := exec.Command("git", "tag", "--sort=-v:refname") +func getGitTags(ctx context.Context) ([]string, error) { + cmd := exec.CommandContext(ctx, "git", "tag", "--sort=-v:refname") output, err := cmd.Output() if err != nil { return nil, fmt.Errorf("error executing git command: %v", err) diff --git a/hack/k8s/main.go b/hack/k8s/main.go index ddaf99f13e..7e5a33798b 100644 --- a/hack/k8s/main.go +++ b/hack/k8s/main.go @@ -44,7 +44,7 @@ func main() { } errors.CheckError(err) - cmd := exec.Command("kubectl", "apply", "-k", "manifests/base/config") + cmd := exec.CommandContext(context.Background(), "kubectl", "apply", "-k", "manifests/base/config") cmd.Env = []string{"KUBECONFIG=" + kubeConfigPath} errors.CheckError(cmd.Run()) <-context.Background().Done() diff --git a/pkg/apiclient/apiclient.go b/pkg/apiclient/apiclient.go index 43d14494d4..4910af2edc 100644 --- a/pkg/apiclient/apiclient.go +++ b/pkg/apiclient/apiclient.go @@ -490,13 +490,13 @@ func (c jwtCredentials) GetRequestMetadata(context.Context, ...string) (map[stri }, nil } -func (c *client) newConn() (*grpc.ClientConn, io.Closer, error) { +func (c *client) newConn(ctx context.Context) (*grpc.ClientConn, io.Closer, error) { closers := make([]io.Closer, 0) serverAddr := c.ServerAddr network := "tcp" if c.GRPCWeb || c.GRPCWebRootPath != "" { // start local grpc server which proxies requests using grpc-web protocol - addr, closer, err := c.useGRPCProxy() + addr, closer, err := c.useGRPCProxy(ctx) if err != nil { return nil, nil, err } @@ -527,8 +527,6 @@ func (c *client) newConn() (*grpc.ClientConn, io.Closer, error) { dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor(retryOpts...))) dialOpts = append(dialOpts, grpc.WithStatsHandler(otelgrpc.NewClientHandler())) - ctx := context.Background() - headers, err := parseHeaders(c.Headers) if err != nil { return nil, nil, err @@ -584,7 +582,7 @@ func (c *client) ClientOptions() ClientOptions { } func (c *client) NewRepoClient() (io.Closer, repositorypkg.RepositoryServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -601,7 +599,7 @@ func (c *client) NewRepoClientOrDie() (io.Closer, repositorypkg.RepositoryServic } func (c *client) NewRepoCredsClient() (io.Closer, repocredspkg.RepoCredsServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -618,7 +616,7 @@ func (c *client) NewRepoCredsClientOrDie() (io.Closer, repocredspkg.RepoCredsSer } func (c *client) NewCertClient() (io.Closer, certificatepkg.CertificateServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -635,7 +633,7 @@ func (c *client) NewCertClientOrDie() (io.Closer, certificatepkg.CertificateServ } func (c *client) NewClusterClient() (io.Closer, clusterpkg.ClusterServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -652,7 +650,7 @@ func (c *client) NewClusterClientOrDie() (io.Closer, clusterpkg.ClusterServiceCl } func (c *client) NewGPGKeyClient() (io.Closer, gpgkeypkg.GPGKeyServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -669,7 +667,7 @@ func (c *client) NewGPGKeyClientOrDie() (io.Closer, gpgkeypkg.GPGKeyServiceClien } func (c *client) NewApplicationClient() (io.Closer, applicationpkg.ApplicationServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -678,7 +676,7 @@ func (c *client) NewApplicationClient() (io.Closer, applicationpkg.ApplicationSe } func (c *client) NewApplicationSetClient() (io.Closer, applicationsetpkg.ApplicationSetServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -695,7 +693,7 @@ func (c *client) NewApplicationClientOrDie() (io.Closer, applicationpkg.Applicat } func (c *client) NewNotificationClient() (io.Closer, notificationpkg.NotificationServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -720,7 +718,7 @@ func (c *client) NewApplicationSetClientOrDie() (io.Closer, applicationsetpkg.Ap } func (c *client) NewSessionClient() (io.Closer, sessionpkg.SessionServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -737,7 +735,7 @@ func (c *client) NewSessionClientOrDie() (io.Closer, sessionpkg.SessionServiceCl } func (c *client) NewSettingsClient() (io.Closer, settingspkg.SettingsServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -754,7 +752,7 @@ func (c *client) NewSettingsClientOrDie() (io.Closer, settingspkg.SettingsServic } func (c *client) NewVersionClient() (io.Closer, versionpkg.VersionServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -771,7 +769,7 @@ func (c *client) NewVersionClientOrDie() (io.Closer, versionpkg.VersionServiceCl } func (c *client) NewProjectClient() (io.Closer, projectpkg.ProjectServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } @@ -788,7 +786,7 @@ func (c *client) NewProjectClientOrDie() (io.Closer, projectpkg.ProjectServiceCl } func (c *client) NewAccountClient() (io.Closer, accountpkg.AccountServiceClient, error) { - conn, closer, err := c.newConn() + conn, closer, err := c.newConn(context.Background()) if err != nil { return nil, nil, err } diff --git a/pkg/apiclient/grpcproxy.go b/pkg/apiclient/grpcproxy.go index b1b4ce3670..df55bc6fb1 100644 --- a/pkg/apiclient/grpcproxy.go +++ b/pkg/apiclient/grpcproxy.go @@ -103,13 +103,14 @@ func (c *client) executeRequest(ctx context.Context, fullMethodName string, msg return resp, nil } -func (c *client) startGRPCProxy() (*grpc.Server, net.Listener, error) { +func (c *client) startGRPCProxy(ctx context.Context) (*grpc.Server, net.Listener, error) { randSuffix, err := rand.String(16) if err != nil { return nil, nil, fmt.Errorf("failed to generate random socket filename: %w", err) } serverAddr := fmt.Sprintf("%s/argocd-%s.sock", os.TempDir(), randSuffix) - ln, err := net.Listen("unix", serverAddr) + lc := &net.ListenConfig{} + ln, err := lc.Listen(ctx, "unix", serverAddr) if err != nil { return nil, nil, err } @@ -188,13 +189,13 @@ func (c *client) startGRPCProxy() (*grpc.Server, net.Listener, error) { } // useGRPCProxy ensures that grpc proxy server is started and return closer which stops server when no one uses it -func (c *client) useGRPCProxy() (net.Addr, io.Closer, error) { +func (c *client) useGRPCProxy(ctx context.Context) (net.Addr, io.Closer, error) { c.proxyMutex.Lock() defer c.proxyMutex.Unlock() if c.proxyListener == nil { var err error - c.proxyServer, c.proxyListener, err = c.startGRPCProxy() + c.proxyServer, c.proxyListener, err = c.startGRPCProxy(ctx) if err != nil { return nil, nil, err } diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go index 053f2aa514..7980b15e46 100644 --- a/reposerver/repository/repository_test.go +++ b/reposerver/repository/repository_test.go @@ -2049,12 +2049,12 @@ func TestGetAppDetailsWithAppParameterFile(t *testing.T) { // There are unit test that will use kustomize set and by that modify the // kustomization.yaml. For proper testing, we need to copy the testdata to a // temporary path, run the tests, and then throw the copy away again. -func mkTempParameters(source string) string { +func mkTempParameters(ctx context.Context, source string) string { tempDir, err := os.MkdirTemp("./testdata", "app-parameters") if err != nil { panic(err) } - cmd := exec.Command("cp", "-R", source, tempDir) + cmd := exec.CommandContext(ctx, "cp", "-R", source, tempDir) err = cmd.Run() if err != nil { os.RemoveAll(tempDir) @@ -2067,7 +2067,7 @@ func mkTempParameters(source string) string { // the test would modify the data when run. func runWithTempTestdata(t *testing.T, path string, runner func(t *testing.T, path string)) { t.Helper() - tempDir := mkTempParameters("./testdata/app-parameters") + tempDir := mkTempParameters(t.Context(), "./testdata/app-parameters") runner(t, filepath.Join(tempDir, "app-parameters", path)) os.RemoveAll(tempDir) } @@ -3068,6 +3068,7 @@ func TestDirectoryPermissionInitializer(t *testing.T) { func addHelmToGitRepo(t *testing.T, options newGitRepoOptions) { t.Helper() + ctx := t.Context() err := os.WriteFile(filepath.Join(options.path, "Chart.yaml"), []byte("name: test\nversion: v1.0.0"), 0o777) require.NoError(t, err) for valuesFileName, values := range options.helmChartOptions.valuesFiles { @@ -3077,10 +3078,10 @@ func addHelmToGitRepo(t *testing.T, options newGitRepoOptions) { require.NoError(t, err) } require.NoError(t, err) - cmd := exec.Command("git", "add", "-A") + cmd := exec.CommandContext(ctx, "git", "add", "-A") cmd.Dir = options.path require.NoError(t, cmd.Run()) - cmd = exec.Command("git", "commit", "-m", "Initial commit") + cmd = exec.CommandContext(ctx, "git", "commit", "-m", "Initial commit") cmd.Dir = options.path require.NoError(t, cmd.Run()) } @@ -3090,20 +3091,21 @@ func initGitRepo(t *testing.T, options newGitRepoOptions) (revision string) { if options.createPath { require.NoError(t, os.Mkdir(options.path, 0o755)) } + ctx := t.Context() - cmd := exec.Command("git", "init", "-b", "main", options.path) + cmd := exec.CommandContext(ctx, "git", "init", "-b", "main", options.path) cmd.Dir = options.path require.NoError(t, cmd.Run()) if options.remote != "" { - cmd = exec.Command("git", "remote", "add", "origin", options.path) + cmd = exec.CommandContext(ctx, "git", "remote", "add", "origin", options.path) cmd.Dir = options.path require.NoError(t, cmd.Run()) } commitAdded := options.addEmptyCommit || options.helmChartOptions.chartName != "" if options.addEmptyCommit { - cmd = exec.Command("git", "commit", "-m", "Initial commit", "--allow-empty") + cmd = exec.CommandContext(ctx, "git", "commit", "-m", "Initial commit", "--allow-empty") cmd.Dir = options.path require.NoError(t, cmd.Run()) } else if options.helmChartOptions.chartName != "" { @@ -3112,7 +3114,7 @@ func initGitRepo(t *testing.T, options newGitRepoOptions) (revision string) { if commitAdded { var revB bytes.Buffer - cmd = exec.Command("git", "rev-parse", "HEAD", options.path) + cmd = exec.CommandContext(ctx, "git", "rev-parse", "HEAD", options.path) cmd.Dir = options.path cmd.Stdout = &revB require.NoError(t, cmd.Run()) @@ -3263,7 +3265,7 @@ func TestFetchRevisionCanGetNonstandardRefs(t *testing.T) { // and error output. If it fails, it stops the test with a failure message. func runGit(t *testing.T, workDir string, args ...string) string { t.Helper() - cmd := exec.Command("git", args...) + cmd := exec.CommandContext(t.Context(), "git", args...) cmd.Dir = workDir out, err := cmd.CombinedOutput() stringOut := string(out) diff --git a/server/badge/badge_test.go b/server/badge/badge_test.go index a004c4e3ae..0997eef49b 100644 --- a/server/badge/badge_test.go +++ b/server/badge/badge_test.go @@ -101,7 +101,7 @@ func testProject() *v1alpha1.AppProject { func TestHandlerFeatureIsEnabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp()), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -204,7 +204,7 @@ func TestHandlerFeatureProjectIsEnabled(t *testing.T) { } handler := NewHandler(appclientset.NewSimpleClientset(objects...), settingsMgr, tt.namespace, []string{}) rr := httptest.NewRecorder() - req, err := http.NewRequest(http.MethodGet, tt.apiEndPoint, http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, tt.apiEndPoint, http.NoBody) require.NoError(t, err) handler.ServeHTTP(rr, req) require.Equal(t, tt.response, rr.Result().StatusCode) @@ -226,7 +226,7 @@ func TestHandlerNamespacesIsEnabled(t *testing.T) { t.Run("Application in allowed namespace", func(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp2()), settingsMgr, "default", []string{"argocd-test"}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&namespace=argocd-test", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&namespace=argocd-test", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -247,7 +247,7 @@ func TestHandlerNamespacesIsEnabled(t *testing.T) { t.Run("Application in disallowed namespace", func(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp2()), settingsMgr, "default", []string{"argocd-test"}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&namespace=kube-system", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&namespace=kube-system", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -264,7 +264,7 @@ func TestHandlerNamespacesIsEnabled(t *testing.T) { t.Run("Request with illegal namespace", func(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp2()), settingsMgr, "default", []string{"argocd-test"}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&namespace=kube()system", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&namespace=kube()system", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -277,7 +277,7 @@ func TestHandlerNamespacesIsEnabled(t *testing.T) { func TestHandlerFeatureIsEnabledKeepFullRevisionIsEnabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp3()), settingsMgr, "argocd-test", []string{""}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true&keepFullRevision=true", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true&keepFullRevision=true", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -298,7 +298,7 @@ func TestHandlerFeatureIsEnabledKeepFullRevisionIsEnabled(t *testing.T) { func TestHandlerFeatureIsEnabledKeepFullRevisionIsDisabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp3()), settingsMgr, "argocd-test", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true&keepFullRevision=false", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true&keepFullRevision=false", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -319,7 +319,7 @@ func TestHandlerFeatureIsEnabledKeepFullRevisionIsDisabled(t *testing.T) { func TestHandlerFeatureIsEnabledKeepFullRevisionAndWidthIsEnabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp3()), settingsMgr, "argocd-test", []string{""}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true&keepFullRevision=true&width=500", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true&keepFullRevision=true&width=500", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -393,7 +393,7 @@ func createApplicationsWithName(appCombo, projectName []string, namespace string func TestHandlerFeatureIsEnabledRevisionIsEnabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp()), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -417,7 +417,7 @@ func TestHandlerRevisionIsEnabledNoOperationState(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -441,7 +441,7 @@ func TestHandlerRevisionIsEnabledShortCommitSHA(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -458,7 +458,7 @@ func TestHandlerRevisionIsEnabledMultipleSources(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&revision=true", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -475,7 +475,7 @@ func TestHandlerFeatureIsDisabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewSimpleClientset(argoCDCmDisabled, argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp()), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -496,7 +496,7 @@ func TestHandlerFeatureIsDisabled(t *testing.T) { func TestHandlerApplicationNameInBadgeIsEnabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewSimpleClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp()), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&showAppName=true", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app&showAppName=true", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() @@ -523,7 +523,7 @@ func TestHandlerApplicationNameInBadgeIsEnabled(t *testing.T) { func TestHandlerApplicationNameInBadgeIsDisabled(t *testing.T) { settingsMgr := settings.NewSettingsManager(t.Context(), fake.NewSimpleClientset(argoCDCm(), argoCDSecret()), "default") handler := NewHandler(appclientset.NewSimpleClientset(testApp()), settingsMgr, "default", []string{}) - req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/api/badge?name=test-app", http.NoBody) require.NoError(t, err) rr := httptest.NewRecorder() diff --git a/server/extension/extension_test.go b/server/extension/extension_test.go index 377ab7623d..2e00b33780 100644 --- a/server/extension/extension_test.go +++ b/server/extension/extension_test.go @@ -28,7 +28,7 @@ import ( func TestValidateHeaders(t *testing.T) { t.Run("will build RequestResources successfully", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "namespace:app-name") r.Header.Add(extension.HeaderArgoCDProjectName, "project-name") @@ -45,7 +45,7 @@ func TestValidateHeaders(t *testing.T) { }) t.Run("will return error if application is malformatted", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "no-namespace") @@ -58,7 +58,7 @@ func TestValidateHeaders(t *testing.T) { }) t.Run("will return error if application header is missing", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDProjectName, "project-name") @@ -71,7 +71,7 @@ func TestValidateHeaders(t *testing.T) { }) t.Run("will return error if project header is missing", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "namespace:app-name") @@ -84,7 +84,7 @@ func TestValidateHeaders(t *testing.T) { }) t.Run("will return error if invalid namespace", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "bad%namespace:app-name") r.Header.Add(extension.HeaderArgoCDProjectName, "project-name") @@ -98,7 +98,7 @@ func TestValidateHeaders(t *testing.T) { }) t.Run("will return error if invalid app name", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "namespace:bad@app") r.Header.Add(extension.HeaderArgoCDProjectName, "project-name") @@ -112,7 +112,7 @@ func TestValidateHeaders(t *testing.T) { }) t.Run("will return error if invalid project name", func(t *testing.T) { // given - r, err := http.NewRequest(http.MethodGet, "http://null", http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://null", http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "namespace:app") r.Header.Add(extension.HeaderArgoCDProjectName, "bad^project") @@ -390,7 +390,7 @@ func TestCallExtension(t *testing.T) { } newExtensionRequest := func(t *testing.T, method, url string) *http.Request { t.Helper() - r, err := http.NewRequest(method, url, http.NoBody) + r, err := http.NewRequestWithContext(t.Context(), method, url, http.NoBody) require.NoError(t, err, "error initializing request") r.Header.Add(extension.HeaderArgoCDApplicationName, "namespace:app-name") r.Header.Add(extension.HeaderArgoCDProjectName, defaultProjectName) diff --git a/server/logout/logout_test.go b/server/logout/logout_test.go index 27f1b0b043..e007d3a054 100644 --- a/server/logout/logout_test.go +++ b/server/logout/logout_test.go @@ -286,21 +286,22 @@ func TestHandlerConstructLogoutURL(t *testing.T) { nonOidcTokenHeader["Cookie"] = []string{"argocd.token=" + nonOidcToken} invalidHeader := make(map[string][]string) invalidHeader["Cookie"] = []string{"argocd.token=" + invalidToken} + ctx := t.Context() - oidcRequest, err := http.NewRequest(http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) + oidcRequest, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) require.NoError(t, err) oidcRequest.Header = oidcTokenHeader - nonoidcRequest, err := http.NewRequest(http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) + nonoidcRequest, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) require.NoError(t, err) nonoidcRequest.Header = nonOidcTokenHeader - nonoidcRequestOnSecondHost, err := http.NewRequest(http.MethodGet, "http://argocd.my-corp.tld/api/logout", http.NoBody) + nonoidcRequestOnSecondHost, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://argocd.my-corp.tld/api/logout", http.NoBody) assert.NoError(t, err) nonoidcRequestOnSecondHost.Header = nonOidcTokenHeader assert.NoError(t, err) - requestWithInvalidToken, err := http.NewRequest(http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) + requestWithInvalidToken, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) require.NoError(t, err) requestWithInvalidToken.Header = invalidHeader - invalidRequest, err := http.NewRequest(http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) + invalidRequest, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:4000/api/logout", http.NoBody) require.NoError(t, err) tests := []struct { diff --git a/server/server.go b/server/server.go index ae100e64bf..28bd794d74 100644 --- a/server/server.go +++ b/server/server.go @@ -495,8 +495,9 @@ func (server *ArgoCDServer) logInClusterWarnings() error { func startListener(host string, port int) (net.Listener, error) { var conn net.Listener var realErr error + lc := net.ListenConfig{} _ = wait.ExponentialBackoff(backoff, func() (bool, error) { - conn, realErr = net.Listen("tcp", fmt.Sprintf("%s:%d", host, port)) + conn, realErr = lc.Listen(context.Background(), "tcp", fmt.Sprintf("%s:%d", host, port)) if realErr != nil { return false, nil } diff --git a/server/server_norace_test.go b/server/server_norace_test.go index 9bce6410fa..dcbdf12be6 100644 --- a/server/server_norace_test.go +++ b/server/server_norace_test.go @@ -108,14 +108,14 @@ func Test_StaticHeaders(t *testing.T) { // Allow server startup time.Sleep(1 * time.Second) - client := http.Client{} url := fmt.Sprintf("http://127.0.0.1:%d/test.html", s.ListenPort) - req, err := http.NewRequest(http.MethodGet, url, http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, url, http.NoBody) require.NoError(t, err) - resp, err := client.Do(req) + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Equal(t, "sameorigin", resp.Header.Get("X-Frame-Options")) assert.Equal(t, "frame-ancestors 'self';", resp.Header.Get("Content-Security-Policy")) + require.NoError(t, resp.Body.Close()) } // Test custom policy for X-Frame-Options and Content-Security-Policy @@ -137,14 +137,14 @@ func Test_StaticHeaders(t *testing.T) { // Allow server startup time.Sleep(1 * time.Second) - client := http.Client{} url := fmt.Sprintf("http://127.0.0.1:%d/test.html", s.ListenPort) - req, err := http.NewRequest(http.MethodGet, url, http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, url, http.NoBody) require.NoError(t, err) - resp, err := client.Do(req) + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Equal(t, "deny", resp.Header.Get("X-Frame-Options")) assert.Equal(t, "frame-ancestors 'none';", resp.Header.Get("Content-Security-Policy")) + require.NoError(t, resp.Body.Close()) } // Test disabled X-Frame-Options and Content-Security-Policy @@ -169,13 +169,13 @@ func Test_StaticHeaders(t *testing.T) { // Allow server startup time.Sleep(1 * time.Second) - client := http.Client{} url := fmt.Sprintf("http://127.0.0.1:%d/test.html", s.ListenPort) - req, err := http.NewRequest(http.MethodGet, url, http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, url, http.NoBody) require.NoError(t, err) - resp, err := client.Do(req) + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Empty(t, resp.Header.Get("X-Frame-Options")) assert.Empty(t, resp.Header.Get("Content-Security-Policy")) + require.NoError(t, resp.Body.Close()) } } diff --git a/test/e2e/applicationset_test.go b/test/e2e/applicationset_test.go index bdc486ff22..ea3d7719b5 100644 --- a/test/e2e/applicationset_test.go +++ b/test/e2e/applicationset_test.go @@ -1316,7 +1316,8 @@ func githubSCMMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) func testServerWithPort(t *testing.T, port int, handler http.Handler) *httptest.Server { t.Helper() // Use mocked API response to avoid rate-limiting. - l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + lc := net.ListenConfig{} + l, err := lc.Listen(t.Context(), "tcp", fmt.Sprintf("127.0.0.1:%d", port)) require.NoError(t, err, "Unable to start server") ts := httptest.NewUnstartedServer(handler) diff --git a/test/e2e/fixture/applicationsets/utils/cmd.go b/test/e2e/fixture/applicationsets/utils/cmd.go index 434e9454d7..a69759649e 100644 --- a/test/e2e/fixture/applicationsets/utils/cmd.go +++ b/test/e2e/fixture/applicationsets/utils/cmd.go @@ -1,6 +1,7 @@ package utils import ( + "context" "os" "os/exec" "strings" @@ -13,7 +14,7 @@ func Run(workDir, name string, args ...string) (string, error) { } func RunWithStdin(stdin, workDir, name string, args ...string) (string, error) { - cmd := exec.Command(name, args...) + cmd := exec.CommandContext(context.Background(), name, args...) if stdin != "" { cmd.Stdin = strings.NewReader(stdin) } diff --git a/test/e2e/fixture/cmd.go b/test/e2e/fixture/cmd.go index 579691b1f2..7887ac2aab 100644 --- a/test/e2e/fixture/cmd.go +++ b/test/e2e/fixture/cmd.go @@ -1,6 +1,7 @@ package fixture import ( + "context" "os" "os/exec" "strings" @@ -13,7 +14,7 @@ func Run(workDir, name string, args ...string) (string, error) { } func RunWithStdin(stdin, workDir, name string, args ...string) (string, error) { - cmd := exec.Command(name, args...) + cmd := exec.CommandContext(context.Background(), name, args...) if stdin != "" { cmd.Stdin = strings.NewReader(stdin) } @@ -24,7 +25,7 @@ func RunWithStdin(stdin, workDir, name string, args ...string) (string, error) { } func RunWithStdinWithRedactor(stdin, workDir, name string, redactor func(string) string, args ...string) (string, error) { - cmd := exec.Command(name, args...) + cmd := exec.CommandContext(context.Background(), name, args...) if stdin != "" { cmd.Stdin = strings.NewReader(stdin) } diff --git a/test/e2e/fixture/http.go b/test/e2e/fixture/http.go index c2c3fa2cbe..47911f35ad 100644 --- a/test/e2e/fixture/http.go +++ b/test/e2e/fixture/http.go @@ -2,6 +2,7 @@ package fixture import ( "bytes" + "context" "crypto/tls" "encoding/json" "io" @@ -27,7 +28,7 @@ func DoHttpRequest(method string, path string, host string, data ...byte) (*http if data != nil { body = bytes.NewReader(data) } - req, err := http.NewRequest(method, reqURL.String(), body) + req, err := http.NewRequestWithContext(context.Background(), method, reqURL.String(), body) if err != nil { return nil, err } diff --git a/test/e2e/helm_test.go b/test/e2e/helm_test.go index 30dce46fe3..d15ab46953 100644 --- a/test/e2e/helm_test.go +++ b/test/e2e/helm_test.go @@ -208,9 +208,10 @@ func TestHelmValuesLiteralFileLocal(t *testing.T) { func TestHelmValuesLiteralFileRemote(t *testing.T) { sentinel := "a: b" + lc := &net.ListenConfig{} serve := func(c chan<- string) { // listen on first available dynamic (unprivileged) port - listener, err := net.Listen("tcp", ":0") + listener, err := lc.Listen(t.Context(), "tcp", ":0") if err != nil { panic(err) } diff --git a/test/e2e/metrics_test.go b/test/e2e/metrics_test.go index cd5c4672c2..cb8f4e3ac6 100644 --- a/test/e2e/metrics_test.go +++ b/test/e2e/metrics_test.go @@ -60,8 +60,11 @@ func TestKubectlMetrics(t *testing.T) { assert.Equal(t, "master", app.Spec.GetSource().TargetRevision) }) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://127.0.0.1:8082/metrics", http.NoBody) + require.NoError(t, err) + // Make a request to the app controller metrics endpoint and ensure the response contains kubectl metrics. - resp, err := http.Get("http://127.0.0.1:8082/metrics") + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) defer func() { err = resp.Body.Close() @@ -87,8 +90,11 @@ func TestKubectlMetrics(t *testing.T) { - argocd_kubectl_transport_create_calls_total: The transport cache is only used under certain conditions, which this test doesn't encounter. */ + req, err = http.NewRequestWithContext(t.Context(), http.MethodGet, "http://127.0.0.1:8083/metrics", http.NoBody) + require.NoError(t, err) + // Repeat the test for port 8083, i.e. the API server. - resp, err = http.Get("http://127.0.0.1:8083/metrics") + resp, err = http.DefaultClient.Do(req) require.NoError(t, err) defer func() { err = resp.Body.Close() diff --git a/test/testutil.go b/test/testutil.go index f2245f59af..e02f5f545c 100644 --- a/test/testutil.go +++ b/test/testutil.go @@ -30,7 +30,8 @@ func StartInformer(informer cache.SharedIndexInformer) context.CancelFunc { // GetFreePort finds an available free port on the OS func GetFreePort() (int, error) { - ln, err := net.Listen("tcp", "[::]:0") + lc := &net.ListenConfig{} + ln, err := lc.Listen(context.Background(), "tcp", "[::]:0") if err != nil { return 0, err } @@ -60,7 +61,8 @@ func WaitForPortListen(addr string, timeout time.Duration) error { } func portIsOpen(addr string) bool { - conn, err := net.Dial("tcp", addr) + d := &net.Dialer{} + conn, err := d.DialContext(context.Background(), "tcp", addr) if err != nil { return false } diff --git a/util/askpass/server.go b/util/askpass/server.go index 65204a1651..651742db79 100644 --- a/util/askpass/server.go +++ b/util/askpass/server.go @@ -63,7 +63,8 @@ func (s *server) GetCredentials(_ context.Context, q *CredentialsRequest) (*Cred func (s *server) Start(path string) (utilio.Closer, error) { _ = os.Remove(path) - listener, err := net.Listen("unix", path) + lc := &net.ListenConfig{} + listener, err := lc.Listen(context.Background(), "unix", path) if err != nil { return nil, err } diff --git a/util/cli/cli.go b/util/cli/cli.go index 91d48de06c..0d44bf3233 100644 --- a/util/cli/cli.go +++ b/util/cli/cli.go @@ -5,6 +5,7 @@ package cli import ( "bufio" "bytes" + "context" stderrors "errors" "flag" "fmt" @@ -275,7 +276,7 @@ func InteractiveEdit(filePattern string, data []byte, save func(input []byte) er for { data = setComments(data, errorComment) tempFile := writeToTempFile(filePattern, data) - cmd := exec.Command(editor, append(editorArgs, tempFile)...) + cmd := exec.CommandContext(context.Background(), editor, append(editorArgs, tempFile)...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin @@ -340,7 +341,7 @@ func PrintDiff(name string, live *unstructured.Unstructured, target *unstructure cmdBinary = parts[0] args = parts[1:] } - cmd := exec.Command(cmdBinary, append(args, liveFile, targetFile)...) + cmd := exec.CommandContext(context.Background(), cmdBinary, append(args, liveFile, targetFile)...) cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout return cmd.Run() diff --git a/util/cli/cli_test.go b/util/cli/cli_test.go index 450ce4825c..bc86097793 100644 --- a/util/cli/cli_test.go +++ b/util/cli/cli_test.go @@ -73,7 +73,7 @@ func TestSetLogFormat(t *testing.T) { SetLogFormat(tt.logFormat) return } - cmd := exec.Command(os.Args[0], "-test.run="+t.Name()) + cmd := exec.CommandContext(t.Context(), os.Args[0], "-test.run="+t.Name()) cmd.Env = append(os.Environ(), "TEST_FATAL=1") err := cmd.Run() e := &exec.ExitError{} diff --git a/util/config/reader.go b/util/config/reader.go index 35b33b9d8a..4aee9c3435 100644 --- a/util/config/reader.go +++ b/util/config/reader.go @@ -1,6 +1,7 @@ package config import ( + "context" "encoding/json" "io" "net/http" @@ -71,7 +72,11 @@ func UnmarshalRemoteFile(url string, obj any) error { // The caller is responsible for checking error return values. func ReadRemoteFile(url string) ([]byte, error) { var data []byte - resp, err := http.Get(url) + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, http.NoBody) + if err != nil { + return data, err + } + resp, err := http.DefaultClient.Do(req) if err == nil { defer func() { _ = resp.Body.Close() diff --git a/util/config/reader_test.go b/util/config/reader_test.go index 31e515bcc6..cf6af6c1df 100644 --- a/util/config/reader_test.go +++ b/util/config/reader_test.go @@ -69,10 +69,11 @@ func TestUnmarshalRemoteFile(t *testing.T) { field2 = 42 ) sentinel := fmt.Sprintf("---\nfield1: %q\nfield2: %d", field1, field2) + lc := &net.ListenConfig{} serve := func(c chan<- string) { // listen on first available dynamic (unprivileged) port - listener, err := net.Listen("tcp", ":0") + listener, err := lc.Listen(t.Context(), "tcp", ":0") if err != nil { panic(err) } diff --git a/util/dex/dex_test.go b/util/dex/dex_test.go index b55ce30070..a0bbfc7014 100644 --- a/util/dex/dex_test.go +++ b/util/dex/dex_test.go @@ -474,12 +474,15 @@ func Test_DexReverseProxy(t *testing.T) { fmt.Printf("Fake API Server listening on %s\n", server.URL) defer server.Close() target, _ := url.Parse(fakeDex.URL) - resp, err := http.Get(server.URL) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, server.URL, http.NoBody) + require.NoError(t, err) + resp, err := http.DefaultClient.Do(req) assert.NotNil(t, resp) require.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, host, target.Host) fmt.Printf("%s\n", resp.Status) + require.NoError(t, resp.Body.Close()) }) t.Run("Bad case", func(t *testing.T) { @@ -496,13 +499,16 @@ func Test_DexReverseProxy(t *testing.T) { return http.ErrUseLastResponse }, } - resp, err := client.Get(server.URL) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, server.URL, http.NoBody) + require.NoError(t, err) + resp, err := client.Do(req) assert.NotNil(t, resp) require.NoError(t, err) assert.Equal(t, http.StatusSeeOther, resp.StatusCode) location, _ := resp.Location() fmt.Printf("%s %s\n", resp.Status, location.RequestURI()) assert.True(t, strings.HasPrefix(location.RequestURI(), "/login?has_sso_error=true")) + assert.NoError(t, resp.Body.Close()) }) t.Run("Invalid URL for Dex reverse proxy", func(t *testing.T) { @@ -519,11 +525,12 @@ func Test_DexReverseProxy(t *testing.T) { defer server.Close() rt := NewDexRewriteURLRoundTripper(server.URL, http.DefaultTransport) assert.NotNil(t, rt) - req, err := http.NewRequest(http.MethodGet, "/", bytes.NewBuffer([]byte(""))) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "/", bytes.NewBuffer([]byte(""))) require.NoError(t, err) _, err = rt.RoundTrip(req) require.NoError(t, err) target, _ := url.Parse(server.URL) assert.Equal(t, req.Host, target.Host) + require.NoError(t, req.Body.Close()) }) } diff --git a/util/exec/exec.go b/util/exec/exec.go index 0df69aeba7..5d87a9aa05 100644 --- a/util/exec/exec.go +++ b/util/exec/exec.go @@ -2,6 +2,7 @@ package exec import ( "bytes" + "context" "errors" "fmt" "os" @@ -283,5 +284,5 @@ func RunCommandExt(cmd *exec.Cmd, opts CmdOpts) (string, error) { } func RunCommand(name string, opts CmdOpts, arg ...string) (string, error) { - return RunCommandExt(exec.Command(name, arg...), opts) + return RunCommandExt(exec.CommandContext(context.Background(), name, arg...), opts) } diff --git a/util/exec/exec_test.go b/util/exec/exec_test.go index d8113ce260..01b41c6829 100644 --- a/util/exec/exec_test.go +++ b/util/exec/exec_test.go @@ -29,19 +29,20 @@ func Test_timeout(t *testing.T) { } func TestRun(t *testing.T) { - out, err := Run(exec.Command("ls")) + out, err := Run(exec.CommandContext(t.Context(), "ls")) require.NoError(t, err) assert.NotEmpty(t, out) } func TestHideUsernamePassword(t *testing.T) { - _, err := RunWithRedactor(exec.Command("helm registry login https://charts.bitnami.com/bitnami", "--username", "foo", "--password", "bar"), nil) + ctx := t.Context() + _, err := RunWithRedactor(exec.CommandContext(ctx, "helm registry login https://charts.bitnami.com/bitnami", "--username", "foo", "--password", "bar"), nil) require.Error(t, err) redactor := func(text string) string { return regexp.MustCompile("(--username|--password) [^ ]*").ReplaceAllString(text, "$1 ******") } - _, err = RunWithRedactor(exec.Command("helm registry login https://charts.bitnami.com/bitnami", "--username", "foo", "--password", "bar"), redactor) + _, err = RunWithRedactor(exec.CommandContext(ctx, "helm registry login https://charts.bitnami.com/bitnami", "--username", "foo", "--password", "bar"), redactor) require.Error(t, err) } @@ -56,7 +57,7 @@ func TestRunWithExecRunOpts(t *testing.T) { ShouldWait: true, }, } - _, err := RunWithExecRunOpts(exec.Command("sh", "-c", "trap 'trap - 15 && echo captured && exit' 15 && sleep 2"), opts) + _, err := RunWithExecRunOpts(exec.CommandContext(t.Context(), "sh", "-c", "trap 'trap - 15 && echo captured && exit' 15 && sleep 2"), opts) assert.ErrorContains(t, err, "failed timeout after 200ms") } @@ -74,7 +75,7 @@ func TestRunWithExecRunOptsFatal(t *testing.T) { }, } // The returned error string in this case should contain a "fatal" in this case - _, err := RunWithExecRunOpts(exec.Command("sh", "-c", "trap 'trap - 15 && echo captured && sleep 10000' 15 && sleep 2"), opts) + _, err := RunWithExecRunOpts(exec.CommandContext(t.Context(), "sh", "-c", "trap 'trap - 15 && echo captured && sleep 10000' 15 && sleep 2"), opts) // The expected timeout is ARGOCD_EXEC_TIMEOUT + ARGOCD_EXEC_FATAL_TIMEOUT = 200ms + 100ms = 300ms assert.ErrorContains(t, err, "failed fatal timeout after 300ms") } @@ -108,7 +109,7 @@ func Test_getCommandArgsToLog(t *testing.T) { tcc := tc t.Run(tcc.name, func(t *testing.T) { t.Parallel() - assert.Equal(t, tcc.expected, GetCommandArgsToLog(exec.Command(tcc.args[0], tcc.args[1:]...))) + assert.Equal(t, tcc.expected, GetCommandArgsToLog(exec.CommandContext(t.Context(), tcc.args[0], tcc.args[1:]...))) }) } } @@ -195,7 +196,7 @@ func TestRunCommandErr(t *testing.T) { } func TestRunInDir(t *testing.T) { - cmd := exec.Command("pwd") + cmd := exec.CommandContext(t.Context(), "pwd") cmd.Dir = "/" message, err := RunCommandExt(cmd, CmdOpts{}) require.NoError(t, err) diff --git a/util/git/client.go b/util/git/client.go index 5a05c96d48..732e5dd444 100644 --- a/util/git/client.go +++ b/util/git/client.go @@ -2,6 +2,7 @@ package git import ( "bufio" + "context" "crypto/tls" "encoding/json" "errors" @@ -414,12 +415,12 @@ func (m *nativeGitClient) IsLFSEnabled() bool { return m.enableLfs } -func (m *nativeGitClient) fetch(revision string) error { +func (m *nativeGitClient) fetch(ctx context.Context, revision string) error { var err error if revision != "" { - err = m.runCredentialedCmd("fetch", "origin", revision, "--tags", "--force", "--prune") + err = m.runCredentialedCmd(ctx, "fetch", "origin", revision, "--tags", "--force", "--prune") } else { - err = m.runCredentialedCmd("fetch", "origin", "--tags", "--force", "--prune") + err = m.runCredentialedCmd(ctx, "fetch", "origin", "--tags", "--force", "--prune") } return err } @@ -430,7 +431,7 @@ func (m *nativeGitClient) IsRevisionPresent(revision string) bool { return false } - cmd := exec.Command("git", "cat-file", "-t", revision) + cmd := exec.CommandContext(context.Background(), "git", "cat-file", "-t", revision) out, err := m.runCmdOutput(cmd, runOpts{SkipErrorLogging: true}) if out == "commit" && err == nil { return true @@ -444,14 +445,15 @@ func (m *nativeGitClient) Fetch(revision string) error { done := m.OnFetch(m.repoURL) defer done() } + ctx := context.Background() - err := m.fetch(revision) + err := m.fetch(ctx, revision) // When we have LFS support enabled, check for large files and fetch them too. if err == nil && m.IsLFSEnabled() { largeFiles, err := m.LsLargeFiles() if err == nil && len(largeFiles) > 0 { - err = m.runCredentialedCmd("lfs", "fetch", "--all") + err = m.runCredentialedCmd(ctx, "lfs", "fetch", "--all") if err != nil { return err } @@ -500,8 +502,9 @@ func (m *nativeGitClient) LsFiles(path string, enableNewGitFileGlobbing bool) ([ } return files, nil } + ctx := context.Background() // This is the old and default way - out, err := m.runCmd("ls-files", "--full-name", "-z", "--", path) + out, err := m.runCmd(ctx, "ls-files", "--full-name", "-z", "--", path) if err != nil { return nil, err } @@ -512,7 +515,7 @@ func (m *nativeGitClient) LsFiles(path string, enableNewGitFileGlobbing bool) ([ // LsLargeFiles lists all files that have references to LFS storage func (m *nativeGitClient) LsLargeFiles() ([]string, error) { - out, err := m.runCmd("lfs", "ls-files", "-n") + out, err := m.runCmd(context.Background(), "lfs", "ls-files", "-n") if err != nil { return nil, err } @@ -522,10 +525,11 @@ func (m *nativeGitClient) LsLargeFiles() ([]string, error) { // Submodule embed other repositories into this repository func (m *nativeGitClient) Submodule() error { - if err := m.runCredentialedCmd("submodule", "sync", "--recursive"); err != nil { + ctx := context.Background() + if err := m.runCredentialedCmd(ctx, "submodule", "sync", "--recursive"); err != nil { return err } - return m.runCredentialedCmd("submodule", "update", "--init", "--recursive") + return m.runCredentialedCmd(ctx, "submodule", "update", "--init", "--recursive") } // Checkout checks out the specified revision @@ -533,7 +537,8 @@ func (m *nativeGitClient) Checkout(revision string, submoduleEnabled bool) (stri if revision == "" || revision == "HEAD" { revision = "origin/HEAD" } - if out, err := m.runCmd("checkout", "--force", revision); err != nil { + ctx := context.Background() + if out, err := m.runCmd(ctx, "checkout", "--force", revision); err != nil { return out, fmt.Errorf("failed to checkout %s: %w", revision, err) } // We must populate LFS content by using lfs checkout, if we have at least @@ -544,7 +549,7 @@ func (m *nativeGitClient) Checkout(revision string, submoduleEnabled bool) (stri return "", fmt.Errorf("failed to list LFS files: %w", err) } if len(largeFiles) > 0 { - if out, err := m.runCmd("lfs", "checkout"); err != nil { + if out, err := m.runCmd(ctx, "lfs", "checkout"); err != nil { return out, fmt.Errorf("failed to checkout LFS files: %w", err) } } @@ -561,7 +566,7 @@ func (m *nativeGitClient) Checkout(revision string, submoduleEnabled bool) (stri // `git clean` to delete untracked files and directories, and the second “f” // tells it to clean untracked nested Git repositories (for example a // submodule which has since been removed). - if out, err := m.runCmd("clean", "-ffdx"); err != nil { + if out, err := m.runCmd(ctx, "clean", "-ffdx"); err != nil { return out, fmt.Errorf("failed to clean: %w", err) } return "", nil @@ -763,7 +768,7 @@ func (m *nativeGitClient) lsRemote(revision string) (string, error) { // CommitSHA returns current commit sha from `git rev-parse HEAD` func (m *nativeGitClient) CommitSHA() (string, error) { - out, err := m.runCmd("rev-parse", "HEAD") + out, err := m.runCmd(context.Background(), "rev-parse", "HEAD") if err != nil { return "", err } @@ -772,7 +777,8 @@ func (m *nativeGitClient) CommitSHA() (string, error) { // RevisionMetadata returns the meta-data for the commit func (m *nativeGitClient) RevisionMetadata(revision string) (*RevisionMetadata, error) { - out, err := m.runCmd("show", "-s", "--format=%an <%ae>%n%at%n%B", revision) + ctx := context.Background() + out, err := m.runCmd(ctx, "show", "-s", "--format=%an <%ae>%n%at%n%B", revision) if err != nil { return nil, err } @@ -784,7 +790,7 @@ func (m *nativeGitClient) RevisionMetadata(revision string) (*RevisionMetadata, authorDateUnixTimestamp, _ := strconv.ParseInt(segments[1], 10, 64) message := strings.TrimSpace(segments[2]) - cmd := exec.Command("git", "interpret-trailers", "--parse") + cmd := exec.CommandContext(ctx, "git", "interpret-trailers", "--parse") cmd.Stdin = strings.NewReader(message) out, err = m.runCmdOutput(cmd, runOpts{}) if err != nil { @@ -792,7 +798,7 @@ func (m *nativeGitClient) RevisionMetadata(revision string) (*RevisionMetadata, } relatedCommits, _ := GetReferences(log.WithFields(log.Fields{"repo": m.repoURL, "revision": revision}), out) - out, err = m.runCmd("tag", "--points-at", revision) + out, err = m.runCmd(ctx, "tag", "--points-at", revision) if err != nil { return nil, err } @@ -903,7 +909,7 @@ func updateCommitMetadata(logCtx *log.Entry, relatedCommit *CommitMetadata, line // VerifyCommitSignature Runs verify-commit on a given revision and returns the output func (m *nativeGitClient) VerifyCommitSignature(revision string) (string, error) { - out, err := m.runGnuPGWrapper("git-verify-wrapper.sh", revision) + out, err := m.runGnuPGWrapper(context.Background(), "git-verify-wrapper.sh", revision) if err != nil { log.Errorf("error verifying commit signature: %v", err) return "", errors.New("permission denied") @@ -913,7 +919,7 @@ func (m *nativeGitClient) VerifyCommitSignature(revision string) (string, error) // IsAnnotatedTag returns true if the revision points to an annotated tag func (m *nativeGitClient) IsAnnotatedTag(revision string) bool { - cmd := exec.Command("git", "describe", "--exact-match", revision) + cmd := exec.CommandContext(context.Background(), "git", "describe", "--exact-match", revision) out, err := m.runCmdOutput(cmd, runOpts{SkipErrorLogging: true}) if out != "" && err == nil { return true @@ -931,7 +937,7 @@ func (m *nativeGitClient) ChangedFiles(revision string, targetRevision string) ( return []string{}, errors.New("invalid revision provided, must be SHA") } - out, err := m.runCmd("diff", "--name-only", fmt.Sprintf("%s..%s", revision, targetRevision)) + out, err := m.runCmd(context.Background(), "diff", "--name-only", fmt.Sprintf("%s..%s", revision, targetRevision)) if err != nil { return nil, fmt.Errorf("failed to diff %s..%s: %w", revision, targetRevision, err) } @@ -945,9 +951,9 @@ func (m *nativeGitClient) ChangedFiles(revision string, targetRevision string) ( } // config runs a git config command. -func (m *nativeGitClient) config(args ...string) (string, error) { +func (m *nativeGitClient) config(ctx context.Context, args ...string) (string, error) { args = append([]string{"config"}, args...) - out, err := m.runCmd(args...) + out, err := m.runCmd(ctx, args...) if err != nil { return out, fmt.Errorf("failed to run git config: %w", err) } @@ -956,14 +962,15 @@ func (m *nativeGitClient) config(args ...string) (string, error) { // SetAuthor sets the author name and email in the git configuration. func (m *nativeGitClient) SetAuthor(name, email string) (string, error) { + ctx := context.Background() if name != "" { - out, err := m.config("--local", "user.name", name) + out, err := m.config(ctx, "--local", "user.name", name) if err != nil { return out, err } } if email != "" { - out, err := m.config("--local", "user.email", email) + out, err := m.config(ctx, "--local", "user.email", email) if err != nil { return out, err } @@ -979,19 +986,20 @@ func (m *nativeGitClient) CheckoutOrOrphan(branch string, submoduleEnabled bool) if !strings.Contains(err.Error(), "did not match any file(s) known to git") { return out, fmt.Errorf("failed to checkout branch: %w", err) } - out, err = m.runCmd("switch", "--orphan", branch) + ctx := context.Background() + out, err = m.runCmd(ctx, "switch", "--orphan", branch) if err != nil { return out, fmt.Errorf("failed to create orphan branch: %w", err) } // Make an empty initial commit. - out, err = m.runCmd("commit", "--allow-empty", "-m", "Initial commit") + out, err = m.runCmd(ctx, "commit", "--allow-empty", "-m", "Initial commit") if err != nil { return out, fmt.Errorf("failed to commit initial commit: %w", err) } // Push the commit. - err = m.runCredentialedCmd("push", "origin", branch) + err = m.runCredentialedCmd(ctx, "push", "origin", branch) if err != nil { return "", fmt.Errorf("failed to push to branch: %w", err) } @@ -1014,7 +1022,7 @@ func (m *nativeGitClient) CheckoutOrNew(branch, base string, submoduleEnabled bo return out, fmt.Errorf("failed to checkout sync branch: %w", err) } - out, err = m.runCmd("checkout", "-b", branch) + out, err = m.runCmd(context.Background(), "checkout", "-b", branch) if err != nil { return out, fmt.Errorf("failed to create branch: %w", err) } @@ -1028,7 +1036,7 @@ func (m *nativeGitClient) RemoveContents(paths []string) (string, error) { return "", nil } args := append([]string{"rm", "-r", "--ignore-unmatch", "--"}, paths...) - out, err := m.runCmd(args...) + out, err := m.runCmd(context.Background(), args...) if err != nil { return out, fmt.Errorf("failed to clear paths %v: %w", paths, err) } @@ -1037,12 +1045,13 @@ func (m *nativeGitClient) RemoveContents(paths []string) (string, error) { // CommitAndPush commits and pushes changes to the target branch. func (m *nativeGitClient) CommitAndPush(branch, message string) (string, error) { - out, err := m.runCmd("add", ".") + ctx := context.Background() + out, err := m.runCmd(ctx, "add", ".") if err != nil { return out, fmt.Errorf("failed to add files: %w", err) } - out, err = m.runCmd("commit", "-m", message) + out, err = m.runCmd(ctx, "commit", "-m", message) if err != nil { if strings.Contains(out, "nothing to commit, working tree clean") { return out, nil @@ -1055,7 +1064,7 @@ func (m *nativeGitClient) CommitAndPush(branch, message string) (string, error) defer done() } - err = m.runCredentialedCmd("push", "origin", branch) + err = m.runCredentialedCmd(ctx, "push", "origin", branch) if err != nil { return "", fmt.Errorf("failed to push: %w", err) } @@ -1064,20 +1073,20 @@ func (m *nativeGitClient) CommitAndPush(branch, message string) (string, error) } // runWrapper runs a custom command with all the semantics of running the Git client -func (m *nativeGitClient) runGnuPGWrapper(wrapper string, args ...string) (string, error) { - cmd := exec.Command(wrapper, args...) +func (m *nativeGitClient) runGnuPGWrapper(ctx context.Context, wrapper string, args ...string) (string, error) { + cmd := exec.CommandContext(ctx, wrapper, args...) cmd.Env = append(cmd.Env, "GNUPGHOME="+common.GetGnuPGHomePath(), "LANG=C") return m.runCmdOutput(cmd, runOpts{}) } // runCmd is a convenience function to run a command in a given directory and return its output -func (m *nativeGitClient) runCmd(args ...string) (string, error) { - cmd := exec.Command("git", args...) +func (m *nativeGitClient) runCmd(ctx context.Context, args ...string) (string, error) { + cmd := exec.CommandContext(ctx, "git", args...) return m.runCmdOutput(cmd, runOpts{}) } // runCredentialedCmd is a convenience function to run a git command with username/password credentials -func (m *nativeGitClient) runCredentialedCmd(args ...string) error { +func (m *nativeGitClient) runCredentialedCmd(ctx context.Context, args ...string) error { closer, environ, err := m.creds.Environ() if err != nil { return err @@ -1094,7 +1103,7 @@ func (m *nativeGitClient) runCredentialedCmd(args ...string) error { } } - cmd := exec.Command("git", args...) + cmd := exec.CommandContext(ctx, "git", args...) cmd.Env = append(cmd.Env, environ...) _, err = m.runCmdOutput(cmd, runOpts{}) return err diff --git a/util/git/client_test.go b/util/git/client_test.go index 6497b4bfd2..659c956538 100644 --- a/util/git/client_test.go +++ b/util/git/client_test.go @@ -27,38 +27,38 @@ import ( "github.com/argoproj/argo-cd/v3/util/workloadidentity/mocks" ) -func runCmd(workingDir string, name string, args ...string) error { - cmd := exec.Command(name, args...) +func runCmd(ctx context.Context, workingDir string, name string, args ...string) error { + cmd := exec.CommandContext(ctx, name, args...) cmd.Dir = workingDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } -func outputCmd(workingDir string, name string, args ...string) ([]byte, error) { - cmd := exec.Command(name, args...) +func outputCmd(ctx context.Context, workingDir string, name string, args ...string) ([]byte, error) { + cmd := exec.CommandContext(ctx, name, args...) cmd.Dir = workingDir cmd.Stderr = os.Stderr return cmd.Output() } -func _createEmptyGitRepo() (string, error) { +func _createEmptyGitRepo(ctx context.Context) (string, error) { tempDir, err := os.MkdirTemp("", "") if err != nil { return tempDir, err } - err = runCmd(tempDir, "git", "init") + err = runCmd(ctx, tempDir, "git", "init") if err != nil { return tempDir, err } - err = runCmd(tempDir, "git", "commit", "-m", "Initial commit", "--allow-empty") + err = runCmd(ctx, tempDir, "git", "commit", "-m", "Initial commit", "--allow-empty") return tempDir, err } func Test_nativeGitClient_Fetch(t *testing.T) { - tempDir, err := _createEmptyGitRepo() + tempDir, err := _createEmptyGitRepo(t.Context()) require.NoError(t, err) client, err := NewClient("file://"+tempDir, NopCreds{}, true, false, "", "") @@ -72,7 +72,8 @@ func Test_nativeGitClient_Fetch(t *testing.T) { } func Test_nativeGitClient_Fetch_Prune(t *testing.T) { - tempDir, err := _createEmptyGitRepo() + ctx := t.Context() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) client, err := NewClient("file://"+tempDir, NopCreds{}, true, false, "", "") @@ -81,15 +82,15 @@ func Test_nativeGitClient_Fetch_Prune(t *testing.T) { err = client.Init() require.NoError(t, err) - err = runCmd(tempDir, "git", "branch", "test/foo") + err = runCmd(ctx, tempDir, "git", "branch", "test/foo") require.NoError(t, err) err = client.Fetch("") require.NoError(t, err) - err = runCmd(tempDir, "git", "branch", "-d", "test/foo") + err = runCmd(ctx, tempDir, "git", "branch", "-d", "test/foo") require.NoError(t, err) - err = runCmd(tempDir, "git", "branch", "test/foo/bar") + err = runCmd(ctx, tempDir, "git", "branch", "test/foo/bar") require.NoError(t, err) err = client.Fetch("") @@ -98,6 +99,7 @@ func Test_nativeGitClient_Fetch_Prune(t *testing.T) { func Test_IsAnnotatedTag(t *testing.T) { tempDir := t.TempDir() + ctx := t.Context() client, err := NewClient("file://"+tempDir, NopCreds{}, true, false, "", "") require.NoError(t, err) @@ -112,16 +114,16 @@ func Test_IsAnnotatedTag(t *testing.T) { err = f.Close() require.NoError(t, err) - err = runCmd(client.Root(), "git", "add", "README") + err = runCmd(ctx, client.Root(), "git", "add", "README") require.NoError(t, err) - err = runCmd(client.Root(), "git", "commit", "-m", "Initial commit", "-a") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", "Initial commit", "-a") require.NoError(t, err) atag := client.IsAnnotatedTag("master") assert.False(t, atag) - err = runCmd(client.Root(), "git", "tag", "some-tag", "-a", "-m", "Create annotated tag") + err = runCmd(ctx, client.Root(), "git", "tag", "some-tag", "-a", "-m", "Create annotated tag") require.NoError(t, err) atag = client.IsAnnotatedTag("some-tag") assert.True(t, atag) @@ -130,9 +132,9 @@ func Test_IsAnnotatedTag(t *testing.T) { atag = client.IsAnnotatedTag("HEAD") assert.True(t, atag) - err = runCmd(client.Root(), "git", "rm", "README") + err = runCmd(ctx, client.Root(), "git", "rm", "README") require.NoError(t, err) - err = runCmd(client.Root(), "git", "commit", "-m", "remove README", "-a") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", "remove README", "-a") require.NoError(t, err) // We moved on, so tag doesn't point to HEAD anymore @@ -155,6 +157,7 @@ func Test_resolveTagReference(t *testing.T) { func Test_ChangedFiles(t *testing.T) { tempDir := t.TempDir() + ctx := t.Context() client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "") require.NoError(t, err) @@ -162,11 +165,11 @@ func Test_ChangedFiles(t *testing.T) { err = client.Init() require.NoError(t, err) - err = runCmd(client.Root(), "git", "commit", "-m", "Initial commit", "--allow-empty") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", "Initial commit", "--allow-empty") require.NoError(t, err) // Create a tag to have a second ref - err = runCmd(client.Root(), "git", "tag", "some-tag") + err = runCmd(ctx, client.Root(), "git", "tag", "some-tag") require.NoError(t, err) p := path.Join(client.Root(), "README") @@ -177,10 +180,10 @@ func Test_ChangedFiles(t *testing.T) { err = f.Close() require.NoError(t, err) - err = runCmd(client.Root(), "git", "add", "README") + err = runCmd(ctx, client.Root(), "git", "add", "README") require.NoError(t, err) - err = runCmd(client.Root(), "git", "commit", "-m", "Changes", "-a") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", "Changes", "-a") require.NoError(t, err) previousSHA, err := client.LsRemote("some-tag") @@ -210,6 +213,7 @@ func Test_ChangedFiles(t *testing.T) { func Test_SemverTags(t *testing.T) { tempDir := t.TempDir() + ctx := t.Context() client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "") require.NoError(t, err) @@ -228,11 +232,11 @@ func Test_SemverTags(t *testing.T) { "2024-apple", "2024-banana", } { - err = runCmd(client.Root(), "git", "commit", "-m", tag+" commit", "--allow-empty") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", tag+" commit", "--allow-empty") require.NoError(t, err) // Create an rc semver tag - err = runCmd(client.Root(), "git", "tag", tag) + err = runCmd(ctx, client.Root(), "git", "tag", tag) require.NoError(t, err) sha, err := client.LsRemote("HEAD") @@ -353,37 +357,38 @@ func Test_SemverTags(t *testing.T) { func Test_nativeGitClient_Submodule(t *testing.T) { tempDir, err := os.MkdirTemp("", "") require.NoError(t, err) + ctx := t.Context() foo := filepath.Join(tempDir, "foo") err = os.Mkdir(foo, 0o755) require.NoError(t, err) - err = runCmd(foo, "git", "init") + err = runCmd(ctx, foo, "git", "init") require.NoError(t, err) bar := filepath.Join(tempDir, "bar") err = os.Mkdir(bar, 0o755) require.NoError(t, err) - err = runCmd(bar, "git", "init") + err = runCmd(ctx, bar, "git", "init") require.NoError(t, err) - err = runCmd(bar, "git", "commit", "-m", "Initial commit", "--allow-empty") + err = runCmd(ctx, bar, "git", "commit", "-m", "Initial commit", "--allow-empty") require.NoError(t, err) // Embed repository bar into repository foo t.Setenv("GIT_ALLOW_PROTOCOL", "file") - err = runCmd(foo, "git", "submodule", "add", bar) + err = runCmd(ctx, foo, "git", "submodule", "add", bar) require.NoError(t, err) - err = runCmd(foo, "git", "commit", "-m", "Initial commit") + err = runCmd(ctx, foo, "git", "commit", "-m", "Initial commit") require.NoError(t, err) tempDir, err = os.MkdirTemp("", "") require.NoError(t, err) // Clone foo - err = runCmd(tempDir, "git", "clone", foo) + err = runCmd(ctx, tempDir, "git", "clone", foo) require.NoError(t, err) client, err := NewClient("file://"+foo, NopCreds{}, true, false, "", "") @@ -403,7 +408,7 @@ func Test_nativeGitClient_Submodule(t *testing.T) { require.NoError(t, err) // Check if submodule url does not exist in .git/config - err = runCmd(client.Root(), "git", "config", "submodule.bar.url") + err = runCmd(ctx, client.Root(), "git", "config", "submodule.bar.url") require.Error(t, err) // Call Submodule() via Checkout() with submoduleEnabled=true. @@ -411,14 +416,14 @@ func Test_nativeGitClient_Submodule(t *testing.T) { require.NoError(t, err) // Check if the .gitmodule URL is reflected in .git/config - cmd := exec.Command("git", "config", "submodule.bar.url") + cmd := exec.CommandContext(ctx, "git", "config", "submodule.bar.url") cmd.Dir = client.Root() result, err := cmd.Output() require.NoError(t, err) assert.Equal(t, bar+"\n", string(result)) // Change URL of submodule bar - err = runCmd(client.Root(), "git", "config", "--file=.gitmodules", "submodule.bar.url", bar+"baz") + err = runCmd(ctx, client.Root(), "git", "config", "--file=.gitmodules", "submodule.bar.url", bar+"baz") require.NoError(t, err) // Call Submodule() @@ -426,7 +431,7 @@ func Test_nativeGitClient_Submodule(t *testing.T) { require.NoError(t, err) // Check if the URL change in .gitmodule is reflected in .git/config - cmd = exec.Command("git", "config", "submodule.bar.url") + cmd = exec.CommandContext(ctx, "git", "config", "submodule.bar.url") cmd.Dir = client.Root() result, err = cmd.Output() require.NoError(t, err) @@ -441,6 +446,7 @@ func TestNewClient_invalidSSHURL(t *testing.T) { func Test_IsRevisionPresent(t *testing.T) { tempDir := t.TempDir() + ctx := t.Context() client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "") require.NoError(t, err) @@ -456,10 +462,10 @@ func Test_IsRevisionPresent(t *testing.T) { err = f.Close() require.NoError(t, err) - err = runCmd(client.Root(), "git", "add", "README") + err = runCmd(ctx, client.Root(), "git", "add", "README") require.NoError(t, err) - err = runCmd(client.Root(), "git", "commit", "-m", "Initial Commit", "-a") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", "Initial Commit", "-a") require.NoError(t, err) commitSHA, err := client.LsRemote("HEAD") @@ -490,15 +496,17 @@ func Test_nativeGitClient_RevisionMetadata(t *testing.T) { err = f.Close() require.NoError(t, err) - err = runCmd(client.Root(), "git", "config", "user.name", "FooBar ||| something\nelse") + ctx := t.Context() + + err = runCmd(ctx, client.Root(), "git", "config", "user.name", "FooBar ||| something\nelse") require.NoError(t, err) - err = runCmd(client.Root(), "git", "config", "user.email", "foo@foo.com") + err = runCmd(ctx, client.Root(), "git", "config", "user.email", "foo@foo.com") require.NoError(t, err) - err = runCmd(client.Root(), "git", "add", "README") + err = runCmd(ctx, client.Root(), "git", "add", "README") require.NoError(t, err) now := time.Now() - err = runCmd(client.Root(), "git", "commit", "--date=\"Sat Jun 5 20:00:00 2021 +0000 UTC\"", "-m", `| Initial commit | + err = runCmd(ctx, client.Root(), "git", "commit", "--date=\"Sat Jun 5 20:00:00 2021 +0000 UTC\"", "-m", `| Initial commit | (╯°□°)╯︵ ┻━┻ @@ -546,8 +554,9 @@ Argocd-reference-commit-repourl: https://git.example.com/test/repo.git`, now.For func Test_nativeGitClient_SetAuthor(t *testing.T) { expectedName := "Tester" expectedEmail := "test@example.com" + ctx := t.Context() - tempDir, err := _createEmptyGitRepo() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) client, err := NewClient("file://"+tempDir, NopCreds{}, true, false, "", "") @@ -560,13 +569,13 @@ func Test_nativeGitClient_SetAuthor(t *testing.T) { require.NoError(t, err, "error output: ", out) // Check git user.name - gitUserName, err := outputCmd(client.Root(), "git", "config", "--local", "user.name") + gitUserName, err := outputCmd(ctx, client.Root(), "git", "config", "--local", "user.name") require.NoError(t, err) actualName := strings.TrimSpace(string(gitUserName)) require.Equal(t, expectedName, actualName) // Check git user.email - gitUserEmail, err := outputCmd(client.Root(), "git", "config", "--local", "user.email") + gitUserEmail, err := outputCmd(ctx, client.Root(), "git", "config", "--local", "user.email") require.NoError(t, err) actualEmail := strings.TrimSpace(string(gitUserEmail)) require.Equal(t, expectedEmail, actualEmail) @@ -576,8 +585,9 @@ func Test_nativeGitClient_CheckoutOrOrphan(t *testing.T) { t.Run("checkout to an existing branch", func(t *testing.T) { // not main or master expectedBranch := "feature" + ctx := t.Context() - tempDir, err := _createEmptyGitRepo() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "") @@ -591,35 +601,35 @@ func Test_nativeGitClient_CheckoutOrOrphan(t *testing.T) { require.NoError(t, err, "error output: %s", out) // get base branch - gitCurrentBranch, err := outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err := outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) baseBranch := strings.TrimSpace(string(gitCurrentBranch)) // get base commit - gitCurrentCommitHash, err := outputCmd(tempDir, "git", "rev-parse", "HEAD") + gitCurrentCommitHash, err := outputCmd(ctx, tempDir, "git", "rev-parse", "HEAD") require.NoError(t, err) expectedCommitHash := strings.TrimSpace(string(gitCurrentCommitHash)) // make expected branch - err = runCmd(tempDir, "git", "checkout", "-b", expectedBranch) + err = runCmd(ctx, tempDir, "git", "checkout", "-b", expectedBranch) require.NoError(t, err) // checkout to base branch, ready to test - err = runCmd(tempDir, "git", "checkout", baseBranch) + err = runCmd(ctx, tempDir, "git", "checkout", baseBranch) require.NoError(t, err) out, err = client.CheckoutOrOrphan(expectedBranch, false) require.NoError(t, err, "error output: ", out) // get current branch, verify current branch - gitCurrentBranch, err = outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err = outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) actualBranch := strings.TrimSpace(string(gitCurrentBranch)) require.Equal(t, expectedBranch, actualBranch) // get current commit hash, verify current commit hash // equal -> not orphan - gitCurrentCommitHash, err = outputCmd(tempDir, "git", "rev-parse", "HEAD") + gitCurrentCommitHash, err = outputCmd(ctx, tempDir, "git", "rev-parse", "HEAD") require.NoError(t, err) actualCommitHash := strings.TrimSpace(string(gitCurrentCommitHash)) require.Equal(t, expectedCommitHash, actualCommitHash) @@ -628,16 +638,17 @@ func Test_nativeGitClient_CheckoutOrOrphan(t *testing.T) { t.Run("orphan", func(t *testing.T) { // not main or master expectedBranch := "feature" + ctx := t.Context() // make origin git repository - tempDir, err := _createEmptyGitRepo() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) originGitRepoURL := "file://" + tempDir - err = runCmd(tempDir, "git", "commit", "-m", "Second commit", "--allow-empty") + err = runCmd(ctx, tempDir, "git", "commit", "-m", "Second commit", "--allow-empty") require.NoError(t, err) // get base branch - gitCurrentBranch, err := outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err := outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) baseBranch := strings.TrimSpace(string(gitCurrentBranch)) @@ -659,11 +670,11 @@ func Test_nativeGitClient_CheckoutOrOrphan(t *testing.T) { require.NoError(t, err) // checkout to origin base branch - err = runCmd(tempDir, "git", "checkout", baseBranch) + err = runCmd(ctx, tempDir, "git", "checkout", baseBranch) require.NoError(t, err) // get base commit - gitCurrentCommitHash, err := outputCmd(tempDir, "git", "rev-parse", "HEAD") + gitCurrentCommitHash, err := outputCmd(ctx, tempDir, "git", "rev-parse", "HEAD") require.NoError(t, err) baseCommitHash := strings.TrimSpace(string(gitCurrentCommitHash)) @@ -671,7 +682,7 @@ func Test_nativeGitClient_CheckoutOrOrphan(t *testing.T) { require.NoError(t, err, "error output: ", out) // get current branch, verify current branch - gitCurrentBranch, err = outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err = outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) actualBranch := strings.TrimSpace(string(gitCurrentBranch)) require.Equal(t, expectedBranch, actualBranch) @@ -680,13 +691,13 @@ func Test_nativeGitClient_CheckoutOrOrphan(t *testing.T) { // get current commit hash, verify current commit hash // not equal -> orphan - gitCurrentCommitHash, err = outputCmd(tempDir, "git", "rev-parse", "HEAD") + gitCurrentCommitHash, err = outputCmd(ctx, tempDir, "git", "rev-parse", "HEAD") require.NoError(t, err) currentCommitHash := strings.TrimSpace(string(gitCurrentCommitHash)) require.NotEqual(t, baseCommitHash, currentCommitHash) // get commit count on current branch, verify 1 -> orphan - gitCommitCount, err := outputCmd(tempDir, "git", "rev-list", "--count", actualBranch) + gitCommitCount, err := outputCmd(ctx, tempDir, "git", "rev-list", "--count", actualBranch) require.NoError(t, err) require.Equal(t, "1", strings.TrimSpace(string(gitCommitCount))) }) @@ -705,8 +716,9 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { // not main or master expectedBranch := "feature" + ctx := t.Context() - tempDir, err := _createEmptyGitRepo() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "") @@ -719,16 +731,16 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { require.NoError(t, err, "error output: %s", out) // get base branch - gitCurrentBranch, err := outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err := outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) baseBranch := strings.TrimSpace(string(gitCurrentBranch)) // make expected branch - err = runCmd(tempDir, "git", "checkout", "-b", expectedBranch) + err = runCmd(ctx, tempDir, "git", "checkout", "-b", expectedBranch) require.NoError(t, err) // make expected commit - err = runCmd(tempDir, "git", "commit", "-m", "Second commit", "--allow-empty") + err = runCmd(ctx, tempDir, "git", "commit", "-m", "Second commit", "--allow-empty") require.NoError(t, err) // get expected commit @@ -736,14 +748,14 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { require.NoError(t, err) // checkout to base branch, ready to test - err = runCmd(tempDir, "git", "checkout", baseBranch) + err = runCmd(ctx, tempDir, "git", "checkout", baseBranch) require.NoError(t, err) out, err = client.CheckoutOrNew(expectedBranch, baseBranch, false) require.NoError(t, err, "error output: ", out) // get current branch, verify current branch - gitCurrentBranch, err = outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err = outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) actualBranch := strings.TrimSpace(string(gitCurrentBranch)) require.Equal(t, expectedBranch, actualBranch) @@ -764,8 +776,9 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { // not main or master expectedBranch := "feature" + ctx := t.Context() - tempDir, err := _createEmptyGitRepo() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "") @@ -778,7 +791,7 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { require.NoError(t, err, "error output: %s", out) // get base branch - gitCurrentBranch, err := outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err := outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) baseBranch := strings.TrimSpace(string(gitCurrentBranch)) @@ -790,7 +803,7 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { require.NoError(t, err, "error output: ", out) // get current branch, verify current branch - gitCurrentBranch, err = outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err = outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) actualBranch := strings.TrimSpace(string(gitCurrentBranch)) require.Equal(t, expectedBranch, actualBranch) @@ -804,7 +817,8 @@ func Test_nativeGitClient_CheckoutOrNew(t *testing.T) { func Test_nativeGitClient_RemoveContents_SpecificPath(t *testing.T) { // given - tempDir, err := _createEmptyGitRepo() + ctx := t.Context() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) client, err := NewClient("file://"+tempDir, NopCreds{}, true, false, "", "") @@ -816,17 +830,17 @@ func Test_nativeGitClient_RemoveContents_SpecificPath(t *testing.T) { _, err = client.SetAuthor("test", "test@example.com") require.NoError(t, err) - err = runCmd(client.Root(), "touch", "README.md") + err = runCmd(ctx, client.Root(), "touch", "README.md") require.NoError(t, err) - err = runCmd(client.Root(), "mkdir", "scripts") + err = runCmd(ctx, client.Root(), "mkdir", "scripts") require.NoError(t, err) - err = runCmd(client.Root(), "touch", "scripts/startup.sh") + err = runCmd(ctx, client.Root(), "touch", "scripts/startup.sh") require.NoError(t, err) - err = runCmd(client.Root(), "git", "add", "--all") + err = runCmd(ctx, client.Root(), "git", "add", "--all") require.NoError(t, err) - err = runCmd(client.Root(), "git", "commit", "-m", "Make files") + err = runCmd(ctx, client.Root(), "git", "commit", "-m", "Make files") require.NoError(t, err) // when: remove only "scripts" directory @@ -841,22 +855,23 @@ func Test_nativeGitClient_RemoveContents_SpecificPath(t *testing.T) { require.Error(t, err, "scripts directory should be removed") // and: listing should only show README.md - ls, err := outputCmd(client.Root(), "ls") + ls, err := outputCmd(ctx, client.Root(), "ls") require.NoError(t, err) require.Equal(t, "README.md", strings.TrimSpace(string(ls))) } func Test_nativeGitClient_CommitAndPush(t *testing.T) { - tempDir, err := _createEmptyGitRepo() + ctx := t.Context() + tempDir, err := _createEmptyGitRepo(ctx) require.NoError(t, err) // config receive.denyCurrentBranch updateInstead // because local git init make a non-bare repository which cannot be pushed normally - err = runCmd(tempDir, "git", "config", "--local", "receive.denyCurrentBranch", "updateInstead") + err = runCmd(ctx, tempDir, "git", "config", "--local", "receive.denyCurrentBranch", "updateInstead") require.NoError(t, err) // get branch - gitCurrentBranch, err := outputCmd(tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") + gitCurrentBranch, err := outputCmd(ctx, tempDir, "git", "rev-parse", "--abbrev-ref", "HEAD") require.NoError(t, err) branch := strings.TrimSpace(string(gitCurrentBranch)) @@ -876,7 +891,7 @@ func Test_nativeGitClient_CommitAndPush(t *testing.T) { require.NoError(t, err, "error output: ", out) // make a file then commit and push - err = runCmd(client.Root(), "touch", "README.md") + err = runCmd(ctx, client.Root(), "touch", "README.md") require.NoError(t, err) out, err = client.CommitAndPush(branch, "docs: README") @@ -887,7 +902,7 @@ func Test_nativeGitClient_CommitAndPush(t *testing.T) { require.NoError(t, err) // get origin repository's current commit hash - gitCurrentCommitHash, err := outputCmd(tempDir, "git", "rev-parse", "HEAD") + gitCurrentCommitHash, err := outputCmd(ctx, tempDir, "git", "rev-parse", "HEAD") require.NoError(t, err) actualCommitHash := strings.TrimSpace(string(gitCurrentCommitHash)) require.Equal(t, expectedCommitHash, actualCommitHash) @@ -1007,8 +1022,9 @@ func Test_nativeGitClient_runCredentialedCmd(t *testing.T) { client := &nativeGitClient{ creds: tt.creds, } + ctx := t.Context() - err := client.runCredentialedCmd("status") + err := client.runCredentialedCmd(ctx, "status") if (err != nil) != tt.expectedErr { t.Errorf("runCredentialedCmd() error = %v, expectedErr %v", err, tt.expectedErr) return @@ -1018,7 +1034,7 @@ func Test_nativeGitClient_runCredentialedCmd(t *testing.T) { return } - cmd := exec.Command("git", tt.expectedArgs...) + cmd := exec.CommandContext(ctx, "git", tt.expectedArgs...) cmd.Env = append(os.Environ(), tt.expectedEnv...) output, err := cmd.CombinedOutput() if err != nil { @@ -1032,6 +1048,7 @@ func Test_LsFiles_RaceCondition(t *testing.T) { // Create two temporary directories and initialize them as git repositories tempDir1 := t.TempDir() tempDir2 := t.TempDir() + ctx := t.Context() client1, err := NewClient("file://"+tempDir1, NopCreds{}, true, false, "", "") require.NoError(t, err) @@ -1047,17 +1064,17 @@ func Test_LsFiles_RaceCondition(t *testing.T) { file1 := filepath.Join(client1.Root(), "file1.txt") err = os.WriteFile(file1, []byte("content1"), 0o644) require.NoError(t, err) - err = runCmd(client1.Root(), "git", "add", "file1.txt") + err = runCmd(ctx, client1.Root(), "git", "add", "file1.txt") require.NoError(t, err) - err = runCmd(client1.Root(), "git", "commit", "-m", "Add file1") + err = runCmd(ctx, client1.Root(), "git", "commit", "-m", "Add file1") require.NoError(t, err) file2 := filepath.Join(client2.Root(), "file2.txt") err = os.WriteFile(file2, []byte("content2"), 0o644) require.NoError(t, err) - err = runCmd(client2.Root(), "git", "add", "file2.txt") + err = runCmd(ctx, client2.Root(), "git", "add", "file2.txt") require.NoError(t, err) - err = runCmd(client2.Root(), "git", "commit", "-m", "Add file2") + err = runCmd(ctx, client2.Root(), "git", "commit", "-m", "Add file2") require.NoError(t, err) // Assert that LsFiles returns the correct files when called sequentially diff --git a/util/git/git_test.go b/util/git/git_test.go index 0fbdbbe8db..dcf9fcaacc 100644 --- a/util/git/git_test.go +++ b/util/git/git_test.go @@ -183,7 +183,7 @@ func TestCustomHTTPClient(t *testing.T) { assert.Nil(t, cert.PrivateKey) } } - req, err := http.NewRequest(http.MethodGet, "http://proxy-from-env:7878", http.NoBody) + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://proxy-from-env:7878", http.NoBody) require.NoError(t, err) proxy, err := transport.Proxy(req) require.NoError(t, err) @@ -454,11 +454,12 @@ func TestListRevisions(t *testing.T) { func TestLsFiles(t *testing.T) { tmpDir1 := t.TempDir() tmpDir2 := t.TempDir() + ctx := t.Context() client, err := NewClientExt("", tmpDir1, NopCreds{}, false, false, "", "") require.NoError(t, err) - require.NoError(t, runCmd(tmpDir1, "git", "init")) + require.NoError(t, runCmd(ctx, tmpDir1, "git", "init")) // Setup files require.NoError(t, os.WriteFile(filepath.Join(tmpDir1, "a.yaml"), []byte{}, 0o644)) @@ -470,8 +471,8 @@ func TestLsFiles(t *testing.T) { require.NoError(t, os.Symlink(filepath.Join(tmpDir2, "c.yaml"), filepath.Join(tmpDir1, "link.yaml"))) - require.NoError(t, runCmd(tmpDir1, "git", "add", ".")) - require.NoError(t, runCmd(tmpDir1, "git", "commit", "-m", "Initial commit")) + require.NoError(t, runCmd(ctx, tmpDir1, "git", "add", ".")) + require.NoError(t, runCmd(ctx, tmpDir1, "git", "commit", "-m", "Initial commit")) tests := []struct { name string @@ -510,11 +511,12 @@ func TestLsFiles(t *testing.T) { func TestLsFilesForGitFileGeneratorGlobbingPatterns(t *testing.T) { tmpDir := t.TempDir() + ctx := t.Context() client, err := NewClientExt("", tmpDir, NopCreds{}, false, false, "", "") require.NoError(t, err) - err = runCmd(tmpDir, "git", "init") + err = runCmd(ctx, tmpDir, "git", "init") require.NoError(t, err) // Setup directory structure and files @@ -538,8 +540,8 @@ func TestLsFilesForGitFileGeneratorGlobbingPatterns(t *testing.T) { _, err := os.Create(filepath.Join(tmpDir, file)) require.NoError(t, err) } - require.NoError(t, runCmd(tmpDir, "git", "add", ".")) - require.NoError(t, runCmd(tmpDir, "git", "commit", "-m", "Initial commit")) + require.NoError(t, runCmd(ctx, tmpDir, "git", "add", ".")) + require.NoError(t, runCmd(ctx, tmpDir, "git", "commit", "-m", "Initial commit")) tests := []struct { name string diff --git a/util/gpg/gpg.go b/util/gpg/gpg.go index 52bdd971bc..d1c70a6fe2 100644 --- a/util/gpg/gpg.go +++ b/util/gpg/gpg.go @@ -2,6 +2,7 @@ package gpg import ( "bufio" + "context" "encoding/hex" "errors" "fmt" @@ -216,6 +217,7 @@ func IsGPGEnabled() bool { // transient private key so that the trust DB will work correctly. func InitializeGnuPG() error { gnuPgHome := common.GetGnuPGHomePath() + ctx := context.Background() // We only operate if ARGOCD_GNUPGHOME is set if gnuPgHome == "" { @@ -273,7 +275,7 @@ func InitializeGnuPG() error { } }() - cmd := exec.Command("gpg", "--no-permission-warning", "--logger-fd", "1", "--batch", "--gen-key", f.Name()) + cmd := exec.CommandContext(ctx, "gpg", "--no-permission-warning", "--logger-fd", "1", "--batch", "--gen-key", f.Name()) cmd.Env = getGPGEnviron() _, err = executil.Run(cmd) @@ -306,8 +308,9 @@ func ImportPGPKeysFromString(keyData string) ([]*appsv1.GnuPGPublicKey, error) { // signs them with the transient private key for leveraging the trust DB. func ImportPGPKeys(keyFile string) ([]*appsv1.GnuPGPublicKey, error) { keys := make([]*appsv1.GnuPGPublicKey, 0) + ctx := context.Background() - cmd := exec.Command("gpg", "--no-permission-warning", "--logger-fd", "1", "--import", keyFile) + cmd := exec.CommandContext(ctx, "gpg", "--no-permission-warning", "--logger-fd", "1", "--import", keyFile) cmd.Env = getGPGEnviron() out, err := executil.Run(cmd) @@ -410,6 +413,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error } defer os.Remove(f.Name()) + ctx := context.Background() for _, k := range pgpKeys { _, err := fmt.Fprintf(f, "%s:%d\n", k.KeyID, trust) @@ -429,7 +433,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error }() // Load ownertrust from the file we have constructed and instruct gpg to update the trustdb - cmd := exec.Command("gpg", "--no-permission-warning", "--import-ownertrust", f.Name()) + cmd := exec.CommandContext(ctx, "gpg", "--no-permission-warning", "--import-ownertrust", f.Name()) cmd.Env = getGPGEnviron() _, err = executil.Run(cmd) @@ -438,7 +442,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error } // Update the trustdb once we updated the ownertrust, to prevent gpg to do it once we validate a signature - cmd = exec.Command("gpg", "--no-permission-warning", "--update-trustdb") + cmd = exec.CommandContext(ctx, "gpg", "--no-permission-warning", "--update-trustdb") cmd.Env = getGPGEnviron() _, err = executil.Run(cmd) if err != nil { @@ -451,7 +455,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error // DeletePGPKey deletes a key from our GnuPG key ring func DeletePGPKey(keyID string) error { args := append([]string{}, "--no-permission-warning", "--yes", "--batch", "--delete-keys", keyID) - cmd := exec.Command("gpg", args...) + cmd := exec.CommandContext(context.Background(), "gpg", args...) cmd.Env = getGPGEnviron() _, err := executil.Run(cmd) @@ -465,7 +469,7 @@ func DeletePGPKey(keyID string) error { // IsSecretKey returns true if the keyID also has a private key in the keyring func IsSecretKey(keyID string) (bool, error) { args := append([]string{}, "--no-permission-warning", "--list-secret-keys", keyID) - cmd := exec.Command("gpg-wrapper.sh", args...) + cmd := exec.CommandContext(context.Background(), "gpg-wrapper.sh", args...) cmd.Env = getGPGEnviron() out, err := executil.Run(cmd) if err != nil { @@ -480,13 +484,14 @@ func IsSecretKey(keyID string) (bool, error) { // GetInstalledPGPKeys() runs gpg to retrieve public keys from our keyring. If kids is non-empty, limit result to those key IDs func GetInstalledPGPKeys(kids []string) ([]*appsv1.GnuPGPublicKey, error) { keys := make([]*appsv1.GnuPGPublicKey, 0) + ctx := context.Background() args := append([]string{}, "--no-permission-warning", "--list-public-keys") // kids can contain an arbitrary list of key IDs we want to list. If empty, we list all keys. if len(kids) > 0 { args = append(args, kids...) } - cmd := exec.Command("gpg", args...) + cmd := exec.CommandContext(ctx, "gpg", args...) cmd.Env = getGPGEnviron() out, err := executil.Run(cmd) @@ -562,7 +567,7 @@ func GetInstalledPGPKeys(kids []string) ([]*appsv1.GnuPGPublicKey, error) { // We need to get the final key for each imported key, so we run --export on each key for _, key := range keys { - cmd := exec.Command("gpg", "--no-permission-warning", "-a", "--export", key.KeyID) + cmd := exec.CommandContext(ctx, "gpg", "--no-permission-warning", "-a", "--export", key.KeyID) cmd.Env = getGPGEnviron() out, err := executil.Run(cmd) diff --git a/util/gpg/gpg_test.go b/util/gpg/gpg_test.go index f5bd5b12da..b5e8d17dfc 100644 --- a/util/gpg/gpg_test.go +++ b/util/gpg/gpg_test.go @@ -78,7 +78,7 @@ func Test_GPG_InitializeGnuPG(t *testing.T) { // During unit-tests, we need to also kill gpg-agent so we can create a new key. // In real world scenario -- i.e. container crash -- gpg-agent is not running yet. - cmd := exec.Command("gpgconf", "--kill", "gpg-agent") + cmd := exec.CommandContext(t.Context(), "gpgconf", "--kill", "gpg-agent") cmd.Env = []string{"GNUPGHOME=" + p} err = cmd.Run() require.NoError(t, err) diff --git a/util/healthz/healthz_test.go b/util/healthz/healthz_test.go index c76a284c67..93f68beb83 100644 --- a/util/healthz/healthz_test.go +++ b/util/healthz/healthz_test.go @@ -11,10 +11,12 @@ import ( func TestHealthCheck(t *testing.T) { sentinel := false + lc := &net.ListenConfig{} + ctx := t.Context() serve := func(c chan<- string) { // listen on first available dynamic (unprivileged) port - listener, err := net.Listen("tcp", ":0") + listener, err := lc.Listen(ctx, "tcp", ":0") if err != nil { panic(err) } @@ -42,12 +44,18 @@ func TestHealthCheck(t *testing.T) { server := "http://" + address - resp, err := http.Get(server + "/healthz") + req, err := http.NewRequestWithContext(ctx, http.MethodGet, server+"/healthz", http.NoBody) + require.NoError(t, err) + + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) require.Equalf(t, http.StatusOK, resp.StatusCode, "Was expecting status code 200 from health check, but got %d instead", resp.StatusCode) sentinel = true - resp, _ = http.Get(server + "/healthz") + req, err = http.NewRequestWithContext(ctx, http.MethodGet, server+"/healthz", http.NoBody) + require.NoError(t, err) + resp, err = http.DefaultClient.Do(req) + require.NoError(t, err) require.Equalf(t, http.StatusServiceUnavailable, resp.StatusCode, "Was expecting status code 503 from health check, but got %d instead", resp.StatusCode) } diff --git a/util/helm/client.go b/util/helm/client.go index dc0a861a1f..f91f615e4c 100644 --- a/util/helm/client.go +++ b/util/helm/client.go @@ -121,9 +121,9 @@ func (c *nativeHelmChart) CleanChartCache(chart string, version string) error { return nil } -func untarChart(tempDir string, cachedChartPath string, manifestMaxExtractedSize int64, disableManifestMaxExtractedSize bool) error { +func untarChart(ctx context.Context, tempDir string, cachedChartPath string, manifestMaxExtractedSize int64, disableManifestMaxExtractedSize bool) error { if disableManifestMaxExtractedSize { - cmd := exec.Command("tar", "-zxvf", cachedChartPath) + cmd := exec.CommandContext(ctx, "tar", "-zxvf", cachedChartPath) cmd.Dir = tempDir _, err := executil.Run(cmd) if err != nil { @@ -225,7 +225,7 @@ func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredent } } - err = untarChart(tempDir, cachedChartPath, manifestMaxExtractedSize, disableManifestMaxExtractedSize) + err = untarChart(context.Background(), tempDir, cachedChartPath, manifestMaxExtractedSize, disableManifestMaxExtractedSize) if err != nil { _ = os.RemoveAll(tempDir) return "", nil, fmt.Errorf("error untarring chart: %w", err) @@ -248,8 +248,9 @@ func (c *nativeHelmChart) GetIndex(noCache bool, maxIndexSize int64) (*Index, er if len(data) == 0 { start := time.Now() + ctx := context.Background() var err error - data, err = c.loadRepoIndex(maxIndexSize) + data, err = c.loadRepoIndex(ctx, maxIndexSize) if err != nil { return nil, fmt.Errorf("error loading repo index: %w", err) } @@ -306,13 +307,13 @@ func (c *nativeHelmChart) TestHelmOCI() (bool, error) { return true, nil } -func (c *nativeHelmChart) loadRepoIndex(maxIndexSize int64) ([]byte, error) { +func (c *nativeHelmChart) loadRepoIndex(ctx context.Context, maxIndexSize int64) ([]byte, error) { indexURL, err := getIndexURL(c.repoURL) if err != nil { return nil, fmt.Errorf("error getting index URL: %w", err) } - req, err := http.NewRequest(http.MethodGet, indexURL, http.NoBody) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, indexURL, http.NoBody) if err != nil { return nil, fmt.Errorf("error creating HTTP request: %w", err) } diff --git a/util/helm/cmd.go b/util/helm/cmd.go index c941094036..f54cf96198 100644 --- a/util/helm/cmd.go +++ b/util/helm/cmd.go @@ -1,6 +1,7 @@ package helm import ( + "context" "errors" "fmt" "os" @@ -50,8 +51,8 @@ var redactor = func(text string) string { return regexp.MustCompile("(--username|--password) [^ ]*").ReplaceAllString(text, "$1 ******") } -func (c Cmd) run(args ...string) (string, string, error) { - cmd := exec.Command("helm", args...) +func (c Cmd) run(ctx context.Context, args ...string) (string, string, error) { + cmd := exec.CommandContext(ctx, "helm", args...) cmd.Dir = c.WorkDir cmd.Env = os.Environ() if !c.IsLocal { @@ -117,7 +118,7 @@ func (c *Cmd) RegistryLogin(repo string, creds Creds) (string, error) { if creds.GetInsecureSkipVerify() { args = append(args, "--insecure") } - out, _, err := c.run(args...) + out, _, err := c.run(context.Background(), args...) if err != nil { return "", fmt.Errorf("failed to login to registry: %w", err) } @@ -127,7 +128,7 @@ func (c *Cmd) RegistryLogin(repo string, creds Creds) (string, error) { func (c *Cmd) RegistryLogout(repo string, _ Creds) (string, error) { args := []string{"registry", "logout"} args = append(args, repo) - out, _, err := c.run(args...) + out, _, err := c.run(context.Background(), args...) if err != nil { return "", fmt.Errorf("failed to logout from registry: %w", err) } @@ -195,7 +196,7 @@ func (c *Cmd) RepoAdd(name string, url string, opts Creds, passCredentials bool) args = append(args, name, url) - out, _, err := c.run(args...) + out, _, err := c.run(context.Background(), args...) if err != nil { return "", fmt.Errorf("failed to add repository: %w", err) } @@ -270,7 +271,7 @@ func (c *Cmd) Fetch(repo, chartName, version, destination string, creds Creds, p args = append(args, "--pass-credentials") } - out, _, err := c.run(args...) + out, _, err := c.run(context.Background(), args...) if err != nil { return "", fmt.Errorf("failed to fetch chart: %w", err) } @@ -309,7 +310,7 @@ func (c *Cmd) PullOCI(repo string, chart string, version string, destination str if creds.GetInsecureSkipVerify() { args = append(args, "--insecure-skip-tls-verify") } - out, _, err := c.run(args...) + out, _, err := c.run(context.Background(), args...) if err != nil { return "", fmt.Errorf("failed to pull OCI chart: %w", err) } @@ -317,7 +318,7 @@ func (c *Cmd) PullOCI(repo string, chart string, version string, destination str } func (c *Cmd) dependencyBuild() (string, error) { - out, _, err := c.run("dependency", "build") + out, _, err := c.run(context.Background(), "dependency", "build") if err != nil { return "", fmt.Errorf("failed to build dependencies: %w", err) } @@ -325,7 +326,7 @@ func (c *Cmd) dependencyBuild() (string, error) { } func (c *Cmd) inspectValues(values string) (string, error) { - out, _, err := c.run("show", "values", values) + out, _, err := c.run(context.Background(), "show", "values", values) if err != nil { return "", fmt.Errorf("failed to inspect values: %w", err) } @@ -333,7 +334,7 @@ func (c *Cmd) inspectValues(values string) (string, error) { } func (c *Cmd) InspectChart() (string, error) { - out, _, err := c.run("show", "chart", ".") + out, _, err := c.run(context.Background(), "show", "chart", ".") if err != nil { return "", fmt.Errorf("failed to inspect chart: %w", err) } @@ -430,7 +431,7 @@ func (c *Cmd) template(chartPath string, opts *TemplateOpts) (string, string, er args = append(args, "--skip-tests") } - out, command, err := c.run(args...) + out, command, err := c.run(context.Background(), args...) if err != nil { msg := err.Error() if strings.Contains(msg, "--api-versions") { @@ -462,7 +463,7 @@ func cleanupChartLockFile(chartPath string) (func(), error) { } func (c *Cmd) Freestyle(args ...string) (string, error) { - out, _, err := c.run(args...) + out, _, err := c.run(context.Background(), args...) if err != nil { return "", fmt.Errorf("failed to execute freestyle helm command: %w", err) } diff --git a/util/helm/creds.go b/util/helm/creds.go index 97cd10c487..a203bb6ad1 100644 --- a/util/helm/creds.go +++ b/util/helm/creds.go @@ -1,6 +1,7 @@ package helm import ( + "context" "crypto/tls" "encoding/json" "errors" @@ -124,6 +125,7 @@ func NewAzureWorkloadIdentityCreds(repoURL string, caPath string, certData []byt func (creds AzureWorkloadIdentityCreds) GetAccessToken() (string, error) { registryHost := strings.Split(creds.repoURL, "/")[0] + ctx := context.Background() // Compute hash as key for refresh token in the cache key, err := argoutils.GenerateCacheKey("accesstoken-%s", registryHost) @@ -138,12 +140,12 @@ func (creds AzureWorkloadIdentityCreds) GetAccessToken() (string, error) { return t.(string), nil } - tokenParams, err := creds.challengeAzureContainerRegistry(registryHost) + tokenParams, err := creds.challengeAzureContainerRegistry(ctx, registryHost) if err != nil { return "", fmt.Errorf("failed to challenge Azure Container Registry: %w", err) } - token, err := creds.getAccessTokenAfterChallenge(tokenParams) + token, err := creds.getAccessTokenAfterChallenge(ctx, tokenParams) if err != nil { return "", fmt.Errorf("failed to get Azure access token after challenge: %w", err) } @@ -175,7 +177,7 @@ func getJWTExpiry(token string) (time.Time, error) { return time.UnixMilli(exp.UnixMilli()), nil } -func (creds AzureWorkloadIdentityCreds) getAccessTokenAfterChallenge(tokenParams map[string]string) (string, error) { +func (creds AzureWorkloadIdentityCreds) getAccessTokenAfterChallenge(ctx context.Context, tokenParams map[string]string) (string, error) { realm := tokenParams["realm"] service := tokenParams["service"] @@ -203,7 +205,13 @@ func (creds AzureWorkloadIdentityCreds) getAccessTokenAfterChallenge(tokenParams formValues.Add("service", service) formValues.Add("access_token", armAccessToken.AccessToken) - resp, err := client.PostForm(refreshTokenURL, formValues) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, refreshTokenURL, strings.NewReader(formValues.Encode())) + if err != nil { + return "", fmt.Errorf("failed to create request to get refresh token: %w", err) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("unable to connect to registry '%w'", err) } @@ -232,7 +240,7 @@ func (creds AzureWorkloadIdentityCreds) getAccessTokenAfterChallenge(tokenParams return res.RefreshToken, nil } -func (creds AzureWorkloadIdentityCreds) challengeAzureContainerRegistry(azureContainerRegistry string) (map[string]string, error) { +func (creds AzureWorkloadIdentityCreds) challengeAzureContainerRegistry(ctx context.Context, azureContainerRegistry string) (map[string]string, error) { requestURL := fmt.Sprintf("https://%s/v2/", azureContainerRegistry) client := &http.Client{ @@ -244,7 +252,7 @@ func (creds AzureWorkloadIdentityCreds) challengeAzureContainerRegistry(azureCon }, } - req, err := http.NewRequest(http.MethodGet, requestURL, http.NoBody) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, http.NoBody) if err != nil { return nil, err } diff --git a/util/helm/creds_test.go b/util/helm/creds_test.go index 532ebbc066..627745b8c8 100644 --- a/util/helm/creds_test.go +++ b/util/helm/creds_test.go @@ -102,7 +102,7 @@ func TestChallengeAzureContainerRegistry(t *testing.T) { workloadIdentityMock := new(mocks.TokenProvider) creds := NewAzureWorkloadIdentityCreds(mockServer.URL[8:], "", nil, nil, true, workloadIdentityMock) - tokenParams, err := creds.challengeAzureContainerRegistry(creds.repoURL) + tokenParams, err := creds.challengeAzureContainerRegistry(t.Context(), creds.repoURL) require.NoError(t, err) expectedParams := map[string]string{ @@ -124,7 +124,7 @@ func TestChallengeAzureContainerRegistryNoChallenge(t *testing.T) { workloadIdentityMock := new(mocks.TokenProvider) creds := NewAzureWorkloadIdentityCreds(mockServer.URL[8:], "", nil, nil, true, workloadIdentityMock) - _, err := creds.challengeAzureContainerRegistry(creds.repoURL) + _, err := creds.challengeAzureContainerRegistry(t.Context(), creds.repoURL) require.Error(t, err) assert.Contains(t, err.Error(), "did not issue a challenge") } @@ -142,7 +142,7 @@ func TestChallengeAzureContainerRegistryNonBearer(t *testing.T) { workloadIdentityMock := new(mocks.TokenProvider) creds := NewAzureWorkloadIdentityCreds(mockServer.URL[8:], "", nil, nil, true, workloadIdentityMock) - _, err := creds.challengeAzureContainerRegistry(creds.repoURL) + _, err := creds.challengeAzureContainerRegistry(t.Context(), creds.repoURL) assert.ErrorContains(t, err, "does not allow 'Bearer' authentication") } @@ -159,7 +159,7 @@ func TestChallengeAzureContainerRegistryNoService(t *testing.T) { workloadIdentityMock := new(mocks.TokenProvider) creds := NewAzureWorkloadIdentityCreds(mockServer.URL[8:], "", nil, nil, true, workloadIdentityMock) - _, err := creds.challengeAzureContainerRegistry(creds.repoURL) + _, err := creds.challengeAzureContainerRegistry(t.Context(), creds.repoURL) assert.ErrorContains(t, err, "service parameter not found in challenge") } @@ -176,7 +176,7 @@ func TestChallengeAzureContainerRegistryNoRealm(t *testing.T) { workloadIdentityMock := new(mocks.TokenProvider) creds := NewAzureWorkloadIdentityCreds(mockServer.URL[8:], "", nil, nil, true, workloadIdentityMock) - _, err := creds.challengeAzureContainerRegistry(creds.repoURL) + _, err := creds.challengeAzureContainerRegistry(t.Context(), creds.repoURL) assert.ErrorContains(t, err, "realm parameter not found in challenge") } @@ -201,7 +201,7 @@ func TestGetAccessTokenAfterChallenge_Success(t *testing.T) { "service": "registry.example.com", } - refreshToken, err := creds.getAccessTokenAfterChallenge(tokenParams) + refreshToken, err := creds.getAccessTokenAfterChallenge(t.Context(), tokenParams) require.NoError(t, err) assert.Equal(t, "newRefreshToken", refreshToken) } @@ -226,7 +226,7 @@ func TestGetAccessTokenAfterChallenge_Failure(t *testing.T) { "service": "registry.example.com", } - refreshToken, err := creds.getAccessTokenAfterChallenge(tokenParams) + refreshToken, err := creds.getAccessTokenAfterChallenge(t.Context(), tokenParams) require.ErrorContains(t, err, "failed to get refresh token") assert.Empty(t, refreshToken) } @@ -251,7 +251,7 @@ func TestGetAccessTokenAfterChallenge_MalformedResponse(t *testing.T) { "service": "registry.example.com", } - refreshToken, err := creds.getAccessTokenAfterChallenge(tokenParams) + refreshToken, err := creds.getAccessTokenAfterChallenge(t.Context(), tokenParams) require.ErrorContains(t, err, "failed to unmarshal response body") assert.Empty(t, refreshToken) } diff --git a/util/helm/helm.go b/util/helm/helm.go index 9bdea79c84..ef8d2fa89b 100644 --- a/util/helm/helm.go +++ b/util/helm/helm.go @@ -1,6 +1,7 @@ package helm import ( + "context" "errors" "fmt" "net/url" @@ -119,7 +120,7 @@ func (h *helm) Dispose() { } func Version() (string, error) { - cmd := exec.Command("helm", "version", "--client", "--short") + cmd := exec.CommandContext(context.Background(), "helm", "version", "--client", "--short") // example version output: // short: "v3.3.1+g249e521" version, err := executil.RunWithRedactor(cmd, redactor) diff --git a/util/http/http_test.go b/util/http/http_test.go index 5a19b9f973..bc97742611 100644 --- a/util/http/http_test.go +++ b/util/http/http_test.go @@ -65,7 +65,7 @@ func (rt TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) func TestTransportWithHeader(t *testing.T) { client := &http.Client{} - req, _ := http.NewRequest(http.MethodGet, "/foo", http.NoBody) + req, _ := http.NewRequestWithContext(t.Context(), http.MethodGet, "/foo", http.NoBody) req.Header.Set("Bar", "req_1") req.Header.Set("Foo", "req_1") diff --git a/util/kube/portforwarder.go b/util/kube/portforwarder.go index 2c96c5fb76..7dd5d66865 100644 --- a/util/kube/portforwarder.go +++ b/util/kube/portforwarder.go @@ -40,6 +40,7 @@ func selectPodForPortForward(clientSet kubernetes.Interface, namespace string, p } func PortForward(targetPort int, namespace string, overrides *clientcmd.ConfigOverrides, podSelectors ...string) (int, error) { + ctx := context.Background() loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin) @@ -93,8 +94,9 @@ func PortForward(targetPort int, namespace string, overrides *clientcmd.ConfigOv failedChan := make(chan error, 1) out := new(bytes.Buffer) errOut := new(bytes.Buffer) + lc := &net.ListenConfig{} - ln, err := net.Listen("tcp", "localhost:0") + ln, err := lc.Listen(ctx, "tcp", "localhost:0") if err != nil { return -1, err } diff --git a/util/kustomize/kustomize.go b/util/kustomize/kustomize.go index b07f54ddeb..1cbbe438d9 100644 --- a/util/kustomize/kustomize.go +++ b/util/kustomize/kustomize.go @@ -1,6 +1,7 @@ package kustomize import ( + "context" "errors" "fmt" "net/url" @@ -105,9 +106,9 @@ func (k *kustomize) getBinaryPath() string { // kustomize v3.8.5 patch release introduced a breaking change in "edit add