github.com/cilium/cilium@v1.16.2/operator/api/server_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package api
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"net/http"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/cilium/hive/cell"
    14  	"github.com/cilium/hive/hivetest"
    15  	"github.com/go-openapi/runtime/middleware"
    16  	"go.uber.org/goleak"
    17  
    18  	operatorApi "github.com/cilium/cilium/api/v1/operator/server"
    19  	clrestapi "github.com/cilium/cilium/api/v1/operator/server/restapi/cluster"
    20  	"github.com/cilium/cilium/pkg/hive"
    21  	k8sClient "github.com/cilium/cilium/pkg/k8s/client"
    22  )
    23  
    24  func TestAPIServerK8sDisabled(t *testing.T) {
    25  	defer goleak.VerifyNone(
    26  		t,
    27  		// ignore goroutine started from sigs.k8s.io/controller-runtime/pkg/log.go init function
    28  		goleak.IgnoreTopFunction("time.Sleep"),
    29  	)
    30  
    31  	var testSrv Server
    32  
    33  	hive := hive.New(
    34  		k8sClient.FakeClientCell,
    35  		cell.Invoke(func(cs *k8sClient.FakeClientset) {
    36  			cs.Disable()
    37  		}),
    38  		MetricsHandlerCell,
    39  		HealthHandlerCell(
    40  			func() bool {
    41  				return false
    42  			},
    43  			func() bool {
    44  				return true
    45  			},
    46  		),
    47  		cell.Provide(func() clrestapi.GetClusterHandler {
    48  			return clrestapi.GetClusterHandlerFunc(clustersHandlerMock)
    49  		}),
    50  		cell.Provide(func() Config {
    51  			return Config{
    52  				OperatorAPIServeAddr: "localhost:0",
    53  			}
    54  		}),
    55  
    56  		operatorApi.SpecCell,
    57  		cell.Provide(newServer),
    58  
    59  		cell.Invoke(func(srv Server) {
    60  			testSrv = srv
    61  		}),
    62  	)
    63  
    64  	tlog := hivetest.Logger(t)
    65  	if err := hive.Start(tlog, context.Background()); err != nil {
    66  		t.Fatalf("failed to start: %s", err)
    67  	}
    68  
    69  	if len(testSrv.Ports()) != 1 {
    70  		t.Fatalf("expected a single opened port, got: %v", len(testSrv.Ports()))
    71  	}
    72  	port := testSrv.Ports()[0]
    73  
    74  	if err := testEndpoint(t, port, "/v1/metrics", http.StatusOK); err != nil {
    75  		t.Fatalf("failed to query endpoint: %s", err)
    76  	}
    77  	if err := testEndpoint(t, port, "/v1/healthz", http.StatusNotImplemented); err != nil {
    78  		t.Fatalf("failed to query endpoint: %s", err)
    79  	}
    80  	if err := testEndpoint(t, port, "/healthz", http.StatusNotImplemented); err != nil {
    81  		t.Fatalf("failed to query endpoint: %s", err)
    82  	}
    83  	if err := testEndpoint(t, port, "/v1/cluster", http.StatusOK); err != nil {
    84  		t.Fatalf("failed to query endpoint: %s", err)
    85  	}
    86  
    87  	if err := hive.Stop(tlog, context.Background()); err != nil {
    88  		t.Fatalf("failed to stop: %s", err)
    89  	}
    90  }
    91  
    92  func TestAPIServerK8sEnabled(t *testing.T) {
    93  	defer goleak.VerifyNone(
    94  		t,
    95  		// ignore goroutine started from sigs.k8s.io/controller-runtime/pkg/log.go init function
    96  		goleak.IgnoreTopFunction("time.Sleep"),
    97  	)
    98  
    99  	var testSrv Server
   100  
   101  	hive := hive.New(
   102  		k8sClient.FakeClientCell,
   103  		MetricsHandlerCell,
   104  		HealthHandlerCell(
   105  			func() bool {
   106  				return false
   107  			},
   108  			func() bool {
   109  				return true
   110  			},
   111  		),
   112  		cell.Provide(func() clrestapi.GetClusterHandler {
   113  			return clrestapi.GetClusterHandlerFunc(clustersHandlerMock)
   114  		}),
   115  		cell.Provide(func() Config {
   116  			return Config{
   117  				OperatorAPIServeAddr: "localhost:0",
   118  			}
   119  		}),
   120  
   121  		operatorApi.SpecCell,
   122  		cell.Provide(newServer),
   123  
   124  		cell.Invoke(func(srv Server) {
   125  			testSrv = srv
   126  		}),
   127  	)
   128  
   129  	tlog := hivetest.Logger(t)
   130  	if err := hive.Start(tlog, context.Background()); err != nil {
   131  		t.Fatalf("failed to start: %s", err)
   132  	}
   133  
   134  	if len(testSrv.Ports()) != 1 {
   135  		t.Fatalf("expected a single opened port, got: %v", len(testSrv.Ports()))
   136  	}
   137  	port := testSrv.Ports()[0]
   138  
   139  	if err := testEndpoint(t, port, "/v1/metrics", http.StatusOK); err != nil {
   140  		t.Fatalf("failed to query endpoint: %s", err)
   141  	}
   142  	if err := testEndpoint(t, port, "/v1/healthz", http.StatusOK); err != nil {
   143  		t.Fatalf("failed to query endpoint: %s", err)
   144  	}
   145  	if err := testEndpoint(t, port, "/healthz", http.StatusOK); err != nil {
   146  		t.Fatalf("failed to query endpoint: %s", err)
   147  	}
   148  	if err := testEndpoint(t, port, "/v1/cluster", http.StatusOK); err != nil {
   149  		t.Fatalf("failed to query endpoint: %s", err)
   150  	}
   151  
   152  	if err := hive.Stop(tlog, context.Background()); err != nil {
   153  		t.Fatalf("failed to stop: %s", err)
   154  	}
   155  }
   156  
   157  func testEndpoint(t *testing.T, port int, path string, statusCode int) error {
   158  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   159  	defer cancel()
   160  
   161  	req, err := http.NewRequestWithContext(
   162  		ctx,
   163  		http.MethodGet,
   164  		fmt.Sprintf("http://localhost:%d%s", port, path),
   165  		nil,
   166  	)
   167  	if err != nil {
   168  		return fmt.Errorf("failed to create http request: %w", err)
   169  	}
   170  
   171  	res, err := http.DefaultClient.Do(req)
   172  	if err != nil {
   173  		return fmt.Errorf("http request for %s failed: %w", path, err)
   174  	}
   175  	defer res.Body.Close()
   176  
   177  	if res.StatusCode != statusCode {
   178  		return fmt.Errorf("expected http status code %d, got: %d", statusCode, res.StatusCode)
   179  	}
   180  
   181  	return nil
   182  }
   183  
   184  func clustersHandlerMock(params clrestapi.GetClusterParams) middleware.Responder {
   185  	return clrestapi.NewGetClusterOK()
   186  }