github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/configuration/core/config_patch_util_test.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package core 21 22 import ( 23 "reflect" 24 "testing" 25 26 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 27 "github.com/1aal/kubeblocks/test/testdata" 28 ) 29 30 func TestCheckExcludeConfigDifference(t *testing.T) { 31 type args struct { 32 oldVersion map[string]string 33 newVersion map[string]string 34 keys []string 35 } 36 tests := []struct { 37 name string 38 args args 39 want bool 40 }{{ 41 name: "emptyKeys", 42 args: args{ 43 oldVersion: map[string]string{ 44 "a": "test1", 45 }, 46 newVersion: map[string]string{ 47 "a": "test1", 48 }, 49 }, 50 want: false, 51 }, { 52 name: "emptyKeys", 53 args: args{ 54 oldVersion: map[string]string{ 55 "a": "test2", 56 }, 57 newVersion: map[string]string{ 58 "a": "test1", 59 }, 60 }, 61 want: true, 62 }, { 63 name: "emptyKeys", 64 args: args{ 65 oldVersion: map[string]string{ 66 "a": "test1", 67 }, 68 newVersion: map[string]string{ 69 "b": "test1", 70 }, 71 }, 72 want: true, 73 }, { 74 name: "keyTest", 75 args: args{ 76 oldVersion: map[string]string{ 77 "a": "test1", 78 "b": "test2", 79 }, 80 newVersion: map[string]string{ 81 "a": "test1", 82 "b": "test3", 83 }, 84 keys: []string{"b"}, 85 }, 86 want: false, 87 }, { 88 name: "keyTest", 89 args: args{ 90 oldVersion: map[string]string{ 91 "a": "test1", 92 "b": "test2", 93 }, 94 newVersion: map[string]string{ 95 "a": "test1", 96 "b": "test3", 97 }, 98 keys: []string{"a"}, 99 }, 100 want: true, 101 }, { 102 name: "keyTest", 103 args: args{ 104 oldVersion: map[string]string{ 105 "a": "test1", 106 "b": "test2", 107 }, 108 newVersion: map[string]string{ 109 "a": "test1", 110 "b": "test3", 111 }, 112 keys: []string{"a", "b"}, 113 }, 114 want: false, 115 }, { 116 name: "keyCountTest", 117 args: args{ 118 oldVersion: map[string]string{ 119 "a": "test1", 120 "b": "test2", 121 "c": "test2", 122 }, 123 newVersion: map[string]string{ 124 "a": "test1", 125 "b": "test3", 126 }, 127 keys: []string{"b"}, 128 }, 129 want: true, 130 }, { 131 name: "notKeyTest", 132 args: args{ 133 oldVersion: map[string]string{ 134 "a": "test1", 135 "b": "test2", 136 "c": "test2", 137 }, 138 newVersion: map[string]string{ 139 "a": "test1", 140 "b": "test3", 141 }, 142 keys: []string{"b", "e", "f", "g"}, 143 }, 144 want: true, 145 }, { 146 name: "notKeyTest", 147 args: args{ 148 oldVersion: map[string]string{ 149 "a": "test1", 150 "b": "test2", 151 "c": "test2", 152 }, 153 newVersion: map[string]string{ 154 "a": "test1", 155 "b": "test3", 156 }, 157 keys: []string{"b", "c", "f", "g"}, 158 }, 159 want: false, 160 }} 161 for _, tt := range tests { 162 t.Run(tt.name, func(t *testing.T) { 163 if got := checkExcludeConfigDifference(tt.args.oldVersion, tt.args.newVersion, tt.args.keys); got != tt.want { 164 t.Errorf("checkExcludeConfigDifference() = %v, want %v", got, tt.want) 165 } 166 }) 167 } 168 } 169 170 func TestCreateConfigurePatch(t *testing.T) { 171 v1 := ` 172 [mysqld] 173 key_buffer_size=16777216 174 max_connections=2666 175 authentication_policy=mysql_native_password, 176 back_log=5285 177 binlog_cache_size=32768 178 binlog_format=MIXED 179 binlog_order_commits=ON 180 binlog_row_image=FULL 181 connect_timeout=10 182 ` 183 v2 := ` 184 [mysqld] 185 authentication_policy=mysql_native_password, 186 back_log=5285 187 binlog_cache_size=32768 188 binlog_format=MIXED 189 binlog_order_commits=ON 190 binlog_row_image=FULL 191 connect_timeout=10 192 key_buffer_size=18874368 193 max_connections=666 194 ` 195 196 type args struct { 197 oldVersion map[string]string 198 newVersion map[string]string 199 format v1alpha1.CfgFileFormat 200 keys []string 201 enableExcludeDiff bool 202 } 203 tests := []struct { 204 name string 205 args args 206 want *ConfigPatchInfo 207 excludeDiff bool 208 wantErr bool 209 }{{ 210 name: "patchTestWithoutKeys", 211 args: args{ 212 oldVersion: map[string]string{ 213 "my.cnf": v1, 214 }, 215 newVersion: map[string]string{ 216 "my.cnf": v2, 217 }, 218 format: v1alpha1.Ini, 219 enableExcludeDiff: true, 220 }, 221 want: &ConfigPatchInfo{IsModify: true}, 222 excludeDiff: false, 223 }, { 224 name: "failedPatchTestWithoutKeys", 225 args: args{ 226 oldVersion: map[string]string{ 227 "my.cnf": v1, 228 "other.cnf": "context", 229 }, 230 newVersion: map[string]string{ 231 "my.cnf": v2, 232 "other.cnf": "context", 233 }, 234 format: v1alpha1.Ini, 235 enableExcludeDiff: true, 236 }, 237 want: &ConfigPatchInfo{IsModify: true}, 238 excludeDiff: false, 239 wantErr: true, 240 }, { 241 name: "patchTest", 242 args: args{ 243 oldVersion: map[string]string{ 244 "my.cnf": v1, 245 "other.cnf": "context", 246 }, 247 newVersion: map[string]string{ 248 "my.cnf": v2, 249 "other.cnf": "context", 250 }, 251 keys: []string{"my.cnf"}, 252 format: v1alpha1.Ini, 253 enableExcludeDiff: true, 254 }, 255 want: &ConfigPatchInfo{IsModify: true}, 256 excludeDiff: false, 257 }, { 258 name: "patchTest", 259 args: args{ 260 oldVersion: map[string]string{ 261 "my.cnf": v1, 262 "other.cnf": "context", 263 }, 264 newVersion: map[string]string{ 265 "my.cnf": v1, 266 "other.cnf": "context difference", 267 }, 268 keys: []string{"my.cnf"}, 269 format: v1alpha1.Ini, 270 enableExcludeDiff: true, 271 }, 272 want: &ConfigPatchInfo{IsModify: false}, 273 excludeDiff: true, 274 }, { 275 name: "patchTest", 276 args: args{ 277 oldVersion: map[string]string{ 278 "my.cnf": v1, 279 "other.cnf": "context", 280 }, 281 newVersion: map[string]string{ 282 "my.cnf": v2, 283 "other.cnf": "context difference", 284 }, 285 keys: []string{"my.cnf"}, 286 format: v1alpha1.Ini, 287 enableExcludeDiff: false, 288 }, 289 want: &ConfigPatchInfo{IsModify: true}, 290 excludeDiff: false, 291 }} 292 for _, tt := range tests { 293 t.Run(tt.name, func(t *testing.T) { 294 got, excludeDiff, err := CreateConfigPatch(tt.args.oldVersion, tt.args.newVersion, tt.args.format, tt.args.keys, tt.args.enableExcludeDiff) 295 if (err != nil) != tt.wantErr { 296 t.Errorf("CreateConfigPatch() error = %v, wantErr %v", err, tt.wantErr) 297 return 298 } 299 if !tt.wantErr && got.IsModify != tt.want.IsModify { 300 t.Errorf("CreateConfigPatch() got = %v, want %v", got, tt.want) 301 } 302 if excludeDiff != tt.excludeDiff { 303 t.Errorf("CreateConfigPatch() got1 = %v, want %v", excludeDiff, tt.excludeDiff) 304 } 305 }) 306 } 307 } 308 309 func TestLoadRawConfigObject(t *testing.T) { 310 getFileContentFn := func(file string) string { 311 content, _ := testdata.GetTestDataFileContent(file) 312 return string(content) 313 } 314 315 type args struct { 316 data map[string]string 317 formatConfig *v1alpha1.FormatterConfig 318 keys []string 319 } 320 tests := []struct { 321 name string 322 args args 323 wantErr bool 324 }{{ 325 name: "test", 326 args: args{ 327 data: map[string]string{"key": getFileContentFn("cue_testdata/mysql.cnf")}, 328 formatConfig: &v1alpha1.FormatterConfig{ 329 Format: v1alpha1.Ini, 330 FormatterOptions: v1alpha1.FormatterOptions{ 331 IniConfig: &v1alpha1.IniConfig{ 332 SectionName: "mysqld", 333 }}, 334 }}, 335 wantErr: false, 336 }, { 337 name: "test", 338 args: args{ 339 data: map[string]string{"key": getFileContentFn("cue_testdata/pg14.conf")}, 340 formatConfig: &v1alpha1.FormatterConfig{ 341 Format: v1alpha1.Properties, 342 }}, 343 wantErr: false, 344 }, { 345 name: "test", 346 args: args{ 347 data: map[string]string{ 348 "key": getFileContentFn("cue_testdata/pg14.conf"), 349 "key2": getFileContentFn("cue_testdata/mysql.cnf"), 350 }, 351 keys: []string{"key"}, 352 formatConfig: &v1alpha1.FormatterConfig{ 353 Format: v1alpha1.Properties, 354 }}, 355 wantErr: false, 356 }, { 357 name: "test-failed", 358 args: args{ 359 data: map[string]string{ 360 "key": getFileContentFn("cue_testdata/pg14.conf"), 361 }, 362 keys: []string{"key"}, 363 formatConfig: &v1alpha1.FormatterConfig{ 364 Format: v1alpha1.XML, 365 }}, 366 wantErr: true, 367 }} 368 for _, tt := range tests { 369 t.Run(tt.name, func(t *testing.T) { 370 _, err := LoadRawConfigObject(tt.args.data, tt.args.formatConfig, tt.args.keys) 371 if (err != nil) != tt.wantErr { 372 t.Errorf("LoadRawConfigObject() error = %v, wantErr %v", err, tt.wantErr) 373 return 374 } 375 }) 376 } 377 } 378 379 func TestTransformConfigFileToKeyValueMap(t *testing.T) { 380 mysqlConfig := ` 381 [mysqld] 382 key_buffer_size=16777216 383 log_error=/data/mysql/logs/mysql.log 384 ` 385 mongodbConfig := ` 386 systemLog: 387 logRotate: reopen 388 path: /data/mongodb/logs/mongodb.log 389 verbosity: 0 390 ` 391 tests := []struct { 392 name string 393 fileName string 394 formatConfig *v1alpha1.FormatterConfig 395 configData []byte 396 expected map[string]string 397 }{{ 398 name: "mysql-test", 399 fileName: "my.cnf", 400 formatConfig: &v1alpha1.FormatterConfig{ 401 Format: v1alpha1.Ini, 402 FormatterOptions: v1alpha1.FormatterOptions{ 403 IniConfig: &v1alpha1.IniConfig{ 404 SectionName: "mysqld", 405 }, 406 }, 407 }, 408 configData: []byte(mysqlConfig), 409 expected: map[string]string{ 410 "key_buffer_size": "16777216", 411 "log_error": "/data/mysql/logs/mysql.log", 412 }, 413 }, { 414 name: "mongodb-test", 415 fileName: "mongodb.conf", 416 formatConfig: &v1alpha1.FormatterConfig{ 417 Format: v1alpha1.YAML, 418 FormatterOptions: v1alpha1.FormatterOptions{ 419 IniConfig: &v1alpha1.IniConfig{ 420 SectionName: "default", 421 }, 422 }, 423 }, 424 configData: []byte(mongodbConfig), 425 expected: map[string]string{ 426 "systemLog.logRotate": "reopen", 427 "systemLog.path": "/data/mongodb/logs/mongodb.log", 428 "systemLog.verbosity": "0", 429 }, 430 }} 431 for _, tt := range tests { 432 t.Run(tt.name, func(t *testing.T) { 433 res, _ := TransformConfigFileToKeyValueMap(tt.fileName, tt.formatConfig, tt.configData) 434 if !reflect.DeepEqual(res, tt.expected) { 435 t.Errorf("TransformConfigFileToKeyValueMap() res = %v, res %v", res, tt.expected) 436 return 437 } 438 }) 439 } 440 }