diff --git a/tests/framework/generate_manifests.go b/tests/framework/generate_manifests.go index 8e5d436fd6..c7a00e234a 100644 --- a/tests/framework/generate_manifests.go +++ b/tests/framework/generate_manifests.go @@ -7,6 +7,7 @@ import ( "io" "text/template" + . "github.com/onsi/ginkgo/v2" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" "sigs.k8s.io/controller-runtime/pkg/client" @@ -221,6 +222,7 @@ func GenerateScaleListenerObjects(numListeners int, tls bool) (ScaleObjects, err } func generateSecrets(secrets []string) ([]client.Object, error) { + GinkgoWriter.Printf("Generating secrets\n") objects := make([]client.Object, 0, len(secrets)) for _, secret := range secrets { @@ -237,6 +239,7 @@ func generateSecrets(secrets []string) ([]client.Object, error) { objects = append(objects, objs...) } + GinkgoWriter.Printf("Generated %d secrets\n", len(objects)) return objects, nil } diff --git a/tests/framework/logging.go b/tests/framework/logging.go new file mode 100644 index 0000000000..aaf9f54a48 --- /dev/null +++ b/tests/framework/logging.go @@ -0,0 +1,13 @@ +package framework + +type Option func(*Options) + +type Options struct { + logEnabled bool +} + +func WithLoggingDisabled() Option { + return func(opts *Options) { + opts.logEnabled = false + } +} diff --git a/tests/framework/ngf.go b/tests/framework/ngf.go index 8bff1a4194..660cb79e8e 100644 --- a/tests/framework/ngf.go +++ b/tests/framework/ngf.go @@ -41,6 +41,7 @@ type InstallationConfig struct { // InstallGatewayAPI installs the specified version of the Gateway API resources. func InstallGatewayAPI(apiVersion string) ([]byte, error) { apiPath := fmt.Sprintf("%s/v%s/standard-install.yaml", gwInstallBasePath, apiVersion) + GinkgoWriter.Printf("Installing Gateway API version %q at API path %q\n", apiVersion, apiPath) cmd := exec.CommandContext( context.Background(), @@ -48,8 +49,11 @@ func InstallGatewayAPI(apiVersion string) ([]byte, error) { ) output, err := cmd.CombinedOutput() if err != nil { + GinkgoWriter.Printf("Error installing Gateway API version %q: %v\n", apiVersion, err) + return output, err } + GinkgoWriter.Printf("Successfully installed Gateway API version %q\n", apiVersion) return nil, nil } @@ -57,11 +61,15 @@ func InstallGatewayAPI(apiVersion string) ([]byte, error) { // UninstallGatewayAPI uninstalls the specified version of the Gateway API resources. func UninstallGatewayAPI(apiVersion string) ([]byte, error) { apiPath := fmt.Sprintf("%s/v%s/standard-install.yaml", gwInstallBasePath, apiVersion) + GinkgoWriter.Printf("Uninstalling Gateway API version %q at API path %q\n", apiVersion, apiPath) output, err := exec.CommandContext(context.Background(), "kubectl", "delete", "-f", apiPath).CombinedOutput() if err != nil && !strings.Contains(string(output), "not found") { + GinkgoWriter.Printf("Error uninstalling Gateway API version %q: %v\n", apiVersion, err) + return output, err } + GinkgoWriter.Printf("Successfully uninstalled Gateway API version %q\n", apiVersion) return nil, nil } @@ -94,9 +102,14 @@ func InstallNGF(cfg InstallationConfig, extraArgs ...string) ([]byte, error) { // CreateLicenseSecret creates the NGINX Plus JWT secret. func CreateLicenseSecret(k8sClient client.Client, namespace, filename string) error { + GinkgoWriter.Printf("Creating NGINX Plus license secret in namespace %q from file %q\n", namespace, filename) + conf, err := os.ReadFile(filename) if err != nil { - return fmt.Errorf("error reading file %q: %w", filename, err) + readFileErr := fmt.Errorf("error reading file %q: %w", filename, err) + GinkgoWriter.Printf("%v\n", readFileErr) + + return readFileErr } ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeoutConfig().CreateTimeout) @@ -109,7 +122,10 @@ func CreateLicenseSecret(k8sClient client.Client, namespace, filename string) er } if err := k8sClient.Create(ctx, ns); err != nil && !apierrors.IsAlreadyExists(err) { - return fmt.Errorf("error creating namespace: %w", err) + createNSErr := fmt.Errorf("error creating namespace: %w", err) + GinkgoWriter.Printf("%v\n", createNSErr) + + return createNSErr } secret := &core.Secret{ @@ -123,7 +139,10 @@ func CreateLicenseSecret(k8sClient client.Client, namespace, filename string) er } if err := k8sClient.Create(ctx, secret); err != nil && !apierrors.IsAlreadyExists(err) { - return fmt.Errorf("error creating secret: %w", err) + createSecretErr := fmt.Errorf("error creating secret: %w", err) + GinkgoWriter.Printf("%v\n", createSecretErr) + + return createSecretErr } return nil @@ -170,6 +189,7 @@ func UninstallNGF(cfg InstallationConfig, k8sClient client.Client) ([]byte, erro args := []string{ "uninstall", cfg.ReleaseName, "--namespace", cfg.Namespace, } + GinkgoWriter.Printf("Uninstalling NGF with command: helm %v\n", strings.Join(args, " ")) output, err := exec.CommandContext(context.Background(), "helm", args...).CombinedOutput() if err != nil && !strings.Contains(string(output), "release: not found") { @@ -204,6 +224,7 @@ func UninstallNGF(cfg InstallationConfig, k8sClient client.Client) ([]byte, erro func setTelemetryArgs(cfg InstallationConfig) []string { var args []string + GinkgoWriter.Printf("Setting telemetry to %v\n", cfg.Telemetry) if cfg.Telemetry { args = append(args, formatValueSet("nginxGateway.productTelemetry.enable", "true")...) } else { diff --git a/tests/framework/portforward.go b/tests/framework/portforward.go index 9465c330d6..7fdd2aa4f5 100644 --- a/tests/framework/portforward.go +++ b/tests/framework/portforward.go @@ -11,6 +11,7 @@ import ( "sync" "time" + . "github.com/onsi/ginkgo/v2" "k8s.io/client-go/rest" "k8s.io/client-go/tools/portforward" "k8s.io/client-go/transport/spdy" @@ -20,12 +21,18 @@ import ( func PortForward(config *rest.Config, namespace, podName string, ports []string, stopCh <-chan struct{}) error { roundTripper, upgrader, err := spdy.RoundTripperFor(config) if err != nil { - return fmt.Errorf("error creating roundtripper: %w", err) + roundTripperErr := fmt.Errorf("error creating roundtripper: %w", err) + GinkgoWriter.Printf("%v\n", roundTripperErr) + + return roundTripperErr } serverURL, err := url.Parse(config.Host) if err != nil { - return fmt.Errorf("error parsing rest config host: %w", err) + parseConfigErr := fmt.Errorf("error parsing rest config host: %w", err) + GinkgoWriter.Printf("%v\n", parseConfigErr) + + return parseConfigErr } serverURL.Path = path.Join( @@ -35,14 +42,24 @@ func PortForward(config *rest.Config, namespace, podName string, ports []string, "portforward", ) + GinkgoWriter.Printf("Creating new dialer for serverURL: %q\n", serverURL) dialer := spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, serverURL) forward := func() error { readyCh := make(chan struct{}, 1) + GinkgoWriter.Printf( + "Starting port-forward to pod %q in namespace %q for ports %v\n", + podName, + namespace, + ports, + ) forwarder, err := portforward.New(dialer, ports, stopCh, readyCh, newSafeBuffer(), newSafeBuffer()) if err != nil { - return fmt.Errorf("error creating port forwarder: %w", err) + createPortForwardErr := fmt.Errorf("error creating port forwarder: %w", err) + GinkgoWriter.Printf("%v\n", createPortForwardErr) + + return createPortForwardErr } return forwarder.ForwardPorts() diff --git a/tests/framework/prometheus.go b/tests/framework/prometheus.go index 24c594ddf2..6ce8a300bb 100644 --- a/tests/framework/prometheus.go +++ b/tests/framework/prometheus.go @@ -456,9 +456,9 @@ func CreateEndTimeFinder( } // CreateResponseChecker returns a function that checks if there is a successful response from a url. -func CreateResponseChecker(url, address string, requestTimeout time.Duration) func() error { +func CreateResponseChecker(url, address string, requestTimeout time.Duration, opts ...Option) func() error { return func() error { - status, _, err := Get(url, address, requestTimeout, nil, nil) + status, _, err := Get(url, address, requestTimeout, nil, nil, opts...) if err != nil { return fmt.Errorf("bad response: %w", err) } diff --git a/tests/framework/request.go b/tests/framework/request.go index 7cc1b0384c..a04d8ccc66 100644 --- a/tests/framework/request.go +++ b/tests/framework/request.go @@ -11,6 +11,8 @@ import ( "net/http" "strings" "time" + + . "github.com/onsi/ginkgo/v2" ) // Get sends a GET request to the specified url. @@ -20,9 +22,22 @@ func Get( url, address string, timeout time.Duration, headers, queryParams map[string]string, + opts ...Option, ) (int, string, error) { - resp, err := makeRequest(http.MethodGet, url, address, nil, timeout, headers, queryParams) + options := &Options{logEnabled: true} + for _, opt := range opts { + opt(options) + } + + resp, err := makeRequest(http.MethodGet, url, address, nil, timeout, headers, queryParams, opts...) if err != nil { + if options.logEnabled { + GinkgoWriter.Printf( + "ERROR occurred during getting response, error: %s\nReturning status: 0, body: ''\n", + err, + ) + } + return 0, "", err } defer resp.Body.Close() @@ -30,8 +45,12 @@ func Get( body := new(bytes.Buffer) _, err = body.ReadFrom(resp.Body) if err != nil { + GinkgoWriter.Printf("ERROR in Body content: %v returning body: ''\n", err) return resp.StatusCode, "", err } + if options.logEnabled { + GinkgoWriter.Printf("Successfully received response and parsed body: %s\n", body.String()) + } return resp.StatusCode, body.String(), nil } @@ -44,7 +63,12 @@ func Post( timeout time.Duration, headers, queryParams map[string]string, ) (*http.Response, error) { - return makeRequest(http.MethodPost, url, address, body, timeout, headers, queryParams) + response, err := makeRequest(http.MethodPost, url, address, body, timeout, headers, queryParams) + if err != nil { + GinkgoWriter.Printf("ERROR occurred during getting response, error: %s\n", err) + } + + return response, err } func makeRequest( @@ -52,6 +76,7 @@ func makeRequest( body io.Reader, timeout time.Duration, headers, queryParams map[string]string, + opts ...Option, ) (*http.Response, error) { dialer := &net.Dialer{} @@ -74,6 +99,23 @@ func makeRequest( ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() + options := &Options{logEnabled: true} + + for _, opt := range opts { + opt(options) + } + if options.logEnabled { + requestDetails := fmt.Sprintf( + "Method: %s, URL: %s, Address: %s, Headers: %v, QueryParams: %v\n", + strings.ToUpper(method), + url, + address, + headers, + queryParams, + ) + GinkgoWriter.Printf("Sending request: %s", requestDetails) + } + req, err := http.NewRequestWithContext(ctx, method, url, body) if err != nil { return nil, err diff --git a/tests/framework/resourcemanager.go b/tests/framework/resourcemanager.go index 8b71b644f6..f51f17920a 100644 --- a/tests/framework/resourcemanager.go +++ b/tests/framework/resourcemanager.go @@ -33,6 +33,7 @@ import ( "strings" "time" + . "github.com/onsi/ginkgo/v2" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -76,6 +77,7 @@ type ClusterInfo struct { // Apply creates or updates Kubernetes resources defined as Go objects. func (rm *ResourceManager) Apply(resources []client.Object) error { + GinkgoWriter.Printf("Applying resources defined as Go objects\n") ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.CreateTimeout) defer cancel() @@ -89,17 +91,35 @@ func (rm *ResourceManager) Apply(resources []client.Object) error { t := reflect.TypeOf(resource).Elem() obj, ok = reflect.New(t).Interface().(client.Object) if !ok { - panic("failed to cast object to client.Object") + panicMsg := "failed to cast object to client.Object" + GinkgoWriter.Printf( + "PANIC occurred during applying creates or updates Kubernetes resources defined as Go objects: %s\n", + panicMsg, + ) + + panic(panicMsg) } } if err := rm.K8sClient.Get(ctx, client.ObjectKeyFromObject(resource), obj); err != nil { if !apierrors.IsNotFound(err) { - return fmt.Errorf("error getting resource: %w", err) + notFoundErr := fmt.Errorf("error getting resource: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during getting Kubernetes resources: %s\n", + notFoundErr, + ) + + return notFoundErr } if err := rm.K8sClient.Create(ctx, resource); err != nil { - return fmt.Errorf("error creating resource: %w", err) + creatingResourceErr := fmt.Errorf("error creating resource: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during applying creates Kubernetes resources: %s\n", + creatingResourceErr, + ) + + return creatingResourceErr } continue @@ -109,15 +129,35 @@ func (rm *ResourceManager) Apply(resources []client.Object) error { // For example, a Gateway resource. err := retry.RetryOnConflict(retry.DefaultRetry, func() error { if err := rm.K8sClient.Get(ctx, client.ObjectKeyFromObject(resource), obj); err != nil { + GinkgoWriter.Printf( + "ERROR occurred during getting Kubernetes resources on retries: %s\n", + err, + ) + return err } resource.SetResourceVersion(obj.GetResourceVersion()) - return rm.K8sClient.Update(ctx, resource) + updateErr := rm.K8sClient.Update(ctx, resource) + if updateErr != nil { + GinkgoWriter.Printf( + "ERROR occurred during updating Kubernetes resources on retries: %s\n", + updateErr, + ) + } + + return updateErr }) if err != nil { - return fmt.Errorf("error updating resource: %w", err) + retryErr := fmt.Errorf("error updating resource: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during retries: %s\n", + retryErr, + ) + + return retryErr } } + GinkgoWriter.Printf("Resources defined as Go objects applied successfully\n") return nil } @@ -125,15 +165,22 @@ func (rm *ResourceManager) Apply(resources []client.Object) error { // ApplyFromFiles creates or updates Kubernetes resources defined within the provided YAML files. func (rm *ResourceManager) ApplyFromFiles(files []string, namespace string) error { for _, file := range files { + GinkgoWriter.Printf("Applying resources from file: %q to namespace %q\n", file, namespace) data, err := rm.GetFileContents(file) if err != nil { + GinkgoWriter.Printf("ERROR occurred during getting file contents for file %q, error: %s\n", file, err) + return err } if err = rm.ApplyFromBuffer(data, namespace); err != nil { + GinkgoWriter.Printf("ERROR occurred during applying resources from file %q, error: %s\n", file, err) + return err } } + GinkgoWriter.Printf("Resources from files applied successfully to namespace %q,\n", namespace) + return nil } @@ -147,11 +194,17 @@ func (rm *ResourceManager) ApplyFromBuffer(buffer *bytes.Buffer, namespace strin fetchedObj := obj.DeepCopy() if err := rm.K8sClient.Get(ctx, nsName, fetchedObj); err != nil { if !apierrors.IsNotFound(err) { - return fmt.Errorf("error getting resource: %w", err) + getResourceErr := fmt.Errorf("error getting resource: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting resource from buffer, error: %s\n", getResourceErr) + + return getResourceErr } if err := rm.K8sClient.Create(ctx, &obj); err != nil { - return fmt.Errorf("error creating resource: %w", err) + createResourceErr := fmt.Errorf("error creating resource: %w", err) + GinkgoWriter.Printf("ERROR occurred during creating resource from buffer, error: %s\n", createResourceErr) + + return createResourceErr } return nil @@ -161,13 +214,29 @@ func (rm *ResourceManager) ApplyFromBuffer(buffer *bytes.Buffer, namespace strin // For example, a Gateway resource. err := retry.RetryOnConflict(retry.DefaultRetry, func() error { if err := rm.K8sClient.Get(ctx, nsName, fetchedObj); err != nil { + GinkgoWriter.Printf( + "ERROR occurred during getting resource from buffer on retries, error: %s\n", + err, + ) + return err } obj.SetResourceVersion(fetchedObj.GetResourceVersion()) - return rm.K8sClient.Update(ctx, &obj) + updateErr := rm.K8sClient.Update(ctx, &obj) + if updateErr != nil { + GinkgoWriter.Printf("ERROR occurred during updating resource from buffer, error: %s\n", updateErr) + } + + return updateErr }) if err != nil { - return fmt.Errorf("error updating resource: %w", err) + retryErr := fmt.Errorf("error updating resource: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during retries, while update from buffer error: %s\n", + retryErr, + ) + + return retryErr } return nil @@ -178,34 +247,49 @@ func (rm *ResourceManager) ApplyFromBuffer(buffer *bytes.Buffer, namespace strin // Delete deletes Kubernetes resources defined as Go objects. func (rm *ResourceManager) Delete(resources []client.Object, opts ...client.DeleteOption) error { + GinkgoWriter.Printf("Deleting resources\n") ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.DeleteTimeout) defer cancel() for _, resource := range resources { if err := rm.K8sClient.Delete(ctx, resource, opts...); err != nil && !apierrors.IsNotFound(err) { - return fmt.Errorf("error deleting resource: %w", err) + delErr := fmt.Errorf("error deleting resource: %w", err) + GinkgoWriter.Printf("ERROR occurred during deleting resource, error: %s\n", delErr) + + return delErr } } + GinkgoWriter.Printf("Resources deleted successfully\n") return nil } func (rm *ResourceManager) DeleteNamespace(name string) error { ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.DeleteNamespaceTimeout) + GinkgoWriter.Printf("Deleting namespace %q\n", name) defer cancel() ns := &core.Namespace{} if err := rm.K8sClient.Get(ctx, types.NamespacedName{Name: name}, ns); err != nil { if apierrors.IsNotFound(err) { + GinkgoWriter.Printf("Namespace %q not found, nothing to delete\n", name) + return nil } - return fmt.Errorf("error getting namespace: %w", err) + getNsErr := fmt.Errorf("error getting namespace: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting namespace, error: %s\n", getNsErr) + + return getNsErr } if err := rm.K8sClient.Delete(ctx, ns); err != nil { - return fmt.Errorf("error deleting namespace: %w", err) + delErr := fmt.Errorf("error deleting namespace: %w", err) + GinkgoWriter.Printf("ERROR occurred during deleting namespace, error: %s\n", delErr) + + return delErr } + GinkgoWriter.Printf("Waiting for namespace %q to be deleted\n", name) // Because the namespace deletion is asynchronous, we need to wait for the namespace to be deleted. return wait.PollUntilContextCancel( ctx, @@ -214,15 +298,22 @@ func (rm *ResourceManager) DeleteNamespace(name string) error { func(ctx context.Context) (bool, error) { if err := rm.K8sClient.Get(ctx, types.NamespacedName{Name: name}, ns); err != nil { if apierrors.IsNotFound(err) { + GinkgoWriter.Printf("Namespace %q not found (deleted)\n", name) + return true, nil } - return false, fmt.Errorf("error getting namespace: %w", err) + getNsErr := fmt.Errorf("error getting namespace: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting namespace, error: %s\n", getNsErr) + + return false, getNsErr } + return false, nil }) } func (rm *ResourceManager) DeleteNamespaces(names []string) error { + GinkgoWriter.Printf("Deleting namespaces: %v\n", names) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.DeleteNamespaceTimeout*2) defer cancel() @@ -232,10 +323,13 @@ func (rm *ResourceManager) DeleteNamespaces(names []string) error { if err := rm.K8sClient.Delete(ctx, ns); err != nil { if apierrors.IsNotFound(err) { + GinkgoWriter.Printf("Namespace %q not found, nothing to delete\n", name) continue } + delNsErr := fmt.Errorf("error deleting namespace: %w", err) + GinkgoWriter.Printf("ERROR occurred during deleting namespace %q, error: %s\n", name, delNsErr) - combinedErrors = errors.Join(combinedErrors, fmt.Errorf("error deleting namespace: %w", err)) + combinedErrors = errors.Join(combinedErrors, delNsErr) } } @@ -263,12 +357,15 @@ func (rm *ResourceManager) DeleteNamespaces(names []string) error { // DeleteFromFiles deletes Kubernetes resources defined within the provided YAML files. func (rm *ResourceManager) DeleteFromFiles(files []string, namespace string) error { + GinkgoWriter.Printf("Deleting resources from files: %v in namespace %q\n", files, namespace) handlerFunc := func(obj unstructured.Unstructured) error { obj.SetNamespace(namespace) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.DeleteTimeout) defer cancel() if err := rm.K8sClient.Delete(ctx, &obj); err != nil && !apierrors.IsNotFound(err) { + GinkgoWriter.Printf("ERROR occurred during deleting resource from file, error: %s\n", err) + return err } @@ -278,6 +375,8 @@ func (rm *ResourceManager) DeleteFromFiles(files []string, namespace string) err for _, file := range files { data, err := rm.GetFileContents(file) if err != nil { + GinkgoWriter.Printf("ERROR occurred during getting file contents for file %q, error: %s\n", file, err) + return err } @@ -367,6 +466,7 @@ func (rm *ResourceManager) GetFileContents(file string) (*bytes.Buffer, error) { // WaitForAppsToBeReady waits for all apps in the specified namespace to be ready, // or until the ctx timeout is reached. func (rm *ResourceManager) WaitForAppsToBeReady(namespace string) error { + GinkgoWriter.Printf("Waiting for apps to be ready in namespace %q\n", namespace) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.CreateTimeout) defer cancel() @@ -377,18 +477,29 @@ func (rm *ResourceManager) WaitForAppsToBeReady(namespace string) error { // until the provided context is canceled. func (rm *ResourceManager) WaitForAppsToBeReadyWithCtx(ctx context.Context, namespace string) error { if err := rm.WaitForPodsToBeReady(ctx, namespace); err != nil { + GinkgoWriter.Printf("ERROR occurred during waiting for pods to be ready, error: %s\n", err) + return err } if err := rm.waitForHTTPRoutesToBeReady(ctx, namespace); err != nil { + GinkgoWriter.Printf("ERROR occurred during waiting for HTTPRoutes to be ready, error: %s\n", err) + return err } if err := rm.waitForGRPCRoutesToBeReady(ctx, namespace); err != nil { + GinkgoWriter.Printf("ERROR occurred during waiting for GRPCRoutes to be ready, error: %s\n", err) + return err } - return rm.waitForGatewaysToBeReady(ctx, namespace) + gatewayReadiness := rm.waitForGatewaysToBeReady(ctx, namespace) + if gatewayReadiness != nil { + GinkgoWriter.Printf("ERROR occurred during waiting for Gateways to be ready, error: %s\n", gatewayReadiness) + } + + return gatewayReadiness } // WaitForPodsToBeReady waits for all Pods in the specified namespace to be ready or @@ -495,12 +606,16 @@ func (rm *ResourceManager) waitForGRPCRoutesToBeReady(ctx context.Context, names // GetLBIPAddress gets the IP or Hostname from the Loadbalancer service. func (rm *ResourceManager) GetLBIPAddress(namespace string) (string, error) { + GinkgoWriter.Printf("Getting LoadBalancer IP/Hostname in namespace %q\n", namespace) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.CreateTimeout) defer cancel() var serviceList core.ServiceList var address string if err := rm.K8sClient.List(ctx, &serviceList, client.InNamespace(namespace)); err != nil { + GinkgoWriter.Printf("ERROR occurred during getting list of services in namespace %q, error: %s\n", + namespace, err) + return "", err } var nsName types.NamespacedName @@ -509,7 +624,14 @@ func (rm *ResourceManager) GetLBIPAddress(namespace string) (string, error) { if svc.Spec.Type == core.ServiceTypeLoadBalancer { nsName = types.NamespacedName{Namespace: svc.GetNamespace(), Name: svc.GetName()} if err := rm.waitForLBStatusToBeReady(ctx, nsName); err != nil { - return "", fmt.Errorf("error getting status from LoadBalancer service: %w", err) + lbStatusErr := fmt.Errorf("error getting status from LoadBalancer service: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during waiting for LoadBalancer service in namespace %q to be ready, error: %s\n", + nsName, + err, + ) + + return "", lbStatusErr } } } @@ -518,7 +640,13 @@ func (rm *ResourceManager) GetLBIPAddress(namespace string) (string, error) { var lbService core.Service if err := rm.K8sClient.Get(ctx, nsName, &lbService); err != nil { - return "", fmt.Errorf("error getting LoadBalancer service: %w", err) + getLBStatusErr := fmt.Errorf("error getting LoadBalancer service: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting LoadBalancer service in namespace %q, error: %s\n", + nsName, + err, + ) + + return "", getLBStatusErr } if lbService.Status.LoadBalancer.Ingress[0].IP != "" { address = lbService.Status.LoadBalancer.Ingress[0].IP @@ -551,13 +679,19 @@ func (rm *ResourceManager) waitForLBStatusToBeReady(ctx context.Context, svcNsNa // GetClusterInfo retrieves node info and Kubernetes version from the cluster. func (rm *ResourceManager) GetClusterInfo() (ClusterInfo, error) { + GinkgoWriter.Printf("Getting cluster info\n") ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() var nodes core.NodeList ci := &ClusterInfo{} if err := rm.K8sClient.List(ctx, &nodes); err != nil { - return *ci, fmt.Errorf("error getting nodes: %w", err) + getNodesErr := fmt.Errorf("error getting nodes: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting nodes in cluster, error: %s\n", + getNodesErr, + ) + + return *ci, getNodesErr } ci.NodeCount = len(nodes.Items) @@ -579,7 +713,12 @@ func (rm *ResourceManager) GetClusterInfo() (ClusterInfo, error) { key := types.NamespacedName{Name: "kube-system"} if err := rm.K8sClient.Get(ctx, key, &ns); err != nil { - return *ci, fmt.Errorf("error getting kube-system namespace: %w", err) + getK8sNamespaceErr := fmt.Errorf("error getting kube-system namespace: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting kube-system namespace, error: %s\n", + getK8sNamespaceErr, + ) + + return *ci, getK8sNamespaceErr } ci.ID = string(ns.UID) @@ -589,6 +728,7 @@ func (rm *ResourceManager) GetClusterInfo() (ClusterInfo, error) { // GetPodNames returns the names of all Pods in the specified namespace that match the given labels. func (rm *ResourceManager) GetPodNames(namespace string, labels client.MatchingLabels) ([]string, error) { + GinkgoWriter.Printf("Getting pod names in namespace %q with labels %v\n", namespace, labels) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() @@ -599,7 +739,13 @@ func (rm *ResourceManager) GetPodNames(namespace string, labels client.MatchingL client.InNamespace(namespace), labels, ); err != nil { - return nil, fmt.Errorf("error getting list of Pods: %w", err) + getPodsErr := fmt.Errorf("error getting list of Pods: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting list of Pods in namespace %q, error: %s\n", + namespace, + getPodsErr, + ) + + return nil, getPodsErr } names := make([]string, 0, len(podList.Items)) @@ -607,12 +753,14 @@ func (rm *ResourceManager) GetPodNames(namespace string, labels client.MatchingL for _, pod := range podList.Items { names = append(names, pod.Name) } + GinkgoWriter.Printf("Found pod names in namespace %q: %v\n", namespace, names) return names, nil } // GetPods returns all Pods in the specified namespace that match the given labels. func (rm *ResourceManager) GetPods(namespace string, labels client.MatchingLabels) ([]core.Pod, error) { + GinkgoWriter.Printf("Getting pods in namespace %q with labels %v\n", namespace, labels) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() @@ -623,21 +771,37 @@ func (rm *ResourceManager) GetPods(namespace string, labels client.MatchingLabel client.InNamespace(namespace), labels, ); err != nil { - return nil, fmt.Errorf("error getting list of Pods: %w", err) + getPodsErr := fmt.Errorf("error getting list of Pods: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting list of Pods in namespace %q, error: %s\n", + namespace, + getPodsErr, + ) + + return nil, getPodsErr } + GinkgoWriter.Printf("Found %d pods in namespace %q\n", len(podList.Items), namespace) return podList.Items, nil } // GetPod returns the Pod in the specified namespace with the given name. func (rm *ResourceManager) GetPod(namespace, name string) (*core.Pod, error) { + GinkgoWriter.Printf("Getting pod %q in namespace %q\n", name, namespace) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() var pod core.Pod if err := rm.K8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, &pod); err != nil { - return nil, fmt.Errorf("error getting Pod: %w", err) + getPodErr := fmt.Errorf("error getting Pod: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting Pod %q in namespace %q, error: %s\n", + name, + namespace, + getPodErr, + ) + + return nil, getPodErr } + GinkgoWriter.Printf("Found pod %q in namespace %q\n", name, namespace) return &pod, nil } @@ -651,13 +815,27 @@ func (rm *ResourceManager) GetPodLogs(namespace, name string, opts *core.PodLogO logs, err := req.Stream(ctx) if err != nil { - return "", fmt.Errorf("error getting logs from Pod: %w", err) + getLogsErr := fmt.Errorf("error getting logs from Pod: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting logs from pod %q in namespace %q, error: %s\n", + name, + namespace, + getLogsErr, + ) + + return "", getLogsErr } defer logs.Close() buf := new(bytes.Buffer) if _, err := buf.ReadFrom(logs); err != nil { - return "", fmt.Errorf("error reading logs from Pod: %w", err) + readLogsErr := fmt.Errorf("error reading logs from Pod: %w", err) + GinkgoWriter.Printf("ERROR occurred during reading logs from pod %q in namespace %q, error: %s\n", + name, + namespace, + readLogsErr, + ) + + return "", readLogsErr } return buf.String(), nil @@ -665,6 +843,7 @@ func (rm *ResourceManager) GetPodLogs(namespace, name string, opts *core.PodLogO // GetNGFDeployment returns the NGF Deployment in the specified namespace with the given release name. func (rm *ResourceManager) GetNGFDeployment(namespace, releaseName string) (*apps.Deployment, error) { + GinkgoWriter.Printf("Getting NGF Deployment in namespace %q with release name %q\n", namespace, releaseName) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() @@ -678,13 +857,33 @@ func (rm *ResourceManager) GetNGFDeployment(namespace, releaseName string) (*app "app.kubernetes.io/instance": releaseName, }, ); err != nil { - return nil, fmt.Errorf("error getting list of Deployments: %w", err) + getDeploymentsErr := fmt.Errorf("error getting list of Deployments: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting list of Deployments in namespace %q with release %q, error: %s\n", + namespace, + releaseName, + getDeploymentsErr, + ) + + return nil, getDeploymentsErr } if len(deployments.Items) != 1 { - return nil, fmt.Errorf("expected 1 NGF Deployment, got %d", len(deployments.Items)) + deploymentsAmountErr := fmt.Errorf("expected 1 NGF Deployment, got %d", len(deployments.Items)) + GinkgoWriter.Printf("ERROR occurred during getting NGF Deployment in namespace %q with release name %q, error: %s\n", + namespace, + releaseName, + deploymentsAmountErr, + ) + + return nil, deploymentsAmountErr } + GinkgoWriter.Printf( + "Found NGF Deployment %q in namespace %q with release name %q\n", + deployments.Items[0].Name, + namespace, + releaseName, + ) deployment := deployments.Items[0] return &deployment, nil } @@ -693,6 +892,7 @@ func (rm *ResourceManager) getGatewayClassNginxProxy( namespace, releaseName string, ) (*ngfAPIv1alpha2.NginxProxy, error) { + GinkgoWriter.Printf("Getting NginxProxy in namespace %q with release name %q\n", namespace, releaseName) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() @@ -700,14 +900,26 @@ func (rm *ResourceManager) getGatewayClassNginxProxy( proxyName := releaseName + "-proxy-config" if err := rm.K8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: proxyName}, &proxy); err != nil { + GinkgoWriter.Printf("ERROR occurred during getting NginxProxy %q in namespace %q, error: %s\n", + proxyName, + namespace, + err, + ) + return nil, err } + GinkgoWriter.Printf("Successfully found NginxProxy %q in namespace %q\n", proxyName, namespace) return &proxy, nil } // ScaleNginxDeployment scales the Nginx Deployment to the specified number of replicas. func (rm *ResourceManager) ScaleNginxDeployment(namespace, releaseName string, replicas int32) error { + GinkgoWriter.Printf("Scaling Nginx Deployment in namespace %q with release name %q to %d replicas\n", + namespace, + releaseName, + replicas, + ) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.UpdateTimeout) defer cancel() @@ -715,20 +927,41 @@ func (rm *ResourceManager) ScaleNginxDeployment(namespace, releaseName string, r // may need refactoring. proxy, err := rm.getGatewayClassNginxProxy(namespace, releaseName) if err != nil { - return fmt.Errorf("error getting NginxProxy: %w", err) + getNginxProxyErr := fmt.Errorf("error getting NginxProxy: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting NginxProxy in namespace %q with release name %q, error: %s\n", + namespace, + releaseName, + getNginxProxyErr, + ) + + return getNginxProxyErr } proxy.Spec.Kubernetes.Deployment.Replicas = &replicas if err = rm.K8sClient.Update(ctx, proxy); err != nil { - return fmt.Errorf("error updating NginxProxy: %w", err) + updateNginxProxyErr := fmt.Errorf("error updating NginxProxy: %w", err) + GinkgoWriter.Printf("ERROR occurred during updating NginxProxy in namespace %q with release name %q, error: %s\n", + namespace, + releaseName, + updateNginxProxyErr, + ) + + return updateNginxProxyErr } + GinkgoWriter.Printf("Successfully scaled Nginx Deployment in namespace %q with release name %q to %d replicas\n", + namespace, + releaseName, + replicas, + ) + return nil } // GetEvents returns all Events in the specified namespace. func (rm *ResourceManager) GetEvents(namespace string) (*core.EventList, error) { + GinkgoWriter.Printf("Getting Events in namespace %q\n", namespace) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.GetTimeout) defer cancel() @@ -738,26 +971,49 @@ func (rm *ResourceManager) GetEvents(namespace string) (*core.EventList, error) &eventList, client.InNamespace(namespace), ); err != nil { - return &core.EventList{}, fmt.Errorf("error getting list of Events: %w", err) + getEventsListErr := fmt.Errorf("error getting list of Events: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting Events in namespace %q, error: %s\n", + namespace, + getEventsListErr, + ) + + return &core.EventList{}, getEventsListErr } + GinkgoWriter.Printf("Successfully found %d Events in namespace %q\n", len(eventList.Items), namespace) return &eventList, nil } // ScaleDeployment scales the Deployment to the specified number of replicas. func (rm *ResourceManager) ScaleDeployment(namespace, name string, replicas int32) error { + GinkgoWriter.Printf("Scaling Deployment %q in namespace %q to %d replicas\n", name, namespace, replicas) ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.UpdateTimeout) defer cancel() var deployment apps.Deployment if err := rm.K8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, &deployment); err != nil { - return fmt.Errorf("error getting Deployment: %w", err) + getDeploymentErr := fmt.Errorf("error getting Deployment: %w", err) + GinkgoWriter.Printf("ERROR occurred during getting Deployment in namespace %q with name %q, error: %s\n", + namespace, + name, + getDeploymentErr, + ) + + return getDeploymentErr } deployment.Spec.Replicas = &replicas if err := rm.K8sClient.Update(ctx, &deployment); err != nil { - return fmt.Errorf("error updating Deployment: %w", err) + updateDeploymentErr := fmt.Errorf("error updating Deployment: %w", err) + GinkgoWriter.Printf("ERROR occurred during updating Deployment in namespace %q with name %q, error: %s\n", + namespace, + name, + updateDeploymentErr, + ) + + return updateDeploymentErr } + GinkgoWriter.Printf("Successfully scaled Deployment %q in namespace %q to %d replicas\n", name, namespace, replicas) return nil } @@ -769,6 +1025,7 @@ func GetReadyNGFPodNames( releaseName string, timeout time.Duration, ) ([]string, error) { + GinkgoWriter.Printf("Getting ready NGF Pod names in namespace %q with release name %q\n", namespace, releaseName) ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() @@ -796,8 +1053,22 @@ func GetReadyNGFPodNames( }, ) if err != nil { - return nil, fmt.Errorf("timed out waiting for NGF Pods to be ready: %w", err) + waitingPodsErr := fmt.Errorf("timed out waiting for NGF Pods to be ready: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during waiting for NGF Pods to be ready in namespace %q with release name %q, error: %s\n", + namespace, + releaseName, + waitingPodsErr, + ) + + return nil, waitingPodsErr } + GinkgoWriter.Printf( + "Successfully found ready NGF Pod names in namespace %q with release name %q: %v\n", + namespace, + releaseName, + ngfPodNames, + ) return ngfPodNames, nil } @@ -808,6 +1079,7 @@ func GetReadyNginxPodNames( namespace string, timeout time.Duration, ) ([]string, error) { + GinkgoWriter.Printf("Getting ready NGINX Pod names in namespace %q\n", namespace) ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() @@ -833,8 +1105,19 @@ func GetReadyNginxPodNames( }, ) if err != nil { - return nil, fmt.Errorf("timed out waiting for NGINX Pods to be ready: %w", err) + waitingPodsErr := fmt.Errorf("timed out waiting for NGINX Pods to be ready: %w", err) + GinkgoWriter.Printf("ERROR occurred during waiting for NGINX Pods to be ready in namespace %q, error: %s\n", + namespace, + waitingPodsErr, + ) + + return nil, waitingPodsErr } + GinkgoWriter.Printf( + "Successfully found ready NGINX Pod names in namespace %q: %v\n", + namespace, + nginxPodNames, + ) return nginxPodNames, nil } @@ -848,6 +1131,7 @@ func getReadyPodNames(podList core.PodList) []string { } } } + GinkgoWriter.Printf("Found %d ready pod names: %v\n", len(names), names) return names } @@ -862,6 +1146,7 @@ func countNumberOfReadyParents(parents []v1.RouteParentStatus) int { } } } + GinkgoWriter.Printf("Found %d ready parent(s)\n", readyCount) return readyCount } @@ -869,6 +1154,7 @@ func countNumberOfReadyParents(parents []v1.RouteParentStatus) int { // WaitForPodsToBeReadyWithCount waits for all Pods in the specified namespace to be ready or // until the provided context is canceled. func (rm *ResourceManager) WaitForPodsToBeReadyWithCount(ctx context.Context, namespace string, count int) error { + GinkgoWriter.Printf("Waiting for %d pods to be ready in namespace %q\n", count, namespace) return wait.PollUntilContextCancel( ctx, 500*time.Millisecond, @@ -887,6 +1173,7 @@ func (rm *ResourceManager) WaitForPodsToBeReadyWithCount(ctx context.Context, na } } } + GinkgoWriter.Printf("Found %d/%d ready pods in namespace %q\n", podsReady, count, namespace) return podsReady == count, nil }, @@ -900,6 +1187,11 @@ func (rm *ResourceManager) WaitForGatewayObservedGeneration( name string, generation int, ) error { + GinkgoWriter.Printf("Waiting for Gateway %q in namespace %q to have ObservedGeneration %d\n", + name, + namespace, + generation, + ) return wait.PollUntilContextCancel( ctx, 500*time.Millisecond, @@ -925,6 +1217,7 @@ func (rm *ResourceManager) WaitForGatewayObservedGeneration( // GetNginxConfig uses crossplane to get the nginx configuration and convert it to JSON. // If the crossplane image is loaded locally on the node, crossplaneImageRepo can be empty. func (rm *ResourceManager) GetNginxConfig(nginxPodName, namespace, crossplaneImageRepo string) (*Payload, error) { + GinkgoWriter.Printf("Getting NGINX config from pod %q in namespace %q\n", nginxPodName, namespace) if err := injectCrossplaneContainer( rm.ClientGoClient, rm.TimeoutConfig.UpdateTimeout, @@ -932,11 +1225,15 @@ func (rm *ResourceManager) GetNginxConfig(nginxPodName, namespace, crossplaneIma namespace, crossplaneImageRepo, ); err != nil { + GinkgoWriter.Printf("ERROR occurred during injecting crossplane container, error: %s\n", err) + return nil, err } exec, err := createCrossplaneExecutor(rm.ClientGoClient, rm.K8sConfig, nginxPodName, namespace) if err != nil { + GinkgoWriter.Printf("ERROR occurred during creating crossplane executor, error: %s\n", err) + return nil, err } @@ -965,13 +1262,27 @@ func (rm *ResourceManager) GetNginxConfig(nginxPodName, namespace, crossplaneIma return true, nil }, ); err != nil { - return nil, fmt.Errorf("could not connect to ephemeral container: %w", err) + containerErr := fmt.Errorf("could not connect to ephemeral container: %w", err) + GinkgoWriter.Printf("ERROR occurred during waiting for NGINX Pods to be ready in namespace %q, error: %s\n", + namespace, + containerErr, + ) + + return nil, containerErr } conf := &Payload{} if err := json.Unmarshal(buf.Bytes(), conf); err != nil { - return nil, fmt.Errorf("error unmarshaling nginx config: %w", err) + unmarshalErr := fmt.Errorf("error unmarshaling nginx config: %w", err) + GinkgoWriter.Printf("ERROR occurred during unmarshaling nginx config from pod %q in namespace %q, error: %s\n", + nginxPodName, + namespace, + unmarshalErr, + ) + + return nil, unmarshalErr } + GinkgoWriter.Printf("Successfully got NGINX config from pod %q in namespace %q\n", nginxPodName, namespace) return conf, nil } diff --git a/tests/suite/advanced_routing_test.go b/tests/suite/advanced_routing_test.go index 465654246f..1163089cc5 100644 --- a/tests/suite/advanced_routing_test.go +++ b/tests/suite/advanced_routing_test.go @@ -116,17 +116,23 @@ func expectRequestToRespondFromExpectedServer( appURL, address, expServerName string, headers, queryParams map[string]string, ) error { + GinkgoWriter.Printf("Expecting request to respond from the server %q\n", expServerName) status, body, err := framework.Get(appURL, address, timeoutConfig.RequestTimeout, headers, queryParams) if err != nil { return err } if status != http.StatusOK { - return errors.New("http status was not 200") + statusErr := errors.New("http status was not 200") + GinkgoWriter.Printf("ERROR: %v\n", statusErr) + + return statusErr } actualServerName, err := extractServerName(body) if err != nil { + GinkgoWriter.Printf("ERROR extracting server name from response body: %v\n", err) + return err } diff --git a/tests/suite/client_settings_test.go b/tests/suite/client_settings_test.go index 557146b789..53762e58bc 100644 --- a/tests/suite/client_settings_test.go +++ b/tests/suite/client_settings_test.go @@ -404,7 +404,10 @@ func waitForClientSettingsAncestorStatus( } if len(pol.Status.Ancestors) != 1 { - return false, fmt.Errorf("policy has %d ancestors, expected 1", len(pol.Status.Ancestors)) + ancestorsAmountErr := fmt.Errorf("policy has %d ancestors, expected 1", len(pol.Status.Ancestors)) + GinkgoWriter.Printf("ERROR: %v\n", ancestorsAmountErr) + + return false, ancestorsAmountErr } ancestor := pol.Status.Ancestors[0] @@ -425,20 +428,33 @@ func ancestorStatusMustHaveAcceptedCondition( condStatus metav1.ConditionStatus, condReason v1alpha2.PolicyConditionReason, ) error { + GinkgoWriter.Printf("Checking if ancestor status has accepted condition\n") if len(status.Conditions) != 1 { - return fmt.Errorf("expected 1 condition in status, got %d", len(status.Conditions)) + tooManyConditionsErr := fmt.Errorf("expected 1 condition in status, got %d", len(status.Conditions)) + GinkgoWriter.Printf("ERROR: %v\n", tooManyConditionsErr) + + return tooManyConditionsErr } if status.Conditions[0].Type != string(v1alpha2.RouteConditionAccepted) { - return fmt.Errorf("expected condition type to be Accepted, got %s", status.Conditions[0].Type) + wrongTypeErr := fmt.Errorf("expected condition type to be Accepted, got %s", status.Conditions[0].Type) + GinkgoWriter.Printf("ERROR: %v\n", wrongTypeErr) + + return wrongTypeErr } if status.Conditions[0].Status != condStatus { - return fmt.Errorf("expected condition status to be %s, got %s", condStatus, status.Conditions[0].Status) + wrongStatusErr := fmt.Errorf("expected condition status to be %s, got %s", condStatus, status.Conditions[0].Status) + GinkgoWriter.Printf("ERROR: %v\n", wrongStatusErr) + + return wrongStatusErr } if status.Conditions[0].Reason != string(condReason) { - return fmt.Errorf("expected condition reason to be %s, got %s", condReason, status.Conditions[0].Reason) + wrongReasonErr := fmt.Errorf("expected condition reason to be %s, got %s", condReason, status.Conditions[0].Reason) + GinkgoWriter.Printf("ERROR: %v\n", wrongReasonErr) + + return wrongReasonErr } return nil @@ -450,46 +466,79 @@ func ancestorMustEqualTargetRef( namespace string, ) error { if ancestor.ControllerName != ngfControllerName { - return fmt.Errorf( + controllerNameErr := fmt.Errorf( "expected ancestor controller name to be %s, got %s", ngfControllerName, ancestor.ControllerName, ) + GinkgoWriter.Printf("ERROR: %v\n", controllerNameErr) + + return controllerNameErr } if ancestor.AncestorRef.Namespace == nil { - return fmt.Errorf("expected ancestor namespace to be %s, got nil", namespace) + nsErr := fmt.Errorf("expected ancestor namespace to be %s, got nil", namespace) + GinkgoWriter.Printf("ERROR: %v\n", nsErr) + + return nsErr } if string(*ancestor.AncestorRef.Namespace) != namespace { - return fmt.Errorf( + wrongNSErr := fmt.Errorf( "expected ancestor namespace to be %s, got %s", namespace, string(*ancestor.AncestorRef.Namespace), ) + GinkgoWriter.Printf("ERROR: %v\n", wrongNSErr) + + return wrongNSErr } ancestorRef := ancestor.AncestorRef if ancestorRef.Name != targetRef.Name { - return fmt.Errorf("expected ancestorRef to have name %s, got %s", targetRef.Name, ancestorRef.Name) + wrongNameErr := fmt.Errorf("expected ancestorRef to have name %s, got %s", targetRef.Name, ancestorRef.Name) + GinkgoWriter.Printf("ERROR: %v\n", wrongNameErr) + + return wrongNameErr } if ancestorRef.Group == nil { - return fmt.Errorf("expected ancestorRef to have group %s, got nil", targetRef.Group) + emptyGroupErr := fmt.Errorf("expected ancestorRef to have group %s, got nil", targetRef.Group) + GinkgoWriter.Printf("ERROR: %v\n", emptyGroupErr) + + return emptyGroupErr } if *ancestorRef.Group != targetRef.Group { - return fmt.Errorf("expected ancestorRef to have group %s, got %s", targetRef.Group, string(*ancestorRef.Group)) + wrongGroupErr := fmt.Errorf( + "expected ancestorRef to have group %s, got %s", + targetRef.Group, + string(*ancestorRef.Group), + ) + GinkgoWriter.Printf("ERROR: %v\n", wrongGroupErr) + + return wrongGroupErr } if ancestorRef.Kind == nil { - return fmt.Errorf("expected ancestorRef to have kind %s, got nil", targetRef.Kind) + noKindErr := fmt.Errorf("expected ancestorRef to have kind %s, got nil", targetRef.Kind) + GinkgoWriter.Printf("ERROR: %v\n", noKindErr) + + return noKindErr } if *ancestorRef.Kind != targetRef.Kind { - return fmt.Errorf("expected ancestorRef to have kind %s, got %s", targetRef.Kind, string(*ancestorRef.Kind)) + wrongKindErr := fmt.Errorf( + "expected ancestorRef to have kind %s, got %s", + targetRef.Kind, + string(*ancestorRef.Kind), + ) + GinkgoWriter.Printf("ERROR: %v\n", wrongKindErr) + + return wrongKindErr } + GinkgoWriter.Printf("Success: AncestorRef %q matches TargetRef\n", ancestorRef.Name) return nil } diff --git a/tests/suite/graceful_recovery_test.go b/tests/suite/graceful_recovery_test.go index ca50c2f6c3..01cfed2652 100644 --- a/tests/suite/graceful_recovery_test.go +++ b/tests/suite/graceful_recovery_test.go @@ -531,6 +531,14 @@ func expectRequestToSucceed(appURL, address string, responseBodyMessage string) return err } +// The function is expecting the request to fail (hence the name) because NGINX is not there to route the request. +// The purpose of the graceful recovery test is to simulate various failure scenarios including NGINX +// container restarts, NGF pod restarts, and Kubernetes node restarts to show the system can recover +// after these real world scenarios and resume serving application traffic after recovery. +// In this case, we verify that our requests fail and then that eventually are successful again - verifying that +// NGINX went down and came back up again. +// We only want an error returned from this particular function if it does not appear that NGINX has +// stopped serving traffic. func expectRequestToFail(appURL, address string) error { status, body, err := framework.Get(appURL, address, timeoutConfig.RequestTimeout, nil, nil) if status != 0 { diff --git a/tests/suite/nginxgateway_test.go b/tests/suite/nginxgateway_test.go index 9c3497d891..3518c2ed69 100644 --- a/tests/suite/nginxgateway_test.go +++ b/tests/suite/nginxgateway_test.go @@ -35,7 +35,14 @@ var _ = Describe("NginxGateway", Ordered, Label("functional", "nginxGateway"), f var nginxGateway ngfAPI.NginxGateway if err := k8sClient.Get(ctx, nsname, &nginxGateway); err != nil { - return nginxGateway, fmt.Errorf("failed to get nginxGateway: %w", err) + gatewayErr := fmt.Errorf("failed to get nginxGateway: %w", err) + GinkgoWriter.Printf( + "ERROR occurred during getting NGINX Gateway in namespace %q: %v\n", + nsname.Namespace, + gatewayErr, + ) + + return nginxGateway, gatewayErr } return nginxGateway, nil @@ -43,14 +50,20 @@ var _ = Describe("NginxGateway", Ordered, Label("functional", "nginxGateway"), f verifyNginxGatewayConditions := func(ng ngfAPI.NginxGateway) error { if ng.Status.Conditions == nil { - return errors.New("nginxGateway has no conditions") + noConditionsErr := errors.New("nginxGateway has no conditions") + GinkgoWriter.Printf("ERROR: %v\n", noConditionsErr) + + return noConditionsErr } if len(ng.Status.Conditions) != 1 { - return fmt.Errorf( + tooManyConditionsErr := fmt.Errorf( "expected nginxGateway to have only one condition, instead has %d conditions", len(ng.Status.Conditions), ) + GinkgoWriter.Printf("ERROR: %v\n", tooManyConditionsErr) + + return tooManyConditionsErr } return nil @@ -72,22 +85,30 @@ var _ = Describe("NginxGateway", Ordered, Label("functional", "nginxGateway"), f condition := ng.Status.Conditions[0] if condition.Type != "Valid" { - return fmt.Errorf( + invalidConditionTypeErr := fmt.Errorf( "expected nginxGateway condition type to be Valid, instead has type %s", condition.Type, ) + GinkgoWriter.Printf("ERROR: %v\n", invalidConditionTypeErr) + + return invalidConditionTypeErr } if condition.Reason != "Valid" { - return fmt.Errorf("expected nginxGateway reason to be Valid, instead is %s", condition.Reason) + invalidReasonErr := fmt.Errorf("expected nginxGateway reason to be Valid, instead is %s", condition.Reason) + GinkgoWriter.Printf("ERROR: %v\n", invalidReasonErr) + + return invalidReasonErr } if condition.ObservedGeneration != expObservedGen { - return fmt.Errorf( + observedGenerationErr := fmt.Errorf( "expected nginxGateway observed generation to be %d, instead is %d", expObservedGen, condition.ObservedGeneration, ) + GinkgoWriter.Printf("ERROR: %v\n", observedGenerationErr) + return observedGenerationErr } return nil @@ -105,7 +126,10 @@ var _ = Describe("NginxGateway", Ordered, Label("functional", "nginxGateway"), f } if len(podNames) != 1 { - return "", fmt.Errorf("expected 1 pod name, got %d", len(podNames)) + tooManyPodsErr := fmt.Errorf("expected 1 pod name, got %d", len(podNames)) + GinkgoWriter.Printf("ERROR: %v\n", tooManyPodsErr) + + return "", tooManyPodsErr } return podNames[0], nil diff --git a/tests/suite/scale_test.go b/tests/suite/scale_test.go index dfe9a24978..526b27049c 100644 --- a/tests/suite/scale_test.go +++ b/tests/suite/scale_test.go @@ -450,7 +450,12 @@ The logs are attached only if there are errors. startCheck := time.Now() Eventually( - framework.CreateResponseChecker(url, address, timeoutConfig.RequestTimeout), + framework.CreateResponseChecker( + url, + address, + timeoutConfig.RequestTimeout, + framework.WithLoggingDisabled(), // disable logging to avoid huge logs + ), ).WithTimeout(6 * timeoutConfig.RequestTimeout).WithPolling(100 * time.Millisecond).Should(Succeed()) ttr := time.Since(startCheck) diff --git a/tests/suite/snippets_filter_test.go b/tests/suite/snippets_filter_test.go index 7c91c93565..78e0a592e8 100644 --- a/tests/suite/snippets_filter_test.go +++ b/tests/suite/snippets_filter_test.go @@ -271,29 +271,46 @@ func checkHTTPRouteToHaveGatewayNotProgrammedCond(httpRouteNsName types.Namespac var err error if err = k8sClient.Get(ctx, httpRouteNsName, &hr); err != nil { + GinkgoWriter.Printf("ERROR: failed to get HTTPRoute: %v\n", err) + return err } if len(hr.Status.Parents) != 1 { - return fmt.Errorf("httproute has %d parent statuses, expected 1", len(hr.Status.Parents)) + tooManyParentStatusesErr := fmt.Errorf("httproute has %d parent statuses, expected 1", len(hr.Status.Parents)) + GinkgoWriter.Printf("ERROR: %v\n", tooManyParentStatusesErr) + + return tooManyParentStatusesErr } parent := hr.Status.Parents[0] if parent.Conditions == nil { - return fmt.Errorf("expected parent conditions to not be nil") + nilConditionErr := fmt.Errorf("expected parent conditions to not be nil") + GinkgoWriter.Printf("ERROR: %v\n", nilConditionErr) + + return nilConditionErr } cond := parent.Conditions[1] if cond.Type != string(v1.GatewayConditionAccepted) { - return fmt.Errorf("expected condition type to be Accepted, got %s", cond.Type) + wrongTypeErr := fmt.Errorf("expected condition type to be Accepted, got %s", cond.Type) + GinkgoWriter.Printf("ERROR: %v\n", wrongTypeErr) + + return wrongTypeErr } if cond.Status != metav1.ConditionFalse { - return fmt.Errorf("expected condition status to be False, got %s", cond.Status) + wrongStatusErr := fmt.Errorf("expected condition status to be False, got %s", cond.Status) + GinkgoWriter.Printf("ERROR: %v\n", wrongStatusErr) + + return wrongStatusErr } if cond.Reason != string(conditions.RouteReasonGatewayNotProgrammed) { - return fmt.Errorf("expected condition reason to be GatewayNotProgrammed, got %s", cond.Reason) + wrongReasonErr := fmt.Errorf("expected condition reason to be GatewayNotProgrammed, got %s", cond.Reason) + GinkgoWriter.Printf("ERROR: %v\n", wrongReasonErr) + + return wrongReasonErr } return nil @@ -312,33 +329,50 @@ func checkForSnippetsFilterToBeAccepted(snippetsFilterNsNames types.NamespacedNa var err error if err = k8sClient.Get(ctx, snippetsFilterNsNames, &sf); err != nil { + GinkgoWriter.Printf("ERROR: failed to get SnippetsFilter: %v\n", err) + return err } if len(sf.Status.Controllers) != 1 { - return fmt.Errorf("snippetsFilter has %d controller statuses, expected 1", len(sf.Status.Controllers)) + tooManyStatusesErr := fmt.Errorf("snippetsFilter has %d controller statuses, expected 1", len(sf.Status.Controllers)) + GinkgoWriter.Printf("ERROR: %v\n", tooManyStatusesErr) + + return tooManyStatusesErr } status := sf.Status.Controllers[0] if status.ControllerName != ngfControllerName { - return fmt.Errorf("expected controller name to be %s, got %s", ngfControllerName, status.ControllerName) + wrongNameErr := fmt.Errorf("expected controller name to be %s, got %s", ngfControllerName, status.ControllerName) + GinkgoWriter.Printf("ERROR: %v\n", wrongNameErr) + + return wrongNameErr } condition := status.Conditions[0] if condition.Type != string(ngfAPI.SnippetsFilterConditionTypeAccepted) { - return fmt.Errorf("expected condition type to be Accepted, got %s", condition.Type) + wrongTypeErr := fmt.Errorf("expected condition type to be Accepted, got %s", condition.Type) + GinkgoWriter.Printf("ERROR: %v\n", wrongTypeErr) + + return wrongTypeErr } if status.Conditions[0].Status != metav1.ConditionTrue { - return fmt.Errorf("expected condition status to be %s, got %s", metav1.ConditionTrue, condition.Status) + wrongStatusErr := fmt.Errorf("expected condition status to be %s, got %s", metav1.ConditionTrue, condition.Status) + GinkgoWriter.Printf("ERROR: %v\n", wrongStatusErr) + + return wrongStatusErr } if status.Conditions[0].Reason != string(ngfAPI.SnippetsFilterConditionReasonAccepted) { - return fmt.Errorf( + wrongReasonErr := fmt.Errorf( "expected condition reason to be %s, got %s", ngfAPI.SnippetsFilterConditionReasonAccepted, condition.Reason, ) + GinkgoWriter.Printf("ERROR: %v\n", wrongReasonErr) + + return wrongReasonErr } return nil diff --git a/tests/suite/system_suite_test.go b/tests/suite/system_suite_test.go index f404f13e55..71d610bf5a 100644 --- a/tests/suite/system_suite_test.go +++ b/tests/suite/system_suite_test.go @@ -193,6 +193,7 @@ func setUpPortForward(nginxPodName, nginxNamespace string) { var err error if *serviceType != "LoadBalancer" { + GinkgoWriter.Printf("Service Type: %s\n", *serviceType) ports := []string{fmt.Sprintf("%d:80", ngfHTTPForwardedPort), fmt.Sprintf("%d:443", ngfHTTPSForwardedPort)} portForwardStopCh = make(chan struct{}) err = framework.PortForward(resourceManager.K8sConfig, nginxNamespace, nginxPodName, ports, portForwardStopCh) @@ -200,6 +201,7 @@ func setUpPortForward(nginxPodName, nginxNamespace string) { portFwdPort = ngfHTTPForwardedPort portFwdHTTPSPort = ngfHTTPSForwardedPort } else { + GinkgoWriter.Printf("Service Type: LoadBalancer\n") address, err = resourceManager.GetLBIPAddress(nginxNamespace) } Expect(err).ToNot(HaveOccurred()) @@ -208,6 +210,7 @@ func setUpPortForward(nginxPodName, nginxNamespace string) { // cleanUpPortForward closes the port forward channel and needs to be called before deleting any gateways or else // the logs will be flooded with port forward errors. func cleanUpPortForward() { + GinkgoWriter.Printf("Cleaning up port forward\n") if portFwdPort != 0 { close(portForwardStopCh) portFwdPort = 0 @@ -216,6 +219,7 @@ func cleanUpPortForward() { } func createNGFInstallConfig(cfg setupConfig, extraInstallArgs ...string) framework.InstallationConfig { + GinkgoWriter.Printf("Creating NGF installation config\n") installCfg := framework.InstallationConfig{ ReleaseName: cfg.releaseName, Namespace: ngfNamespace, @@ -229,6 +233,7 @@ func createNGFInstallConfig(cfg setupConfig, extraInstallArgs ...string) framewo switch { // if we aren't installing from the public charts, then set the custom images case !strings.HasPrefix(cfg.chartPath, "oci://"): + GinkgoWriter.Printf("Chart path doesn't have prefix 'oci://'\n") installCfg.NgfImageRepository = *ngfImageRepository installCfg.NginxImageRepository = *nginxImageRepository if *plusEnabled && cfg.nfr { @@ -237,6 +242,7 @@ func createNGFInstallConfig(cfg setupConfig, extraInstallArgs ...string) framewo installCfg.ImageTag = *imageTag installCfg.ImagePullPolicy = *imagePullPolicy case version == "edge": + GinkgoWriter.Printf("Using NGF image repository %q with version 'edge'\n", *ngfImageRepository) chartVersion = "0.0.0-edge" installCfg.ChartVersion = chartVersion if *plusEnabled && cfg.nfr { diff --git a/tests/suite/tracing_test.go b/tests/suite/tracing_test.go index 2837a01cb3..bdc1abda54 100644 --- a/tests/suite/tracing_test.go +++ b/tests/suite/tracing_test.go @@ -127,10 +127,18 @@ var _ = Describe("Tracing", FlakeAttempts(2), Ordered, Label("functional", "trac }) sendRequests := func(url string, count int) { + GinkgoWriter.Printf("Sending %d requests to %s\n", count, url) for range count { Eventually( func() error { - status, _, err := framework.Get(url, address, timeoutConfig.RequestTimeout, nil, nil) + status, _, err := framework.Get( + url, + address, + timeoutConfig.RequestTimeout, + nil, + nil, + framework.WithLoggingDisabled(), + ) if err != nil { return err } @@ -227,30 +235,46 @@ var _ = Describe("Tracing", FlakeAttempts(2), Ordered, Label("functional", "trac }) func verifyGatewayClassResolvedRefs() error { + GinkgoWriter.Println("Verifying GatewayClass ResolvedRefs condition is True\n") ctx, cancel := context.WithTimeout(context.Background(), timeoutConfig.GetTimeout) defer cancel() var gc gatewayv1.GatewayClass if err := k8sClient.Get(ctx, types.NamespacedName{Name: gatewayClassName}, &gc); err != nil { + GinkgoWriter.Printf("ERROR getting GatewayClass %s: %v\n", gatewayClassName, err) + return err } for _, cond := range gc.Status.Conditions { + GinkgoWriter.Printf( + "GatewayClass condition: Type=%s, Status=%s. Expected condition: Type=%s, Status=%s\n", + cond.Type, + cond.Status, + string(conditions.GatewayClassResolvedRefs), + metav1.ConditionTrue, + ) if cond.Type == string(conditions.GatewayClassResolvedRefs) && cond.Status == metav1.ConditionTrue { + GinkgoWriter.Println("Success: GatewayClass ResolvedRefs condition is True\n") return nil } } + statusErr := errors.New("ResolvedRefs status not set to true on GatewayClass") + GinkgoWriter.Printf("ERROR: %v\n", statusErr) - return errors.New("ResolvedRefs status not set to true on GatewayClass") + return statusErr } func verifyPolicyStatus() error { + GinkgoWriter.Println("Verifying ObservabilityPolicy status\n") ctx, cancel := context.WithTimeout(context.Background(), timeoutConfig.GetTimeout) defer cancel() var pol ngfAPIv1alpha2.ObservabilityPolicy key := types.NamespacedName{Name: "test-observability-policy", Namespace: "helloworld"} if err := k8sClient.Get(ctx, key, &pol); err != nil { + GinkgoWriter.Printf("ERROR getting ObservabilityPolicy %q in namespace %q: %v\n", key.Name, key.Namespace, err) + return err } @@ -264,7 +288,14 @@ func verifyPolicyStatus() error { } if count != len(pol.Status.Ancestors) { - return fmt.Errorf("Policy not accepted; expected %d accepted conditions, got %d", len(pol.Status.Ancestors), count) + acceptedConditionsErr := fmt.Errorf( + "Policy not accepted; expected %d accepted conditions, got %d", + len(pol.Status.Ancestors), + count, + ) + GinkgoWriter.Printf("ERROR: %v\n", acceptedConditionsErr) + + return acceptedConditionsErr } return nil diff --git a/tests/suite/upstream_settings_test.go b/tests/suite/upstream_settings_test.go index 2f5c2bb408..cd70604ef0 100644 --- a/tests/suite/upstream_settings_test.go +++ b/tests/suite/upstream_settings_test.go @@ -425,11 +425,19 @@ func usPolicyHasNoAncestors(usPolicyNsName types.NamespacedName) bool { var usPolicy ngfAPI.UpstreamSettingsPolicy if err := k8sClient.Get(ctx, usPolicyNsName, &usPolicy); err != nil { - GinkgoWriter.Printf("Failed to get UpstreamSettingsPolicy %q: %s", usPolicyNsName, err.Error()) + GinkgoWriter.Printf("ERROR: Failed to get UpstreamSettingsPolicy %q: %s", usPolicyNsName, err.Error()) return false } + isZeroAncestors := len(usPolicy.Status.Ancestors) == 0 + if !isZeroAncestors { + GinkgoWriter.Printf( + "UpstreamSettingsPolicy %q has %d ancestors in status\n", + usPolicyNsName, + len(usPolicy.Status.Ancestors), + ) + } - return len(usPolicy.Status.Ancestors) == 0 + return isZeroAncestors } func waitForUSPolicyStatus( @@ -457,6 +465,8 @@ func waitForUSPolicyStatus( var err error if err := k8sClient.Get(ctx, usPolicyNsName, &usPolicy); err != nil { + GinkgoWriter.Printf("ERROR: Failed to get UpstreamSettingsPolicy %q: %s", usPolicyNsName, err.Error()) + return false, err } @@ -467,13 +477,18 @@ func waitForUSPolicyStatus( } if len(usPolicy.Status.Ancestors) != 1 { - return false, fmt.Errorf("policy has %d ancestors, expected 1", len(usPolicy.Status.Ancestors)) + tooManyAncestorsErr := fmt.Errorf("policy has %d ancestors, expected 1", len(usPolicy.Status.Ancestors)) + GinkgoWriter.Printf("ERROR: %v\n", tooManyAncestorsErr) + + return false, tooManyAncestorsErr } ancestors := usPolicy.Status.Ancestors for _, ancestor := range ancestors { if err := ancestorMustEqualGatewayRef(ancestor, gatewayName, usPolicy.Namespace); err != nil { + GinkgoWriter.Printf("ERROR: %v\n", err) + return false, err }