vitess.io/vitess@v0.16.2/go/vt/vtadmin/http/keyspaces.go (about) 1 /* 2 Copyright 2021 The Vitess 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 http 18 19 import ( 20 "context" 21 "encoding/json" 22 "strings" 23 24 "github.com/gorilla/mux" 25 26 "vitess.io/vitess/go/vt/vtadmin/errors" 27 28 vtadminpb "vitess.io/vitess/go/vt/proto/vtadmin" 29 vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" 30 ) 31 32 // CreateKeyspace implements the http wrapper for POST /keyspace/{cluster_id}. 33 func CreateKeyspace(ctx context.Context, r Request, api *API) *JSONResponse { 34 vars := mux.Vars(r.Request) 35 decoder := json.NewDecoder(r.Body) 36 defer r.Body.Close() 37 38 var req vtctldatapb.CreateKeyspaceRequest 39 if err := decoder.Decode(&req); err != nil { 40 return NewJSONResponse(nil, &errors.BadRequest{ 41 Err: err, 42 }) 43 } 44 45 resp, err := api.server.CreateKeyspace(ctx, &vtadminpb.CreateKeyspaceRequest{ 46 ClusterId: vars["cluster_id"], 47 Options: &req, 48 }) 49 return NewJSONResponse(resp, err) 50 } 51 52 // DeleteKeyspace implements the http wrapper for DELETE /keyspace/{cluster_id}/{name}[?recursive=]. 53 func DeleteKeyspace(ctx context.Context, r Request, api *API) *JSONResponse { 54 vars := mux.Vars(r.Request) 55 recursive, err := r.ParseQueryParamAsBool("recursive", false) 56 if err != nil { 57 return NewJSONResponse(nil, err) 58 } 59 60 resp, err := api.server.DeleteKeyspace(ctx, &vtadminpb.DeleteKeyspaceRequest{ 61 ClusterId: vars["cluster_id"], 62 Options: &vtctldatapb.DeleteKeyspaceRequest{ 63 Keyspace: vars["name"], 64 Recursive: recursive, 65 }, 66 }) 67 return NewJSONResponse(resp, err) 68 } 69 70 // GetKeyspace implements the http wrapper for /keyspace/{cluster_id}/{name}. 71 func GetKeyspace(ctx context.Context, r Request, api *API) *JSONResponse { 72 vars := mux.Vars(r.Request) 73 keyspace, err := api.server.GetKeyspace(ctx, &vtadminpb.GetKeyspaceRequest{ 74 ClusterId: vars["cluster_id"], 75 Keyspace: vars["name"], 76 }) 77 78 return NewJSONResponse(keyspace, err) 79 } 80 81 // GetKeyspaces implements the http wrapper for /keyspaces[?cluster=[&cluster=]]. 82 func GetKeyspaces(ctx context.Context, r Request, api *API) *JSONResponse { 83 keyspaces, err := api.server.GetKeyspaces(ctx, &vtadminpb.GetKeyspacesRequest{ 84 ClusterIds: r.URL.Query()["cluster"], 85 }) 86 87 return NewJSONResponse(keyspaces, err) 88 } 89 90 // RebuildKeyspaceGraph implements the http wrapper for /keyspaces/{cluster_id}/{name}/rebuild_keyspace_graph 91 func RebuildKeyspaceGraph(ctx context.Context, r Request, api *API) *JSONResponse { 92 vars := mux.Vars(r.Request) 93 decoder := json.NewDecoder(r.Body) 94 defer r.Body.Close() 95 96 var params struct { 97 Cells string `json:"cells"` 98 AllowPartial bool `json:"allow_partial"` 99 } 100 101 if err := decoder.Decode(¶ms); err != nil { 102 return NewJSONResponse(nil, &errors.BadRequest{ 103 Err: err, 104 }) 105 } 106 107 res, err := api.server.RebuildKeyspaceGraph(ctx, &vtadminpb.RebuildKeyspaceGraphRequest{ 108 ClusterId: vars["cluster_id"], 109 Keyspace: vars["name"], 110 Cells: strings.Split(params.Cells, ","), 111 AllowPartial: params.AllowPartial, 112 }) 113 114 return NewJSONResponse(res, err) 115 } 116 117 // RemoveKeyspaceCell implements the http wrapper for /keyspaces/{cluster_id}/{name}/remove_keyspace_cell 118 func RemoveKeyspaceCell(ctx context.Context, r Request, api *API) *JSONResponse { 119 vars := mux.Vars(r.Request) 120 decoder := json.NewDecoder(r.Body) 121 defer r.Body.Close() 122 123 var params struct { 124 Cell string `json:"cell"` 125 Force bool `json:"force"` 126 Recursive bool `json:"recursive"` 127 } 128 129 if err := decoder.Decode(¶ms); err != nil { 130 return NewJSONResponse(nil, &errors.BadRequest{ 131 Err: err, 132 }) 133 } 134 135 res, err := api.server.RemoveKeyspaceCell(ctx, &vtadminpb.RemoveKeyspaceCellRequest{ 136 ClusterId: vars["cluster_id"], 137 Keyspace: vars["name"], 138 Cell: params.Cell, 139 Force: params.Force, 140 Recursive: params.Recursive, 141 }) 142 143 return NewJSONResponse(res, err) 144 } 145 146 // ValidateKeyspace validates that all nodes reachable from the specified keyspace are consistent. 147 func ValidateKeyspace(ctx context.Context, r Request, api *API) *JSONResponse { 148 vars := mux.Vars(r.Request) 149 decoder := json.NewDecoder(r.Body) 150 defer r.Body.Close() 151 152 var result struct { 153 PingTablets bool `json:"pingTablets"` 154 } 155 156 if err := decoder.Decode(&result); err != nil { 157 return NewJSONResponse(nil, &errors.BadRequest{ 158 Err: err, 159 }) 160 } 161 162 res, err := api.server.ValidateKeyspace(ctx, &vtadminpb.ValidateKeyspaceRequest{ 163 Keyspace: vars["name"], 164 ClusterId: vars["cluster_id"], 165 PingTablets: result.PingTablets, 166 }) 167 168 return NewJSONResponse(res, err) 169 } 170 171 // ValidateKeyspace validates that all nodes reachable from the specified keyspace are consistent. 172 func ValidateSchemaKeyspace(ctx context.Context, r Request, api *API) *JSONResponse { 173 vars := mux.Vars(r.Request) 174 175 res, err := api.server.ValidateSchemaKeyspace(ctx, &vtadminpb.ValidateSchemaKeyspaceRequest{ 176 Keyspace: vars["name"], 177 ClusterId: vars["cluster_id"], 178 }) 179 180 return NewJSONResponse(res, err) 181 } 182 183 // ValidateVersionKeyspace validates that the version on the primary of shard 0 matches all of the other tablets in the keyspace. 184 func ValidateVersionKeyspace(ctx context.Context, r Request, api *API) *JSONResponse { 185 vars := mux.Vars(r.Request) 186 187 res, err := api.server.ValidateVersionKeyspace(ctx, &vtadminpb.ValidateVersionKeyspaceRequest{ 188 Keyspace: vars["name"], 189 ClusterId: vars["cluster_id"], 190 }) 191 192 return NewJSONResponse(res, err) 193 }