github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/spd/cnc_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 spd 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 "github.com/stretchr/testify/assert" 25 appsv1 "k8s.io/api/apps/v1" 26 v1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/runtime" 29 "k8s.io/client-go/tools/cache" 30 "k8s.io/utils/pointer" 31 32 apis "github.com/kubewharf/katalyst-api/pkg/apis/autoscaling/v1alpha1" 33 configapi "github.com/kubewharf/katalyst-api/pkg/apis/config/v1alpha1" 34 apiworkload "github.com/kubewharf/katalyst-api/pkg/apis/workload/v1alpha1" 35 "github.com/kubewharf/katalyst-api/pkg/consts" 36 katalystbase "github.com/kubewharf/katalyst-core/cmd/base" 37 "github.com/kubewharf/katalyst-core/pkg/config/controller" 38 "github.com/kubewharf/katalyst-core/pkg/config/generic" 39 ) 40 41 func Test_cncCacheController_Run(t *testing.T) { 42 t.Parallel() 43 44 type fields struct { 45 pod *v1.Pod 46 workload *appsv1.StatefulSet 47 spd *apiworkload.ServiceProfileDescriptor 48 cnc *configapi.CustomNodeConfig 49 enableCNCCache bool 50 } 51 tests := []struct { 52 name string 53 fields fields 54 wantCNC *configapi.CustomNodeConfig 55 }{ 56 { 57 name: "update cnc spd config when cnc cache enable", 58 fields: fields{ 59 pod: &v1.Pod{ 60 ObjectMeta: metav1.ObjectMeta{ 61 Name: "pod1", 62 Namespace: "default", 63 OwnerReferences: []metav1.OwnerReference{ 64 { 65 APIVersion: "apps/v1", 66 Kind: "StatefulSet", 67 Name: "sts1", 68 }, 69 }, 70 Annotations: map[string]string{ 71 consts.PodAnnotationSPDNameKey: "spd1", 72 }, 73 Labels: map[string]string{ 74 "workload": "sts1", 75 }, 76 }, 77 Spec: v1.PodSpec{ 78 NodeName: "node1", 79 }, 80 }, 81 workload: &appsv1.StatefulSet{ 82 TypeMeta: metav1.TypeMeta{ 83 Kind: "StatefulSet", 84 APIVersion: "apps/v1", 85 }, 86 ObjectMeta: metav1.ObjectMeta{ 87 Name: "sts1", 88 Namespace: "default", 89 Annotations: map[string]string{ 90 consts.WorkloadAnnotationSPDEnableKey: consts.WorkloadAnnotationSPDEnabled, 91 }, 92 }, 93 Spec: appsv1.StatefulSetSpec{ 94 Selector: &metav1.LabelSelector{ 95 MatchLabels: map[string]string{ 96 "workload": "sts1", 97 }, 98 }, 99 Template: v1.PodTemplateSpec{ 100 ObjectMeta: metav1.ObjectMeta{ 101 Annotations: map[string]string{ 102 "katalyst.kubewharf.io/qos_level": "dedicated_cores", 103 }, 104 }, 105 Spec: v1.PodSpec{}, 106 }, 107 }, 108 }, 109 spd: &apiworkload.ServiceProfileDescriptor{ 110 ObjectMeta: metav1.ObjectMeta{ 111 Namespace: "default", 112 Name: "sts1", 113 OwnerReferences: []metav1.OwnerReference{ 114 { 115 APIVersion: "apps/v1", 116 Kind: "StatefulSet", 117 Name: "sts1", 118 }, 119 }, 120 }, 121 Spec: apiworkload.ServiceProfileDescriptorSpec{ 122 TargetRef: apis.CrossVersionObjectReference{ 123 Kind: stsGVK.Kind, 124 Name: "sts1", 125 APIVersion: stsGVK.GroupVersion().String(), 126 }, 127 BaselinePercent: pointer.Int32(100), 128 }, 129 Status: apiworkload.ServiceProfileDescriptorStatus{ 130 AggMetrics: []apiworkload.AggPodMetrics{}, 131 }, 132 }, 133 cnc: &configapi.CustomNodeConfig{ 134 ObjectMeta: metav1.ObjectMeta{ 135 Name: "node1", 136 }, 137 }, 138 enableCNCCache: true, 139 }, 140 wantCNC: &configapi.CustomNodeConfig{ 141 ObjectMeta: metav1.ObjectMeta{ 142 Name: "node1", 143 }, 144 Status: configapi.CustomNodeConfigStatus{ 145 ServiceProfileConfigList: []configapi.TargetConfig{ 146 { 147 ConfigNamespace: "default", 148 ConfigName: "sts1", 149 Hash: "51131be1b092", 150 }, 151 }, 152 }, 153 }, 154 }, 155 { 156 name: "clear cnc spd config when cnc cache disable", 157 fields: fields{ 158 pod: &v1.Pod{ 159 ObjectMeta: metav1.ObjectMeta{ 160 Name: "pod1", 161 Namespace: "default", 162 OwnerReferences: []metav1.OwnerReference{ 163 { 164 APIVersion: "apps/v1", 165 Kind: "StatefulSet", 166 Name: "sts1", 167 }, 168 }, 169 Annotations: map[string]string{ 170 consts.PodAnnotationSPDNameKey: "spd1", 171 }, 172 Labels: map[string]string{ 173 "workload": "sts1", 174 }, 175 }, 176 Spec: v1.PodSpec{ 177 NodeName: "node1", 178 }, 179 }, 180 workload: &appsv1.StatefulSet{ 181 TypeMeta: metav1.TypeMeta{ 182 Kind: "StatefulSet", 183 APIVersion: "apps/v1", 184 }, 185 ObjectMeta: metav1.ObjectMeta{ 186 Name: "sts1", 187 Namespace: "default", 188 Annotations: map[string]string{ 189 consts.WorkloadAnnotationSPDEnableKey: consts.WorkloadAnnotationSPDEnabled, 190 }, 191 }, 192 Spec: appsv1.StatefulSetSpec{ 193 Selector: &metav1.LabelSelector{ 194 MatchLabels: map[string]string{ 195 "workload": "sts1", 196 }, 197 }, 198 Template: v1.PodTemplateSpec{ 199 ObjectMeta: metav1.ObjectMeta{ 200 Annotations: map[string]string{ 201 "katalyst.kubewharf.io/qos_level": "dedicated_cores", 202 }, 203 }, 204 Spec: v1.PodSpec{}, 205 }, 206 }, 207 }, 208 spd: &apiworkload.ServiceProfileDescriptor{ 209 ObjectMeta: metav1.ObjectMeta{ 210 Namespace: "default", 211 Name: "sts1", 212 OwnerReferences: []metav1.OwnerReference{ 213 { 214 APIVersion: "apps/v1", 215 Kind: "StatefulSet", 216 Name: "sts1", 217 }, 218 }, 219 }, 220 Spec: apiworkload.ServiceProfileDescriptorSpec{ 221 TargetRef: apis.CrossVersionObjectReference{ 222 Kind: stsGVK.Kind, 223 Name: "sts1", 224 APIVersion: stsGVK.GroupVersion().String(), 225 }, 226 BaselinePercent: pointer.Int32(100), 227 }, 228 Status: apiworkload.ServiceProfileDescriptorStatus{ 229 AggMetrics: []apiworkload.AggPodMetrics{}, 230 }, 231 }, 232 cnc: &configapi.CustomNodeConfig{ 233 ObjectMeta: metav1.ObjectMeta{ 234 Name: "node1", 235 }, 236 Status: configapi.CustomNodeConfigStatus{ 237 ServiceProfileConfigList: []configapi.TargetConfig{ 238 { 239 ConfigNamespace: "default", 240 ConfigName: "sts1", 241 Hash: "51131be1b092", 242 }, 243 }, 244 }, 245 }, 246 enableCNCCache: false, 247 }, 248 wantCNC: &configapi.CustomNodeConfig{ 249 ObjectMeta: metav1.ObjectMeta{ 250 Name: "node1", 251 }, 252 Status: configapi.CustomNodeConfigStatus{}, 253 }, 254 }, 255 } 256 for _, tt := range tests { 257 tt := tt 258 t.Run(tt.name, func(t *testing.T) { 259 t.Parallel() 260 261 spdConfig := &controller.SPDConfig{ 262 EnableCNCCache: tt.fields.enableCNCCache, 263 SPDWorkloadGVResources: []string{"statefulsets.v1.apps"}, 264 } 265 genericConfig := &generic.GenericConfiguration{} 266 controllerConf := &controller.GenericControllerConfiguration{ 267 DynamicGVResources: []string{"statefulsets.v1.apps"}, 268 } 269 270 ctx := context.TODO() 271 controlCtx, err := katalystbase.GenerateFakeGenericContext([]runtime.Object{tt.fields.pod}, 272 []runtime.Object{tt.fields.spd, tt.fields.cnc}, []runtime.Object{tt.fields.workload}) 273 assert.NoError(t, err) 274 275 spdController, err := NewSPDController(ctx, controlCtx, genericConfig, controllerConf, 276 spdConfig, generic.NewQoSConfiguration(), struct{}{}) 277 assert.NoError(t, err) 278 279 controlCtx.StartInformer(ctx) 280 go spdController.Run() 281 synced := cache.WaitForCacheSync(ctx.Done(), spdController.syncedFunc...) 282 assert.True(t, synced) 283 time.Sleep(1 * time.Second) 284 285 newCNC, err := controlCtx.Client.InternalClient.ConfigV1alpha1().CustomNodeConfigs(). 286 Get(ctx, tt.fields.cnc.Name, metav1.GetOptions{}) 287 assert.NoError(t, err) 288 assert.Equal(t, tt.wantCNC, newCNC) 289 }) 290 } 291 }