github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/lorry/client/client.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 client 21 22 import ( 23 context "context" 24 "errors" 25 "net/http" 26 27 corev1 "k8s.io/api/core/v1" 28 29 . "github.com/1aal/kubeblocks/pkg/lorry/util" 30 ) 31 32 // HACK: for unit test only. 33 var mockClient Client 34 var mockClientError error 35 36 func SetMockClient(cli Client, err error) { 37 mockClient = cli 38 mockClientError = err 39 } 40 41 func UnsetMockClient() { 42 mockClient = nil 43 mockClientError = nil 44 } 45 46 func NewClient(characterType string, pod corev1.Pod) (Client, error) { 47 if mockClient != nil || mockClientError != nil { 48 return mockClient, mockClientError 49 } 50 return NewHTTPClientWithPod(&pod) 51 } 52 53 type Requester interface { 54 Request(ctx context.Context, operation, method string, req map[string]any) (map[string]any, error) 55 } 56 type lorryClient struct { 57 requester Requester 58 } 59 60 func (cli *lorryClient) GetRole(ctx context.Context) (string, error) { 61 resp, err := cli.Request(ctx, string(GetRoleOperation), http.MethodGet, nil) 62 if err != nil { 63 return "", err 64 } 65 66 role, ok := resp["role"] 67 if !ok { 68 return "", nil 69 } 70 71 return role.(string), nil 72 } 73 74 func (cli *lorryClient) CreateUser(ctx context.Context, userName, password string) error { 75 parameters := map[string]any{ 76 "userName": userName, 77 "password": password, 78 } 79 req := map[string]any{"parameters": parameters} 80 _, err := cli.Request(ctx, string(CreateUserOp), http.MethodPost, req) 81 return err 82 } 83 84 func (cli *lorryClient) DeleteUser(ctx context.Context, userName string) error { 85 parameters := map[string]any{ 86 "userName": userName, 87 } 88 req := map[string]any{"parameters": parameters} 89 _, err := cli.Request(ctx, string(DeleteUserOp), http.MethodPost, req) 90 return err 91 } 92 93 func (cli *lorryClient) DescribeUser(ctx context.Context, userName string) (map[string]any, error) { 94 parameters := map[string]any{ 95 "userName": userName, 96 } 97 req := map[string]any{"parameters": parameters} 98 resp, err := cli.Request(ctx, string(DescribeUserOp), http.MethodGet, req) 99 if err != nil { 100 return nil, err 101 } 102 user, ok := resp["user"] 103 if !ok { 104 return nil, nil 105 } 106 107 return user.(map[string]any), nil 108 } 109 110 func (cli *lorryClient) GrantUserRole(ctx context.Context, userName, roleName string) error { 111 parameters := map[string]any{ 112 "userName": userName, 113 "roleName": roleName, 114 } 115 req := map[string]any{"parameters": parameters} 116 _, err := cli.Request(ctx, string(GrantUserRoleOp), http.MethodPost, req) 117 return err 118 } 119 120 func (cli *lorryClient) RevokeUserRole(ctx context.Context, userName, roleName string) error { 121 parameters := map[string]any{ 122 "userName": userName, 123 "roleName": roleName, 124 } 125 req := map[string]any{"parameters": parameters} 126 _, err := cli.Request(ctx, string(RevokeUserRoleOp), http.MethodPost, req) 127 return err 128 } 129 130 // ListUsers lists all normal users created 131 func (cli *lorryClient) ListUsers(ctx context.Context) ([]map[string]any, error) { 132 resp, err := cli.Request(ctx, string(ListUsersOp), http.MethodGet, nil) 133 if err != nil { 134 return nil, err 135 } 136 users, ok := resp["users"] 137 if !ok { 138 return nil, nil 139 } 140 return convertToArrayOfMap(users) 141 } 142 143 // ListSystemAccounts lists all system accounts created 144 func (cli *lorryClient) ListSystemAccounts(ctx context.Context) ([]map[string]any, error) { 145 resp, err := cli.Request(ctx, string(ListSystemAccountsOp), http.MethodGet, nil) 146 if err != nil { 147 return nil, err 148 } 149 systemAccounts, ok := resp["systemAccounts"] 150 if !ok { 151 return nil, nil 152 } 153 return convertToArrayOfMap(systemAccounts) 154 } 155 156 // JoinMember sends a join member operation request to Lorry, located on the target pod that is about to join. 157 func (cli *lorryClient) JoinMember(ctx context.Context) error { 158 _, err := cli.Request(ctx, string(JoinMemberOperation), http.MethodPost, nil) 159 return err 160 } 161 162 // LeaveMember sends a Leave member operation request to Lorry, located on the target pod that is about to leave. 163 func (cli *lorryClient) LeaveMember(ctx context.Context) error { 164 _, err := cli.Request(ctx, string(LeaveMemberOperation), http.MethodPost, nil) 165 return err 166 } 167 168 func (cli *lorryClient) Request(ctx context.Context, operation, method string, req map[string]any) (map[string]any, error) { 169 if cli.requester == nil { 170 return nil, errors.New("lorry client's requester must be set") 171 } 172 return cli.requester.Request(ctx, operation, method, req) 173 }