github.com/cilium/cilium@v1.16.2/operator/pkg/ingress/helpers_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package ingress
     5  
     6  import (
     7  	"context"
     8  	"io"
     9  	"testing"
    10  
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/stretchr/testify/require"
    13  	networkingv1 "k8s.io/api/networking/v1"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"k8s.io/apimachinery/pkg/runtime"
    16  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    17  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    18  	"sigs.k8s.io/controller-runtime/pkg/client"
    19  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    20  	gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
    21  
    22  	"github.com/cilium/cilium/operator/pkg/model"
    23  	ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2"
    24  )
    25  
    26  func TestIsIngressClassMarkedAsDefault(t *testing.T) {
    27  	testCases := []struct {
    28  		desc         string
    29  		ingressClass networkingv1.IngressClass
    30  		isDefault    bool
    31  	}{
    32  		{
    33  			desc: "Is default IngressClass if annotation is present and set to true",
    34  			ingressClass: networkingv1.IngressClass{
    35  				ObjectMeta: metav1.ObjectMeta{
    36  					Namespace: "test",
    37  					Name:      "test",
    38  					Annotations: map[string]string{
    39  						"ingressclass.kubernetes.io/is-default-class": "true",
    40  					},
    41  				},
    42  			},
    43  			isDefault: true,
    44  		},
    45  		{
    46  			desc: "Isn't default IngressClass if annotation is present and set to false",
    47  			ingressClass: networkingv1.IngressClass{
    48  				ObjectMeta: metav1.ObjectMeta{
    49  					Namespace: "test",
    50  					Name:      "test",
    51  					Annotations: map[string]string{
    52  						"ingressclass.kubernetes.io/is-default-class": "false",
    53  					},
    54  				},
    55  			},
    56  			isDefault: false,
    57  		},
    58  		{
    59  			desc: "Isn't default IngressClass if annotation isn't present",
    60  			ingressClass: networkingv1.IngressClass{
    61  				ObjectMeta: metav1.ObjectMeta{
    62  					Namespace:   "test",
    63  					Name:        "test",
    64  					Annotations: map[string]string{},
    65  				},
    66  			},
    67  			isDefault: false,
    68  		},
    69  	}
    70  	for _, tC := range testCases {
    71  		t.Run(tC.desc, func(t *testing.T) {
    72  			isDefault, err := isIngressClassMarkedAsDefault(tC.ingressClass)
    73  			require.NoError(t, err)
    74  			require.Equal(t, tC.isDefault, isDefault)
    75  		})
    76  	}
    77  }
    78  
    79  func TestIsCiliumManagedIngress(t *testing.T) {
    80  	fakeLogger := logrus.New()
    81  	fakeLogger.SetOutput(io.Discard)
    82  
    83  	testCases := []struct {
    84  		desc    string
    85  		ingress networkingv1.Ingress
    86  		fixture []client.Object
    87  		managed bool
    88  	}{
    89  		{
    90  			desc: "Marked via IngressClassName",
    91  			ingress: networkingv1.Ingress{
    92  				ObjectMeta: metav1.ObjectMeta{
    93  					Namespace: "test",
    94  					Name:      "test",
    95  				},
    96  				Spec: networkingv1.IngressSpec{
    97  					IngressClassName: model.AddressOf("cilium"),
    98  				},
    99  			},
   100  			fixture: []client.Object{},
   101  			managed: true,
   102  		},
   103  		{
   104  			desc: "Marked via annotation",
   105  			ingress: networkingv1.Ingress{
   106  				ObjectMeta: metav1.ObjectMeta{
   107  					Namespace: "test",
   108  					Name:      "test",
   109  					Annotations: map[string]string{
   110  						"kubernetes.io/ingress.class": "cilium",
   111  					},
   112  				},
   113  				Spec: networkingv1.IngressSpec{},
   114  			},
   115  			fixture: []client.Object{},
   116  			managed: true,
   117  		},
   118  		{
   119  			desc: "Legacy ingress class annotation takes presedence over ingressClassName field",
   120  			ingress: networkingv1.Ingress{
   121  				ObjectMeta: metav1.ObjectMeta{
   122  					Namespace: "test",
   123  					Name:      "test",
   124  					Annotations: map[string]string{
   125  						"kubernetes.io/ingress.class": "other",
   126  					},
   127  				},
   128  				Spec: networkingv1.IngressSpec{
   129  					IngressClassName: model.AddressOf("cilium"),
   130  				},
   131  			},
   132  			fixture: []client.Object{},
   133  			managed: false,
   134  		},
   135  		{
   136  			desc: "Cilium is default IngressClass and Ingress has no specific class set",
   137  			ingress: networkingv1.Ingress{
   138  				ObjectMeta: metav1.ObjectMeta{
   139  					Namespace: "test",
   140  					Name:      "test",
   141  				},
   142  				Spec: networkingv1.IngressSpec{},
   143  			},
   144  			fixture: []client.Object{
   145  				&networkingv1.IngressClass{
   146  					ObjectMeta: metav1.ObjectMeta{
   147  						Name: "cilium",
   148  						Annotations: map[string]string{
   149  							"ingressclass.kubernetes.io/is-default-class": "true",
   150  						},
   151  					},
   152  				},
   153  			},
   154  			managed: true,
   155  		},
   156  		{
   157  			desc: "Cilium isn't IngressClass (annotation set to false) and Ingress has no specific class set",
   158  			ingress: networkingv1.Ingress{
   159  				ObjectMeta: metav1.ObjectMeta{
   160  					Namespace: "test",
   161  					Name:      "test",
   162  				},
   163  				Spec: networkingv1.IngressSpec{},
   164  			},
   165  			fixture: []client.Object{
   166  				&networkingv1.IngressClass{
   167  					ObjectMeta: metav1.ObjectMeta{
   168  						Name: "cilium",
   169  						Annotations: map[string]string{
   170  							"ingressclass.kubernetes.io/is-default-class": "false",
   171  						},
   172  					},
   173  				},
   174  			},
   175  			managed: false,
   176  		},
   177  		{
   178  			desc: "Cilium isn't IngressClass (annotation missconfigured) and Ingress has no specific class set",
   179  			ingress: networkingv1.Ingress{
   180  				ObjectMeta: metav1.ObjectMeta{
   181  					Namespace: "test",
   182  					Name:      "test",
   183  				},
   184  				Spec: networkingv1.IngressSpec{},
   185  			},
   186  			fixture: []client.Object{
   187  				&networkingv1.IngressClass{
   188  					ObjectMeta: metav1.ObjectMeta{
   189  						Name: "cilium",
   190  						Annotations: map[string]string{
   191  							"ingressclass.kubernetes.io/is-default-class": "wrong-bool",
   192  						},
   193  					},
   194  				},
   195  			},
   196  			managed: false,
   197  		},
   198  		{
   199  			desc: "Cilium isn't IngressClass (annotation not present) and Ingress has no specific class set",
   200  			ingress: networkingv1.Ingress{
   201  				ObjectMeta: metav1.ObjectMeta{
   202  					Namespace: "test",
   203  					Name:      "test",
   204  				},
   205  				Spec: networkingv1.IngressSpec{},
   206  			},
   207  			fixture: []client.Object{
   208  				&networkingv1.IngressClass{
   209  					ObjectMeta: metav1.ObjectMeta{
   210  						Name:        "cilium",
   211  						Annotations: map[string]string{},
   212  					},
   213  				},
   214  			},
   215  			managed: false,
   216  		},
   217  		{
   218  			desc: "Cilium is default IngressClass but  Ingress has set another specific Ingress class",
   219  			ingress: networkingv1.Ingress{
   220  				ObjectMeta: metav1.ObjectMeta{
   221  					Namespace: "test",
   222  					Name:      "test",
   223  				},
   224  				Spec: networkingv1.IngressSpec{
   225  					IngressClassName: model.AddressOf("other"),
   226  				},
   227  			},
   228  			fixture: []client.Object{
   229  				&networkingv1.IngressClass{
   230  					ObjectMeta: metav1.ObjectMeta{
   231  						Name: "cilium",
   232  						Annotations: map[string]string{
   233  							"ingressclass.kubernetes.io/is-default-class": "true",
   234  						},
   235  					},
   236  				},
   237  			},
   238  			managed: false,
   239  		},
   240  	}
   241  	for _, tC := range testCases {
   242  		t.Run(tC.desc, func(t *testing.T) {
   243  			fakeClient := fake.NewClientBuilder().
   244  				WithScheme(testScheme()).
   245  				WithObjects(tC.fixture...).
   246  				Build()
   247  
   248  			isManaged := isCiliumManagedIngress(context.Background(), fakeClient, fakeLogger, tC.ingress)
   249  			require.Equal(t, tC.managed, isManaged)
   250  		})
   251  	}
   252  }
   253  
   254  func testScheme() *runtime.Scheme {
   255  	scheme := runtime.NewScheme()
   256  
   257  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
   258  	utilruntime.Must(ciliumv2.AddToScheme(scheme))
   259  	utilruntime.Must(gatewayv1.AddToScheme(scheme))
   260  
   261  	return scheme
   262  }