istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/policyattachment_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package model
    16  
    17  import (
    18  	"testing"
    19  
    20  	"k8s.io/apimachinery/pkg/types"
    21  
    22  	"istio.io/api/type/v1beta1"
    23  	"istio.io/istio/pilot/pkg/features"
    24  	"istio.io/istio/pkg/config"
    25  	"istio.io/istio/pkg/config/constants"
    26  	"istio.io/istio/pkg/config/labels"
    27  	"istio.io/istio/pkg/config/schema/gvk"
    28  	"istio.io/istio/pkg/test"
    29  )
    30  
    31  func TestPolicyMatcher(t *testing.T) {
    32  	sampleTargetRef := &v1beta1.PolicyTargetReference{
    33  		Group: gvk.KubernetesGateway.Group,
    34  		Kind:  gvk.KubernetesGateway.Kind,
    35  		Name:  "sample-gateway",
    36  	}
    37  	waypointTargetRef := &v1beta1.PolicyTargetReference{
    38  		Group: gvk.KubernetesGateway.Group,
    39  		Kind:  gvk.KubernetesGateway.Kind,
    40  		Name:  "sample-waypoint",
    41  	}
    42  	serviceTargetRef := &v1beta1.PolicyTargetReference{
    43  		Group: gvk.Service.Group,
    44  		Kind:  gvk.Service.Kind,
    45  		Name:  "sample-svc",
    46  	}
    47  	sampleSelector := &v1beta1.WorkloadSelector{
    48  		MatchLabels: labels.Instance{
    49  			"app": "my-app",
    50  		},
    51  	}
    52  	sampleGatewaySelector := &v1beta1.WorkloadSelector{
    53  		MatchLabels: labels.Instance{
    54  			constants.GatewayNameLabel: "sample-gateway",
    55  		},
    56  	}
    57  	sampleWaypointSelector := &v1beta1.WorkloadSelector{
    58  		MatchLabels: labels.Instance{
    59  			constants.GatewayNameLabel: "sample-waypoint",
    60  		},
    61  	}
    62  	regularApp := WorkloadPolicyMatcher{
    63  		Namespace: "default",
    64  		WorkloadLabels: labels.Instance{
    65  			"app": "my-app",
    66  		},
    67  		IsWaypoint: false,
    68  	}
    69  	sampleGateway := WorkloadPolicyMatcher{
    70  		Namespace: "default",
    71  		WorkloadLabels: labels.Instance{
    72  			constants.GatewayNameLabel: "sample-gateway",
    73  		},
    74  		IsWaypoint: false,
    75  	}
    76  	sampleWaypoint := WorkloadPolicyMatcher{
    77  		Namespace: "default",
    78  		WorkloadLabels: labels.Instance{
    79  			constants.GatewayNameLabel: "sample-waypoint",
    80  		},
    81  		IsWaypoint: true,
    82  	}
    83  	serviceTarget := WorkloadPolicyMatcher{
    84  		Namespace: "default",
    85  		WorkloadLabels: labels.Instance{
    86  			"app":                      "my-app",
    87  			constants.GatewayNameLabel: "sample-waypoint",
    88  		},
    89  		IsWaypoint: true,
    90  		Service:    "sample-svc",
    91  	}
    92  	tests := []struct {
    93  		name                   string
    94  		selection              WorkloadPolicyMatcher
    95  		policy                 TargetablePolicy
    96  		enableSelectorPolicies bool
    97  
    98  		expected bool
    99  	}{
   100  		{
   101  			name:      "non-gateway API workload and a targetRef",
   102  			selection: regularApp,
   103  			policy: &mockPolicyTargetGetter{
   104  				targetRef: sampleTargetRef,
   105  			},
   106  			expected:               false,
   107  			enableSelectorPolicies: true,
   108  		},
   109  		{
   110  			name:      "non-gateway API workload and a selector",
   111  			selection: regularApp,
   112  			policy: &mockPolicyTargetGetter{
   113  				selector: sampleSelector,
   114  			},
   115  			expected:               true,
   116  			enableSelectorPolicies: true,
   117  		},
   118  		{
   119  			name:      "non-gateway API workload and both a targetRef and a selector",
   120  			selection: regularApp,
   121  			policy: &mockPolicyTargetGetter{
   122  				selector:  sampleSelector,
   123  				targetRef: sampleTargetRef,
   124  			},
   125  			expected:               false,
   126  			enableSelectorPolicies: true,
   127  		},
   128  		{
   129  			name:                   "non-gateway API workload and no targetRef or selector",
   130  			policy:                 &mockPolicyTargetGetter{},
   131  			selection:              regularApp,
   132  			expected:               true,
   133  			enableSelectorPolicies: true,
   134  		},
   135  		{
   136  			name: "gateway API ingress and a targetRef",
   137  			policy: &mockPolicyTargetGetter{
   138  				targetRef: sampleTargetRef,
   139  			},
   140  			selection: sampleGateway,
   141  			expected:  true,
   142  		},
   143  		{
   144  			name: "gateway API ingress and a selector",
   145  			policy: &mockPolicyTargetGetter{
   146  				selector: sampleGatewaySelector,
   147  			},
   148  			selection:              sampleGateway,
   149  			expected:               true,
   150  			enableSelectorPolicies: true,
   151  		},
   152  		{
   153  			name: "gateway API ingress and a selector (policy attachment only)",
   154  			policy: &mockPolicyTargetGetter{
   155  				selector: sampleGatewaySelector,
   156  			},
   157  			selection:              sampleGateway,
   158  			expected:               false,
   159  			enableSelectorPolicies: false,
   160  		},
   161  		{
   162  			name: "gateway API ingress and both a targetRef and a selector",
   163  			policy: &mockPolicyTargetGetter{
   164  				targetRef: sampleTargetRef,
   165  				selector:  sampleGatewaySelector,
   166  			},
   167  			selection: sampleGateway,
   168  			expected:  true,
   169  		},
   170  		{
   171  			name: "gateway API ingress and non-matching targetRef",
   172  			policy: &mockPolicyTargetGetter{
   173  				targetRef: waypointTargetRef,
   174  			},
   175  			selection:              sampleGateway,
   176  			expected:               false,
   177  			enableSelectorPolicies: true,
   178  		},
   179  		{
   180  			name:                   "gateway API ingress and no targetRef or selector",
   181  			selection:              sampleGateway,
   182  			policy:                 &mockPolicyTargetGetter{},
   183  			expected:               true,
   184  			enableSelectorPolicies: true,
   185  		},
   186  		{
   187  			name: "waypoint and a targetRef",
   188  			policy: &mockPolicyTargetGetter{
   189  				targetRef: waypointTargetRef,
   190  			},
   191  			selection:              sampleWaypoint,
   192  			expected:               true,
   193  			enableSelectorPolicies: true,
   194  		},
   195  		{
   196  			name: "waypoint and a selector",
   197  			policy: &mockPolicyTargetGetter{
   198  				selector: sampleWaypointSelector,
   199  			},
   200  			selection:              sampleWaypoint,
   201  			expected:               false,
   202  			enableSelectorPolicies: true,
   203  		},
   204  		{
   205  			name: "waypoint and both a targetRef and a selector",
   206  			policy: &mockPolicyTargetGetter{
   207  				targetRef: waypointTargetRef,
   208  				selector:  sampleWaypointSelector,
   209  			},
   210  			selection:              sampleWaypoint,
   211  			expected:               true,
   212  			enableSelectorPolicies: true,
   213  		},
   214  		{
   215  			name:                   "waypoint and no targetRef or selector",
   216  			selection:              sampleWaypoint,
   217  			policy:                 &mockPolicyTargetGetter{},
   218  			expected:               false,
   219  			enableSelectorPolicies: true,
   220  		},
   221  		{
   222  			name:      "waypoint and non-matching targetRef",
   223  			selection: sampleWaypoint,
   224  			policy: &mockPolicyTargetGetter{
   225  				targetRef: sampleTargetRef,
   226  			},
   227  			expected:               false,
   228  			enableSelectorPolicies: true,
   229  		},
   230  		{
   231  			name:      "waypoint and matching targetRefs",
   232  			selection: sampleWaypoint,
   233  			policy: &mockPolicyTargetGetter{
   234  				targetRefs: []*v1beta1.PolicyTargetReference{waypointTargetRef},
   235  			},
   236  			expected:               true,
   237  			enableSelectorPolicies: true,
   238  		},
   239  		{
   240  			name:      "waypoint and partial matching targetRefs",
   241  			selection: sampleWaypoint,
   242  			policy: &mockPolicyTargetGetter{
   243  				targetRefs: []*v1beta1.PolicyTargetReference{waypointTargetRef, sampleTargetRef},
   244  			},
   245  			expected:               true,
   246  			enableSelectorPolicies: true,
   247  		},
   248  		{
   249  			name:      "waypoint and non matching targetRefs",
   250  			selection: sampleWaypoint,
   251  			policy: &mockPolicyTargetGetter{
   252  				targetRefs: []*v1beta1.PolicyTargetReference{sampleTargetRef},
   253  			},
   254  			expected:               false,
   255  			enableSelectorPolicies: true,
   256  		},
   257  		{
   258  			name:      "service attached policy",
   259  			selection: serviceTarget,
   260  			policy: &mockPolicyTargetGetter{
   261  				targetRefs: []*v1beta1.PolicyTargetReference{serviceTargetRef},
   262  			},
   263  			enableSelectorPolicies: false,
   264  			expected:               true,
   265  		},
   266  	}
   267  
   268  	for _, tt := range tests {
   269  		t.Run(tt.name, func(t *testing.T) {
   270  			test.SetForTest(t, &features.EnableSelectorBasedK8sGatewayPolicy, tt.enableSelectorPolicies)
   271  			nsName := types.NamespacedName{Name: "policy1", Namespace: "default"}
   272  			matcher := tt.selection.ShouldAttachPolicy(mockKind, nsName, tt.policy)
   273  
   274  			if matcher != tt.expected {
   275  				t.Errorf("Expected %v, but got %v", tt.expected, matcher)
   276  			}
   277  		})
   278  	}
   279  }
   280  
   281  type mockPolicyTargetGetter struct {
   282  	targetRef  *v1beta1.PolicyTargetReference
   283  	targetRefs []*v1beta1.PolicyTargetReference
   284  	selector   *v1beta1.WorkloadSelector
   285  }
   286  
   287  func (m *mockPolicyTargetGetter) GetTargetRef() *v1beta1.PolicyTargetReference {
   288  	return m.targetRef
   289  }
   290  
   291  func (m *mockPolicyTargetGetter) GetTargetRefs() []*v1beta1.PolicyTargetReference {
   292  	return m.targetRefs
   293  }
   294  
   295  func (m *mockPolicyTargetGetter) GetSelector() *v1beta1.WorkloadSelector {
   296  	return m.selector
   297  }
   298  
   299  var mockKind = config.GroupVersionKind{
   300  	Group:   "mock.istio.io",
   301  	Version: "v1",
   302  	Kind:    "MockKind",
   303  }