github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/lorry/engines/redis/manager_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 redis 21 22 import ( 23 . "github.com/onsi/ginkgo/v2" 24 . "github.com/onsi/gomega" 25 "github.com/spf13/viper" 26 27 "github.com/1aal/kubeblocks/pkg/lorry/engines" 28 ) 29 30 const ( 31 // testData = `{"data":"data"}` 32 // testKey = "test" 33 // redisHost = "127.0.0.1:6379" 34 35 // userName = "kiminonawa" 36 // password = "moss" 37 // roleName = util.ReadWriteRole 38 ) 39 40 var _ = Describe("Redis DBManager", func() { 41 // Set up relevant viper config variables 42 viper.Set("KB_SERVICE_USER", "testuser") 43 viper.Set("KB_SERVICE_PASSWORD", "testpassword") 44 Context("new db manager", func() { 45 It("with rigth configurations", func() { 46 properties := engines.Properties{ 47 "url": "127.0.0.1", 48 } 49 dbManger, err := NewManager(properties) 50 Expect(err).Should(Succeed()) 51 Expect(dbManger).ShouldNot(BeNil()) 52 }) 53 54 It("with wrong configurations", func() { 55 properties := engines.Properties{ 56 "poolSize": "wrong-number", 57 } 58 dbManger, err := NewManager(properties) 59 Expect(err).Should(HaveOccurred()) 60 Expect(dbManger).Should(BeNil()) 61 }) 62 }) 63 }) 64 65 // func TestRedisInit(t *testing.T) { 66 // r, _ := mockRedisOps(t) 67 // defer r.Close() 68 // // make sure operations are inited 69 // assert.NotNil(t, r.client) 70 // assert.NotNil(t, r.OperationsMap[util.ListUsersOp]) 71 // assert.NotNil(t, r.OperationsMap[util.CreateUserOp]) 72 // assert.NotNil(t, r.OperationsMap[util.DeleteUserOp]) 73 // assert.NotNil(t, r.OperationsMap[util.DescribeUserOp]) 74 // assert.NotNil(t, r.OperationsMap[util.GrantUserRoleOp]) 75 // assert.NotNil(t, r.OperationsMap[util.RevokeUserRoleOp]) 76 // } 77 // func TestRedisInvokeCreate(t *testing.T) { 78 // r, mock := mockRedisOps(t) 79 // defer r.Close() 80 // 81 // result := OpsResult{} 82 // request := &ProbeRequest{ 83 // Data: []byte(testData), 84 // Metadata: map[string]string{"key": testKey}, 85 // Operation: util.CreateOperation, 86 // } 87 // // mock expectation 88 // mock.ExpectDo("SET", testKey, testData).SetVal("ok") 89 // 90 // // invoke 91 // bindingRes, err := r.Invoke(context.TODO(), request) 92 // assert.Equal(t, nil, err) 93 // assert.NotNil(t, bindingRes) 94 // assert.NotNil(t, bindingRes.Data) 95 // 96 // err = json.Unmarshal(bindingRes.Data, &result) 97 // assert.Nil(t, err) 98 // assert.Equal(t, util.RespEveSucc, result[util.RespFieldEvent], result[util.RespFieldMessage]) 99 // } 100 // 101 // func TestRedisInvokeGet(t *testing.T) { 102 // r, mock := mockRedisOps(t) 103 // defer r.Close() 104 // 105 // opsResult := OpsResult{} 106 // request := &ProbeRequest{ 107 // Metadata: map[string]string{"key": testKey}, 108 // Operation: util.GetOperation, 109 // } 110 // // mock expectation, set to nil 111 // mock.ExpectDo("GET", testKey).RedisNil() 112 // mock.ExpectDo("GET", testKey).SetVal(testData) 113 // 114 // // invoke create 115 // bindingRes, err := r.Invoke(context.TODO(), request) 116 // assert.Nil(t, err) 117 // assert.NotNil(t, bindingRes) 118 // assert.NotNil(t, bindingRes.Data) 119 // err = json.Unmarshal(bindingRes.Data, &opsResult) 120 // assert.Nil(t, err) 121 // assert.Equal(t, util.RespEveFail, opsResult[util.RespFieldEvent]) 122 // 123 // // invoke one more time 124 // bindingRes, err = r.Invoke(context.TODO(), request) 125 // assert.Nil(t, err) 126 // assert.NotNil(t, bindingRes.Data) 127 // err = json.Unmarshal(bindingRes.Data, &opsResult) 128 // assert.Nil(t, err) 129 // assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent]) 130 // var o1 interface{} 131 // _ = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &o1) 132 // assert.Equal(t, testData, o1) 133 // } 134 // 135 // func TestRedisInvokeDelete(t *testing.T) { 136 // r, mock := mockRedisOps(t) 137 // defer r.Close() 138 // 139 // opsResult := OpsResult{} 140 // request := &ProbeRequest{ 141 // Metadata: map[string]string{"key": testKey}, 142 // Operation: util.DeleteOperation, 143 // } 144 // // mock expectation, set to err 145 // mock.ExpectDo("DEL", testKey).SetVal("ok") 146 // 147 // // invoke delete 148 // bindingRes, err := r.Invoke(context.TODO(), request) 149 // assert.Nil(t, err) 150 // assert.NotNil(t, bindingRes) 151 // assert.NotNil(t, bindingRes.Data) 152 // err = json.Unmarshal(bindingRes.Data, &opsResult) 153 // assert.Nil(t, err) 154 // assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent]) 155 // } 156 // 157 // func TestRedisGetRoles(t *testing.T) { 158 // r, mock := mockRedisOps(t) 159 // defer r.Close() 160 // 161 // opsResult := OpsResult{} 162 // request := &ProbeRequest{ 163 // Operation: util.GetRoleOperation, 164 // } 165 // 166 // // mock expectation, set to err 167 // mock.ExpectInfo("Replication").SetVal("role:master\r\nconnected_slaves:1") 168 // mock.ExpectInfo("Replication").SetVal("role:slave\r\nmaster_port:6379") 169 // // invoke request 170 // bindingRes, err := r.Invoke(context.TODO(), request) 171 // assert.Nil(t, err) 172 // assert.NotNil(t, bindingRes) 173 // assert.NotNil(t, bindingRes.Data) 174 // err = json.Unmarshal(bindingRes.Data, &opsResult) 175 // assert.Nil(t, err) 176 // assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent]) 177 // assert.Equal(t, PRIMARY, opsResult["role"]) 178 // 179 // // invoke one more time 180 // bindingRes, err = r.Invoke(context.TODO(), request) 181 // assert.Nil(t, err) 182 // err = json.Unmarshal(bindingRes.Data, &opsResult) 183 // assert.Nil(t, err) 184 // assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent]) 185 // assert.Equal(t, SECONDARY, opsResult["role"]) 186 // } 187 // 188 // func TestRedisAccounts(t *testing.T) { 189 // // prepare 190 // r, mock := mockRedisOps(t) 191 // defer r.Close() 192 // 193 // ctx := context.TODO() 194 // // list accounts 195 // t.Run("List Accounts", func(t *testing.T) { 196 // mock.ExpectDo("ACL", "USERS").SetVal([]string{"ape", "default", "kbadmin"}) 197 // 198 // response, err := r.Invoke(ctx, &ProbeRequest{ 199 // Operation: util.ListUsersOp, 200 // }) 201 // 202 // assert.Nil(t, err) 203 // assert.NotNil(t, response) 204 // assert.NotNil(t, response.Data) 205 // // parse result 206 // opsResult := OpsResult{} 207 // _ = json.Unmarshal(response.Data, &opsResult) 208 // assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage]) 209 // 210 // users := make([]util.UserInfo, 0) 211 // err = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &users) 212 // assert.Nil(t, err) 213 // assert.NotEmpty(t, users) 214 // user := users[0] 215 // assert.Equal(t, "ape", user.UserName) 216 // mock.ClearExpect() 217 // }) 218 // 219 // // create accounts 220 // t.Run("Create Accounts", func(t *testing.T) { 221 // 222 // var ( 223 // err error 224 // opsResult = OpsResult{} 225 // response *ProbeResponse 226 // request = &ProbeRequest{ 227 // Operation: util.CreateUserOp, 228 // } 229 // ) 230 // 231 // testCases := []redisTestCase{ 232 // { 233 // testName: "emptymeta", 234 // testMetaData: map[string]string{}, 235 // expectEveType: util.RespEveFail, 236 // expectEveMsg: ErrNoUserName.Error(), 237 // }, 238 // { 239 // testName: "nousername", 240 // testMetaData: map[string]string{"password": "moli"}, 241 // expectEveType: util.RespEveFail, 242 // expectEveMsg: ErrNoUserName.Error(), 243 // }, 244 // { 245 // testName: "nopasswd", 246 // testMetaData: map[string]string{"userName": "namae"}, 247 // expectEveType: util.RespEveFail, 248 // expectEveMsg: ErrNoPassword.Error(), 249 // }, 250 // { 251 // testName: "validInput", 252 // testMetaData: map[string]string{ 253 // "userName": userName, 254 // "password": password, 255 // }, 256 // expectEveType: util.RespEveSucc, 257 // expectEveMsg: fmt.Sprintf("created user: %s", userName), 258 // }, 259 // } 260 // // mock a user 261 // mock.ExpectDo("ACL", "SETUSER", userName, ">"+password).SetVal("ok") 262 // 263 // for _, accTest := range testCases { 264 // request.Metadata = accTest.testMetaData 265 // response, err = r.Invoke(ctx, request) 266 // assert.Nil(t, err) 267 // assert.NotNil(t, response.Data) 268 // err = json.Unmarshal(response.Data, &opsResult) 269 // assert.Nil(t, err) 270 // assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage]) 271 // assert.Contains(t, opsResult[util.RespFieldMessage], accTest.expectEveMsg) 272 // } 273 // mock.ClearExpect() 274 // }) 275 // // grant and revoke role 276 // t.Run("Grant Accounts", func(t *testing.T) { 277 // 278 // var ( 279 // err error 280 // opsResult = OpsResult{} 281 // response *ProbeResponse 282 // ) 283 // 284 // testCases := []redisTestCase{ 285 // { 286 // testName: "emptymeta", 287 // testMetaData: map[string]string{}, 288 // expectEveType: util.RespEveFail, 289 // expectEveMsg: ErrNoUserName.Error(), 290 // }, 291 // { 292 // testName: "nousername", 293 // testMetaData: map[string]string{"password": "moli"}, 294 // expectEveType: util.RespEveFail, 295 // expectEveMsg: ErrNoUserName.Error(), 296 // }, 297 // { 298 // testName: "norolename", 299 // testMetaData: map[string]string{"userName": "namae"}, 300 // expectEveType: util.RespEveFail, 301 // expectEveMsg: ErrNoRoleName.Error(), 302 // }, 303 // { 304 // testName: "invalidRoleName", 305 // testMetaData: map[string]string{"userName": "namae", "roleName": "superman"}, 306 // expectEveType: util.RespEveFail, 307 // expectEveMsg: ErrInvalidRoleName.Error(), 308 // }, 309 // { 310 // testName: "validInput", 311 // testMetaData: map[string]string{ 312 // "userName": userName, 313 // "roleName": (string)(roleName), 314 // }, 315 // expectEveType: util.RespEveSucc, 316 // }, 317 // } 318 // 319 // for _, ops := range []util.OperationKind{util.GrantUserRoleOp, util.RevokeUserRoleOp} { 320 // // mock exepctation 321 // args := tokenizeCmd2Args(fmt.Sprintf("ACL SETUSER %s %s", userName, r.role2Priv(ops, (string)(roleName)))) 322 // mock.ExpectDo(args...).SetVal("ok") 323 // 324 // request := &ProbeRequest{ 325 // Operation: ops, 326 // } 327 // for _, accTest := range testCases { 328 // request.Metadata = accTest.testMetaData 329 // response, err = r.Invoke(ctx, request) 330 // assert.Nil(t, err) 331 // assert.NotNil(t, response.Data) 332 // err = json.Unmarshal(response.Data, &opsResult) 333 // assert.Nil(t, err) 334 // assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage]) 335 // if len(accTest.expectEveMsg) > 0 { 336 // assert.Contains(t, accTest.expectEveMsg, opsResult[util.RespFieldMessage]) 337 // } 338 // } 339 // } 340 // mock.ClearExpect() 341 // }) 342 // 343 // // desc accounts 344 // t.Run("Desc Accounts", func(t *testing.T) { 345 // var ( 346 // err error 347 // opsResult = OpsResult{} 348 // response *ProbeResponse 349 // request = &ProbeRequest{ 350 // Operation: util.DescribeUserOp, 351 // } 352 // // mock a user, describing it as an array of interface{} 353 // userInfo = []interface{}{ 354 // "flags", 355 // []interface{}{"on"}, 356 // "passwords", 357 // []interface{}{"mock-password"}, 358 // "commands", 359 // "+@all", 360 // "keys", 361 // "~*", 362 // "channels", 363 // "", 364 // "selectors", 365 // []interface{}{}, 366 // } 367 // 368 // userInfoMap = map[string]interface{}{ 369 // "flags": []interface{}{"on"}, 370 // "passwords": []interface{}{"mock-password"}, 371 // "commands": "+@all", 372 // "keys": "~*", 373 // "channels": "", 374 // "selectors": []interface{}{}, 375 // } 376 // ) 377 // 378 // testCases := []redisTestCase{ 379 // { 380 // testName: "emptymeta", 381 // testMetaData: map[string]string{}, 382 // expectEveType: util.RespEveFail, 383 // expectEveMsg: ErrNoUserName.Error(), 384 // }, 385 // { 386 // testName: "nousername", 387 // testMetaData: map[string]string{"password": "moli"}, 388 // expectEveType: util.RespEveFail, 389 // expectEveMsg: ErrNoUserName.Error(), 390 // }, 391 // { 392 // testName: "validInputButNil", 393 // testMetaData: map[string]string{ 394 // "userName": userName, 395 // }, 396 // expectEveType: util.RespEveFail, 397 // expectEveMsg: "redis: nil", 398 // }, 399 // { 400 // testName: "validInput", 401 // testMetaData: map[string]string{ 402 // "userName": userName, 403 // }, 404 // expectEveType: util.RespEveSucc, 405 // }, 406 // { 407 // testName: "validInputAsMap", 408 // testMetaData: map[string]string{ 409 // "userName": userName, 410 // }, 411 // expectEveType: util.RespEveSucc, 412 // }, 413 // } 414 // 415 // mock.ExpectDo("ACL", "GETUSER", userName).RedisNil() 416 // mock.ExpectDo("ACL", "GETUSER", userName).SetVal(userInfo) 417 // mock.ExpectDo("ACL", "GETUSER", userName).SetVal(userInfoMap) 418 // 419 // for _, accTest := range testCases { 420 // request.Metadata = accTest.testMetaData 421 // response, err = r.Invoke(ctx, request) 422 // assert.Nil(t, err) 423 // assert.NotNil(t, response.Data) 424 // err = json.Unmarshal(response.Data, &opsResult) 425 // assert.Nil(t, err) 426 // assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage]) 427 // if len(accTest.expectEveMsg) > 0 { 428 // assert.Contains(t, opsResult[util.RespFieldMessage], accTest.expectEveMsg) 429 // } 430 // if util.RespEveSucc == opsResult[util.RespFieldEvent] { 431 // // parse user info 432 // users := make([]util.UserInfo, 0) 433 // err = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &users) 434 // assert.Nil(t, err) 435 // assert.Len(t, users, 1) 436 // user := users[0] 437 // assert.Equal(t, userName, user.UserName) 438 // assert.True(t, util.SuperUserRole.EqualTo(user.RoleName)) 439 // } 440 // } 441 // mock.ClearExpect() 442 // }) 443 // // delete accounts 444 // t.Run("Delete Accounts", func(t *testing.T) { 445 // 446 // var ( 447 // err error 448 // opsResult = OpsResult{} 449 // response *ProbeResponse 450 // request = &ProbeRequest{ 451 // Operation: util.DeleteUserOp, 452 // } 453 // ) 454 // 455 // testCases := []redisTestCase{ 456 // { 457 // testName: "emptymeta", 458 // testMetaData: map[string]string{}, 459 // expectEveType: util.RespEveFail, 460 // expectEveMsg: ErrNoUserName.Error(), 461 // }, 462 // { 463 // testName: "nousername", 464 // testMetaData: map[string]string{"password": "moli"}, 465 // expectEveType: util.RespEveFail, 466 // expectEveMsg: ErrNoUserName.Error(), 467 // }, 468 // { 469 // testName: "validInput", 470 // testMetaData: map[string]string{ 471 // "userName": userName, 472 // }, 473 // expectEveType: util.RespEveSucc, 474 // expectEveMsg: fmt.Sprintf("deleted user: %s", userName), 475 // }, 476 // } 477 // // mock a user 478 // mock.ExpectDo("ACL", "DELUSER", userName).SetVal("ok") 479 // 480 // for _, accTest := range testCases { 481 // request.Metadata = accTest.testMetaData 482 // response, err = r.Invoke(ctx, request) 483 // assert.Nil(t, err) 484 // assert.NotNil(t, response.Data) 485 // err = json.Unmarshal(response.Data, &opsResult) 486 // assert.Nil(t, err) 487 // assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage]) 488 // assert.Contains(t, opsResult[util.RespFieldMessage], accTest.expectEveMsg) 489 // } 490 // mock.ClearExpect() 491 // }) 492 // 493 // t.Run("RoleName Conversion", func(t *testing.T) { 494 // type roleTestCase struct { 495 // roleName util.RoleType 496 // redisPrivs string 497 // } 498 // grantTestCases := []roleTestCase{ 499 // { 500 // util.SuperUserRole, 501 // "+@all allkeys", 502 // }, 503 // { 504 // util.ReadWriteRole, 505 // "-@all +@write +@read allkeys", 506 // }, 507 // { 508 // util.ReadOnlyRole, 509 // "-@all +@read allkeys", 510 // }, 511 // } 512 // for _, test := range grantTestCases { 513 // cmd := r.role2Priv(util.GrantUserRoleOp, (string)(test.roleName)) 514 // assert.Equal(t, test.redisPrivs, cmd) 515 // 516 // // allkeys -> ~* 517 // cmd = strings.Replace(cmd, "allkeys", "~*", 1) 518 // inferredRole := r.priv2Role(cmd) 519 // assert.Equal(t, test.roleName, inferredRole) 520 // } 521 // 522 // revokeTestCases := []roleTestCase{ 523 // { 524 // util.SuperUserRole, 525 // "-@all allkeys", 526 // }, 527 // { 528 // util.ReadWriteRole, 529 // "-@all -@write -@read allkeys", 530 // }, 531 // { 532 // util.ReadOnlyRole, 533 // "-@all -@read allkeys", 534 // }, 535 // } 536 // for _, test := range revokeTestCases { 537 // cmd := r.role2Priv(util.RevokeUserRoleOp, (string)(test.roleName)) 538 // assert.Equal(t, test.redisPrivs, cmd) 539 // } 540 // }) 541 // // list accounts 542 // t.Run("List System Accounts", func(t *testing.T) { 543 // mock.ExpectDo("ACL", "USERS").SetVal([]string{"ape", "default", "kbadmin"}) 544 // 545 // response, err := r.Invoke(ctx, &ProbeRequest{ 546 // Operation: util.ListSystemAccountsOp, 547 // }) 548 // 549 // assert.Nil(t, err) 550 // assert.NotNil(t, response) 551 // assert.NotNil(t, response.Data) 552 // // parse result 553 // opsResult := OpsResult{} 554 // _ = json.Unmarshal(response.Data, &opsResult) 555 // assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage]) 556 // 557 // users := []string{} 558 // err = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &users) 559 // assert.Nil(t, err) 560 // assert.NotEmpty(t, users) 561 // assert.Len(t, users, 2) 562 // assert.Contains(t, users, "kbadmin") 563 // assert.Contains(t, users, "default") 564 // mock.ClearExpect() 565 // }) 566 // } 567 // 568 // func mockRedisOps(t *testing.T) (*Redis, redismock.ClientMock) { 569 // client, mock := redismock.NewClientMock() 570 // viper.SetDefault("KB_ROLECHECK_DELAY", "0") 571 // 572 // if client == nil || mock == nil { 573 // t.Fatalf("failed to mock a redis client") 574 // return nil, nil 575 // } 576 // r := &Redis{} 577 // development, _ := zap.NewDevelopment() 578 // r.Logger = zapr.NewLogger(development) 579 // r.client = client 580 // r.ctx, r.cancel = context.WithCancel(context.Background()) 581 // _ = r.Init(nil) 582 // r.DBPort = 6379 583 // return r, mock 584 // } 585 //