github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/kcc/util/kcct_test.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  
    24  	v1 "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    27  	"k8s.io/klog/v2"
    28  
    29  	apisv1alpha1 "github.com/kubewharf/katalyst-api/pkg/apis/config/v1alpha1"
    30  	"github.com/kubewharf/katalyst-core/pkg/util/native"
    31  )
    32  
    33  func toTestUnstructured(obj interface{}) *unstructured.Unstructured {
    34  	ret, err := native.ToUnstructured(obj)
    35  	if err != nil {
    36  		klog.Error(err)
    37  	}
    38  	return ret
    39  }
    40  
    41  func generateTestCNC(name string, labels map[string]string) *apisv1alpha1.CustomNodeConfig {
    42  	return &apisv1alpha1.CustomNodeConfig{
    43  		ObjectMeta: metav1.ObjectMeta{
    44  			Name:   name,
    45  			Labels: labels,
    46  		},
    47  	}
    48  }
    49  
    50  func generateTestTargetResource(name, labelSelector string, nodeNames []string) *unstructured.Unstructured {
    51  	return toTestUnstructured(&apisv1alpha1.AdminQoSConfiguration{
    52  		ObjectMeta: metav1.ObjectMeta{
    53  			Name: name,
    54  		},
    55  		Spec: apisv1alpha1.AdminQoSConfigurationSpec{
    56  			GenericConfigSpec: apisv1alpha1.GenericConfigSpec{
    57  				NodeLabelSelector: labelSelector,
    58  				EphemeralSelector: apisv1alpha1.EphemeralSelector{
    59  					NodeNames: nodeNames,
    60  				},
    61  			},
    62  		},
    63  		Status: apisv1alpha1.GenericConfigStatus{},
    64  	})
    65  }
    66  
    67  func generateTestTargetResourceWithTimeout(name, labelSelector string, nodeNames []string) *unstructured.Unstructured {
    68  	return toTestUnstructured(&apisv1alpha1.AdminQoSConfiguration{
    69  		ObjectMeta: metav1.ObjectMeta{
    70  			Name:              name,
    71  			CreationTimestamp: metav1.NewTime(time.Now().Add(-1 * time.Minute * 10)),
    72  		},
    73  		Spec: apisv1alpha1.AdminQoSConfigurationSpec{
    74  			GenericConfigSpec: apisv1alpha1.GenericConfigSpec{
    75  				NodeLabelSelector: labelSelector,
    76  				EphemeralSelector: apisv1alpha1.EphemeralSelector{
    77  					NodeNames:    nodeNames,
    78  					LastDuration: &metav1.Duration{Duration: time.Minute},
    79  				},
    80  			},
    81  		},
    82  		Status: apisv1alpha1.GenericConfigStatus{},
    83  	})
    84  }
    85  
    86  func Test_findMatchedTargetConfig(t *testing.T) {
    87  	t.Parallel()
    88  
    89  	type args struct {
    90  		cnc        *apisv1alpha1.CustomNodeConfig
    91  		configList []*unstructured.Unstructured
    92  	}
    93  	tests := []struct {
    94  		name    string
    95  		args    args
    96  		want    []*unstructured.Unstructured
    97  		wantErr bool
    98  	}{
    99  		{
   100  			name: "only nodeNames config",
   101  			args: args{
   102  				cnc: generateTestCNC("node-1", map[string]string{
   103  					"aa": "default",
   104  				}),
   105  				configList: []*unstructured.Unstructured{
   106  					generateTestTargetResource("config-1", "", []string{"node-1"}),
   107  					generateTestTargetResource("config-2", "", []string{"node-2"}),
   108  				},
   109  			},
   110  			want: []*unstructured.Unstructured{
   111  				generateTestTargetResource("config-1", "", []string{"node-1"}),
   112  			},
   113  		},
   114  		{
   115  			name: "nodeNames overlap",
   116  			args: args{
   117  				cnc: generateTestCNC("node-1", map[string]string{
   118  					"aa": "default",
   119  				}),
   120  				configList: []*unstructured.Unstructured{
   121  					generateTestTargetResource("config-1", "", []string{"node-1"}),
   122  					generateTestTargetResource("config-2", "", []string{"node-1"}),
   123  				},
   124  			},
   125  			want: []*unstructured.Unstructured{
   126  				generateTestTargetResource("config-1", "", []string{"node-1"}),
   127  				generateTestTargetResource("config-2", "", []string{"node-1"}),
   128  			},
   129  		},
   130  		{
   131  			name: "target config invalid",
   132  			args: args{
   133  				cnc: generateTestCNC("node-1", map[string]string{
   134  					"aa": "default",
   135  				}),
   136  				configList: []*unstructured.Unstructured{
   137  					generateTestTargetResourceWithTimeout("config-1", "aa=default", []string{"node-1"}),
   138  					generateTestTargetResourceWithTimeout("config-2", "", nil),
   139  				},
   140  			},
   141  			want: []*unstructured.Unstructured{
   142  				generateTestTargetResourceWithTimeout("config-1", "aa=default", []string{"node-1"}),
   143  			},
   144  		},
   145  		{
   146  			name: "nodeNames prior than labelSelector",
   147  			args: args{
   148  				cnc: generateTestCNC("node-1", map[string]string{
   149  					"aa": "default",
   150  				}),
   151  				configList: []*unstructured.Unstructured{
   152  					generateTestTargetResource("config-1", "aa=default", nil),
   153  					generateTestTargetResource("config-2", "", []string{"node-1"}),
   154  				},
   155  			},
   156  			want: []*unstructured.Unstructured{
   157  				generateTestTargetResource("config-2", "", []string{"node-1"}),
   158  			},
   159  		},
   160  		{
   161  			name: "labelSelector overlap",
   162  			args: args{
   163  				cnc: generateTestCNC("node-1", map[string]string{
   164  					"aa": "default",
   165  				}),
   166  				configList: []*unstructured.Unstructured{
   167  					generateTestTargetResource("config-1", "aa=default", nil),
   168  					generateTestTargetResource("config-2", "", nil),
   169  					generateTestTargetResource("config-3", "aa in (default,non-standard)", nil),
   170  				},
   171  			},
   172  			want: []*unstructured.Unstructured{
   173  				generateTestTargetResource("config-1", "aa=default", nil),
   174  				generateTestTargetResource("config-3", "aa in (default,non-standard)", nil),
   175  			},
   176  		},
   177  		{
   178  			name: "labelSelector overlap but nodeName valid",
   179  			args: args{
   180  				cnc: generateTestCNC("node-1", map[string]string{
   181  					"aa": "default",
   182  				}),
   183  				configList: []*unstructured.Unstructured{
   184  					generateTestTargetResource("config-1", "aa=default", nil),
   185  					generateTestTargetResource("config-2", "", []string{"node-1"}),
   186  					generateTestTargetResource("config-3", "aa in (default,non-standard)", nil),
   187  				},
   188  			},
   189  			want: []*unstructured.Unstructured{
   190  				generateTestTargetResource("config-2", "", []string{"node-1"}),
   191  			},
   192  		},
   193  	}
   194  	for _, tt := range tests {
   195  		tt := tt
   196  		t.Run(tt.name, func(t *testing.T) {
   197  			t.Parallel()
   198  
   199  			got, err := findMatchedKCCTargetConfigForNode(tt.args.cnc, tt.args.configList)
   200  			if (err != nil) != tt.wantErr {
   201  				t.Errorf("findMatchedKCCTargetConfigForNode() error = %v, wantErr %v", err, tt.wantErr)
   202  				return
   203  			}
   204  			if !reflect.DeepEqual(got, tt.want) {
   205  				t.Errorf("findMatchedKCCTargetConfigForNode() got = %v, want %v", got, tt.want)
   206  			}
   207  		})
   208  	}
   209  }
   210  
   211  func TestUpdateKCCTGenericConditions(t *testing.T) {
   212  	t.Parallel()
   213  
   214  	type args struct {
   215  		status          *apisv1alpha1.GenericConfigStatus
   216  		conditionType   apisv1alpha1.ConfigConditionType
   217  		conditionStatus v1.ConditionStatus
   218  		reason          string
   219  		message         string
   220  	}
   221  	tests := []struct {
   222  		name string
   223  		args args
   224  		want bool
   225  	}{
   226  		{
   227  			name: "test-1",
   228  			args: args{
   229  				status:          &apisv1alpha1.GenericConfigStatus{},
   230  				conditionType:   apisv1alpha1.ConfigConditionTypeValid,
   231  				conditionStatus: v1.ConditionTrue,
   232  				reason:          "",
   233  				message:         "",
   234  			},
   235  			want: true,
   236  		},
   237  	}
   238  	for _, tt := range tests {
   239  		tt := tt
   240  		t.Run(tt.name, func(t *testing.T) {
   241  			t.Parallel()
   242  			if got := UpdateKCCTGenericConditions(tt.args.status, tt.args.conditionType, tt.args.conditionStatus, tt.args.reason, tt.args.message); got != tt.want {
   243  				t.Errorf("UpdateKCCTGenericConditions() = %v, want %v", got, tt.want)
   244  			}
   245  		})
   246  	}
   247  }