diff --git a/.golangci.yaml b/.golangci.yaml index 5fbf3f0da..97522e261 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -47,7 +47,7 @@ linters: - nestif - nilerr - nilnil - # - noctx + - noctx - nolintlint - nonamedreturns - nosprintfhostport diff --git a/cmd/cl-controlplane/app/server.go b/cmd/cl-controlplane/app/server.go index 0bd6f34fc..df566dfc6 100644 --- a/cmd/cl-controlplane/app/server.go +++ b/cmd/cl-controlplane/app/server.go @@ -230,10 +230,19 @@ func (o *Options) Run() error { readinessListenAddress := fmt.Sprintf("0.0.0.0:%d", api.ReadinessListenPort) httpServer := utilhttp.NewServer("controlplane-http", nil) httpServer.Router().Get("/", func(w http.ResponseWriter, r *http.Request) { - resp, err := http.Get(fmt.Sprintf("https://127.0.0.1:%d", api.ListenPort)) + ctx := r.Context() + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://127.0.0.1:%d", api.ListenPort), http.NoBody) + if err != nil { + logrus.Errorf("Error creating request: %v", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + resp, err := http.DefaultClient.Do(req) if err == nil && resp.Body.Close() != nil { logrus.Infof("Cannot close readiness response body: %v", err) } + if errors.Is(err, syscall.ECONNREFUSED) || errors.Is(err, syscall.ECONNRESET) || !authzManager.IsReady() || diff --git a/cmd/cl-dataplane/app/server.go b/cmd/cl-dataplane/app/server.go index 0f6953f9f..49670eb94 100644 --- a/cmd/cl-dataplane/app/server.go +++ b/cmd/cl-dataplane/app/server.go @@ -92,7 +92,15 @@ func (o *Options) Run() error { return fmt.Errorf("cannot listen for readiness: %w", err) } httpServer.Router().Get("/", func(w http.ResponseWriter, r *http.Request) { - resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/ready", adminPort)) + ctx := r.Context() + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("http://127.0.0.1:%d/ready", adminPort), http.NoBody) + if err != nil { + logrus.Errorf("Error creating request: %v", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + resp, err := http.DefaultClient.Do(req) if err == nil && resp.Body.Close() != nil { logrus.Infof("Cannot close readiness response body: %v", err) } diff --git a/cmd/cl-go-dataplane/app/server.go b/cmd/cl-go-dataplane/app/server.go index 42d8be5ef..0182937a3 100644 --- a/cmd/cl-go-dataplane/app/server.go +++ b/cmd/cl-go-dataplane/app/server.go @@ -111,7 +111,7 @@ func (o *Options) runGoDataplane(dataplaneID string, parsedCertData *tls.ParsedC return fmt.Errorf("cannot listen for readiness: %w", err) } httpServer.Router().Get("/", func(w http.ResponseWriter, r *http.Request) { - if !xdsClient.IsReady() || !dataplane.IsReady() { + if !xdsClient.IsReady() || !dataplane.IsReady(r.Context()) { w.WriteHeader(http.StatusServiceUnavailable) } }) diff --git a/pkg/controlplane/authz/manager.go b/pkg/controlplane/authz/manager.go index 38da2bb6d..293a4ac35 100644 --- a/pkg/controlplane/authz/manager.go +++ b/pkg/controlplane/authz/manager.go @@ -324,11 +324,13 @@ func (m *Manager) authorizeEgress(ctx context.Context, req *egressAuthorizationR } m.logger.Infof("Egress authorized. Sending authorization request to %s", importSource.Peer) - accessToken, err := cl.Authorize(&cpapi.AuthorizationRequest{ - ServiceName: DstName, - ServiceNamespace: DstNamespace, - SrcAttributes: srcAttributes, - }) + accessToken, err := cl.Authorize( + ctx, + &cpapi.AuthorizationRequest{ + ServiceName: DstName, + ServiceNamespace: DstNamespace, + SrcAttributes: srcAttributes, + }) if err != nil { m.logger.Infof("Unable to get access token from peer: %v", err) continue diff --git a/pkg/controlplane/peer/client.go b/pkg/controlplane/peer/client.go index bc1dcf51c..79972357f 100644 --- a/pkg/controlplane/peer/client.go +++ b/pkg/controlplane/peer/client.go @@ -14,6 +14,7 @@ package peer import ( + "context" "crypto/tls" "encoding/json" "errors" @@ -94,14 +95,14 @@ func (c *Client) getResponse( } // Authorize a request for accessing a peer exported service, yielding an access token. -func (c *Client) Authorize(req *api.AuthorizationRequest) (string, error) { +func (c *Client) Authorize(ctx context.Context, req *api.AuthorizationRequest) (string, error) { body, err := json.Marshal(req) if err != nil { return "", fmt.Errorf("unable to serialize authorization request: %w", err) } serverResp, err := c.getResponse(func(client *jsonapi.Client) (*jsonapi.Response, error) { - return client.Post(api.RemotePeerAuthorizationPath, body) + return client.Post(ctx, api.RemotePeerAuthorizationPath, body) }) if err != nil { return "", err @@ -118,7 +119,7 @@ func (c *Client) Authorize(req *api.AuthorizationRequest) (string, error) { // GetHeartbeat get a heartbeat from other peers. func (c *Client) GetHeartbeat() error { serverResp, err := c.getResponse(func(client *jsonapi.Client) (*jsonapi.Response, error) { - return client.Get(api.HeartbeatPath) + return client.Get(context.Background(), api.HeartbeatPath) }) if err != nil { return err diff --git a/pkg/dataplane/server/server.go b/pkg/dataplane/server/server.go index d8e1f1148..cbd44cd3d 100644 --- a/pkg/dataplane/server/server.go +++ b/pkg/dataplane/server/server.go @@ -14,6 +14,7 @@ package server import ( + "context" "crypto/tls" "errors" "fmt" @@ -60,8 +61,14 @@ func (d *Dataplane) StartDataplaneServer(dataplaneServerAddress string) error { return server.ListenAndServeTLS("", "") } -func (d *Dataplane) IsReady() bool { - resp, err := http.Get(fmt.Sprintf("https://127.0.0.1:%d", api.ListenPort)) +func (d *Dataplane) IsReady(ctx context.Context) bool { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://127.0.0.1:%d", api.ListenPort), http.NoBody) + if err != nil { + d.logger.Errorf("Error creating readiness request: %v", err) + return false + } + + resp, err := http.DefaultClient.Do(req) if err == nil && resp.Body.Close() != nil { d.logger.Infof("Cannot close readiness response body: %v", err) } @@ -239,6 +246,8 @@ func (d *Dataplane) initiateEgressConnection(targetCluster, authToken string, ap return err } + ctx := context.Background() + client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsConfig, @@ -246,7 +255,7 @@ func (d *Dataplane) initiateEgressConnection(targetCluster, authToken string, ap }, } - egressReq, err := http.NewRequest(http.MethodConnect, url, http.NoBody) + egressReq, err := http.NewRequestWithContext(ctx, http.MethodConnect, url, http.NoBody) if err != nil { return err } diff --git a/pkg/util/jsonapi/client.go b/pkg/util/jsonapi/client.go index 22d86eeed..683424d59 100644 --- a/pkg/util/jsonapi/client.go +++ b/pkg/util/jsonapi/client.go @@ -15,6 +15,7 @@ package jsonapi import ( "bytes" + "context" "crypto/tls" "errors" "fmt" @@ -44,23 +45,23 @@ type Response struct { } // Get sends an HTTP GET request. -func (c *Client) Get(path string) (*Response, error) { - return c.do(http.MethodGet, path, nil) +func (c *Client) Get(ctx context.Context, path string) (*Response, error) { + return c.do(ctx, http.MethodGet, path, nil) } // Post sends an HTTP POST request. -func (c *Client) Post(path string, body []byte) (*Response, error) { - return c.do(http.MethodPost, path, body) +func (c *Client) Post(ctx context.Context, path string, body []byte) (*Response, error) { + return c.do(ctx, http.MethodPost, path, body) } // Put sends an HTTP PUT request. -func (c *Client) Put(path string, body []byte) (*Response, error) { - return c.do(http.MethodPut, path, body) +func (c *Client) Put(ctx context.Context, path string, body []byte) (*Response, error) { + return c.do(ctx, http.MethodPut, path, body) } // Delete sends an HTTP DELETE request. -func (c *Client) Delete(path string, body []byte) (*Response, error) { - return c.do(http.MethodDelete, path, body) +func (c *Client) Delete(ctx context.Context, path string, body []byte) (*Response, error) { + return c.do(ctx, http.MethodDelete, path, body) } // ServerURL returns the server URL configured for this client. @@ -68,13 +69,13 @@ func (c *Client) ServerURL() string { return c.serverURL } -func (c *Client) do(method, path string, body []byte) (*Response, error) { +func (c *Client) do(ctx context.Context, method, path string, body []byte) (*Response, error) { requestLogger := c.logger.WithFields(logrus.Fields{"method": method, "path": path}) requestLogger.WithField("body-length", len(body)).Debugf("Issuing request.") requestLogger.Debugf("Request body: %v.", body) - req, err := http.NewRequest(method, c.serverURL+path, bytes.NewBuffer(body)) + req, err := http.NewRequestWithContext(ctx, method, c.serverURL+path, bytes.NewBuffer(body)) if err != nil { return nil, fmt.Errorf("unable to create http request: %w", err) } diff --git a/tests/e2e/k8s/services/httpecho/client.go b/tests/e2e/k8s/services/httpecho/client.go index 3fe3139a0..dad8e12fe 100644 --- a/tests/e2e/k8s/services/httpecho/client.go +++ b/tests/e2e/k8s/services/httpecho/client.go @@ -14,6 +14,7 @@ package httpecho import ( + "context" "errors" "fmt" "io" @@ -48,7 +49,14 @@ func GetEchoValue(cluster *util.KindCluster, server *util.Service) (string, erro } url := fmt.Sprintf("http://%s", net.JoinHostPort(cluster.IP(), strconv.Itoa(int(port)))) - resp, err := client.Get(url) + ctx := context.Background() + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) + if err != nil { + // handle error + return "", fmt.Errorf("cannot create request: %w", err) + } + + resp, err := client.Do(req) if err != nil { if errors.Is(err, syscall.ECONNREFUSED) { return "", &services.ConnectionRefusedError{} diff --git a/tests/e2e/k8s/util/k8s_yaml.go b/tests/e2e/k8s/util/k8s_yaml.go index 9b7ad6349..b17868a56 100644 --- a/tests/e2e/k8s/util/k8s_yaml.go +++ b/tests/e2e/k8s/util/k8s_yaml.go @@ -37,20 +37,20 @@ func replaceOnce(s, search, replace string) (string, error) { return strings.ReplaceAll(s, search, replace), nil } -func (f *Fabric) generateK8SYAML(p *peer, cfg *PeerConfig) (string, error) { +func (f *Fabric) generateK8SYAML(pr *peer, cfg *PeerConfig) (string, error) { logLevel := "info" if os.Getenv("DEBUG") == "1" { logLevel = "debug" } k8sYAMLBytes, err := platform.K8SConfig(&platform.Config{ - Peer: p.cluster.Name(), + Peer: pr.cluster.Name(), FabricCertificate: f.cert, - PeerCertificate: p.peerCert, - CACertificate: p.caCert, + PeerCertificate: pr.peerCert, + CACertificate: pr.caCert, Controlplanes: cfg.Controlplanes, - ControlplaneCertificate: p.controlplaneCert, - DataplaneCertificate: p.dataplaneCert, + ControlplaneCertificate: pr.controlplaneCert, + DataplaneCertificate: pr.dataplaneCert, Dataplanes: cfg.Dataplanes, DataplaneType: cfg.DataplaneType, LogLevel: logLevel, @@ -58,8 +58,8 @@ func (f *Fabric) generateK8SYAML(p *peer, cfg *PeerConfig) (string, error) { Namespace: f.namespace, Tag: "latest", PeerLabels: map[string]string{ - ClusterNameLabel: p.cluster.name, - PeerIPLabel: p.cluster.ip, + ClusterNameLabel: pr.cluster.name, + PeerIPLabel: pr.cluster.ip, }, }) if err != nil {