From 806fde6c9b542b35c4e306ef25ccdbadb0321779 Mon Sep 17 00:00:00 2001 From: Steve Wagner Date: Fri, 14 Feb 2025 10:26:23 -0800 Subject: [PATCH] Renames the label designating Nodes that are running in the control plane This accommodates the change made in v1.20 which became the standard in 1.24. This will require users to have Kubernetes v1.24 or higher; while NLK will run on lower versions, the control plane Nodes will not be excluded. --- README.md | 2 +- internal/communication/roundtripper_test.go | 34 ++++++++++++++++----- internal/observation/watcher.go | 15 ++++----- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b025f67..226a973 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ The NGINX Loadbalancer for Kubernetes, or _NLK_, is a Kubernetes controller that ### What you will need -- [ ] A Kubernetes cluster running on-premise. +- [ ] A On-Premise Kubernetes cluster running version 1.24 or higher. - [ ] One or more NGINX Plus hosts running outside your Kubernetes cluster (NGINX Plus hosts must have the ability to route traffic to the cluster). There is a more detailed [Installation Reference](docs/README.md) available in the `docs/` directory. diff --git a/internal/communication/roundtripper_test.go b/internal/communication/roundtripper_test.go index f46fb71..71620c3 100644 --- a/internal/communication/roundtripper_test.go +++ b/internal/communication/roundtripper_test.go @@ -8,10 +8,13 @@ package communication import ( "bytes" "context" - "github.com/nginxinc/kubernetes-nginx-ingress/internal/configuration" - "k8s.io/client-go/kubernetes/fake" + "fmt" netHttp "net/http" + "net/http/httptest" "testing" + + "github.com/nginxinc/kubernetes-nginx-ingress/internal/configuration" + "k8s.io/client-go/kubernetes/fake" ) func TestNewRoundTripper(t *testing.T) { @@ -47,32 +50,49 @@ func TestNewRoundTripper(t *testing.T) { } func TestRoundTripperRoundTrip(t *testing.T) { + // Create a mock HTTP server + mockServer := httptest.NewServer(netHttp.HandlerFunc(func(w netHttp.ResponseWriter, r *netHttp.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("x-mock-header", "test-value") + w.WriteHeader(netHttp.StatusOK) + fmt.Fprintln(w, `{"message": "mock response"}`) + })) + defer mockServer.Close() + + // Initialize dependencies k8sClient := fake.NewSimpleClientset() settings, err := configuration.NewSettings(context.Background(), k8sClient) + if err != nil { + t.Fatalf("Unexpected error creating settings: %v", err) + } + headers := NewHeaders() transport := NewTransport(NewTlsConfig(settings)) roundTripper := NewRoundTripper(headers, transport) - request, err := NewRequest("GET", "http://example.com", nil) + // Use the mock server URL + request, err := NewRequest("GET", mockServer.URL, nil) if err != nil { - t.Fatalf(`Unexpected error: %v`, err) + t.Fatalf("Unexpected error: %v", err) } request.Header.Set("Content-Type", "application/json") request.Header.Set("x-nginx-loadbalancer-kubernetes", "nlk") + // Perform the request response, err := roundTripper.RoundTrip(request) if err != nil { - t.Fatalf(`Unexpected error: %v`, err) + t.Fatalf("Unexpected error: %v", err) } if response == nil { - t.Fatalf(`response should not be nil`) + t.Fatalf("Response should not be nil") } + // Validate response headers headerLen := len(response.Header) if headerLen <= 2 { - t.Fatalf(`response.Header should have at least 2 elements, found %d`, headerLen) + t.Fatalf("Response headers should have at least 2 elements, found %d", headerLen) } } diff --git a/internal/observation/watcher.go b/internal/observation/watcher.go index 3ee9d3f..bf866ee 100644 --- a/internal/observation/watcher.go +++ b/internal/observation/watcher.go @@ -8,6 +8,8 @@ package observation import ( "errors" "fmt" + "time" + "github.com/nginxinc/kubernetes-nginx-ingress/internal/configuration" "github.com/nginxinc/kubernetes-nginx-ingress/internal/core" "github.com/sirupsen/logrus" @@ -16,7 +18,6 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/informers" "k8s.io/client-go/tools/cache" - "time" ) // Watcher is responsible for watching for changes to Kubernetes resources. @@ -163,7 +164,7 @@ func (w *Watcher) initializeEventListeners() error { return nil } -// notMasterNode retrieves the IP Addresses of the nodes in the cluster. Currently, the master node is excluded. This is +// notControlPlaneNode retrieves the IP Addresses of the nodes in the cluster. Currently, the master node is excluded. This is // because the master node may or may not be a worker node and thus may not be able to route traffic. func (w *Watcher) retrieveNodeIps() ([]string, error) { started := time.Now() @@ -180,7 +181,7 @@ func (w *Watcher) retrieveNodeIps() ([]string, error) { for _, node := range nodes.Items { // this is kind of a broad assumption, should probably make this a configurable option - if w.notMasterNode(node) { + if w.notControlPlaneNode(node) { for _, address := range node.Status.Addresses { if address.Type == v1.NodeInternalIP { nodeIps = append(nodeIps, address.Address) @@ -194,11 +195,11 @@ func (w *Watcher) retrieveNodeIps() ([]string, error) { return nodeIps, nil } -// notMasterNode determines if the node is a master node. -func (w *Watcher) notMasterNode(node v1.Node) bool { - logrus.Debug("Watcher::notMasterNode") +// notControlPlaneNode determines if the node is a master node. +func (w *Watcher) notControlPlaneNode(node v1.Node) bool { + logrus.Debug("Watcher::notControlPlaneNode") - _, found := node.Labels["node-role.kubernetes.io/master"] + _, found := node.Labels["node-role.kubernetes.io/control-plane"] return !found }