github.com/polarismesh/polaris@v1.17.8/test/integrate/http/instance.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package http 19 20 import ( 21 "bytes" 22 "errors" 23 "fmt" 24 "io" 25 "reflect" 26 27 "github.com/golang/protobuf/jsonpb" 28 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 29 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 30 ) 31 32 /** 33 * @brief 实例数组转JSON 34 */ 35 func JSONFromInstances(instances []*apiservice.Instance) (*bytes.Buffer, error) { 36 m := jsonpb.Marshaler{Indent: " "} 37 38 buffer := bytes.NewBuffer([]byte{}) 39 40 buffer.Write([]byte("[")) 41 for index, instance := range instances { 42 if index > 0 { 43 buffer.Write([]byte(",\n")) 44 } 45 err := m.Marshal(buffer, instance) 46 if err != nil { 47 return nil, err 48 } 49 } 50 51 buffer.Write([]byte("]")) 52 return buffer, nil 53 } 54 55 /** 56 * @brief 创建实例 57 */ 58 func (c *Client) CreateInstances(instances []*apiservice.Instance) (*apiservice.BatchWriteResponse, error) { 59 fmt.Printf("\ncreate instances\n") 60 61 url := fmt.Sprintf("http://%v/naming/%v/instances", c.Address, c.Version) 62 63 body, err := JSONFromInstances(instances) 64 if err != nil { 65 fmt.Printf("%v\n", err) 66 return nil, err 67 } 68 69 response, err := c.SendRequest("POST", url, body) 70 if err != nil { 71 fmt.Printf("%v\n", err) 72 return nil, err 73 } 74 75 ret, err := GetBatchWriteResponse(response) 76 if err != nil { 77 fmt.Printf("%v\n", err) 78 return ret, err 79 } 80 81 return checkCreateInstancesResponse(ret, instances) 82 } 83 84 /** 85 * @brief 删除实例 86 */ 87 func (c *Client) DeleteInstances(instances []*apiservice.Instance) error { 88 fmt.Printf("\ndelete instances\n") 89 90 url := fmt.Sprintf("http://%v/naming/%v/instances/delete", c.Address, c.Version) 91 92 body, err := JSONFromInstances(instances) 93 if err != nil { 94 fmt.Printf("%v\n", err) 95 return err 96 } 97 98 response, err := c.SendRequest("POST", url, body) 99 if err != nil { 100 fmt.Printf("%v\n", err) 101 return err 102 } 103 104 _, err = GetBatchWriteResponse(response) 105 if err != nil { 106 if err == io.EOF { 107 return nil 108 } 109 110 fmt.Printf("%v\n", err) 111 return err 112 } 113 114 return nil 115 } 116 117 /** 118 * @brief 更新实例 119 */ 120 func (c *Client) UpdateInstances(instances []*apiservice.Instance) error { 121 fmt.Printf("\nupdate instances\n") 122 123 url := fmt.Sprintf("http://%v/naming/%v/instances", c.Address, c.Version) 124 125 body, err := JSONFromInstances(instances) 126 if err != nil { 127 fmt.Printf("%v\n", err) 128 return err 129 } 130 131 response, err := c.SendRequest("PUT", url, body) 132 if err != nil { 133 fmt.Printf("%v\n", err) 134 return err 135 } 136 137 _, err = GetBatchWriteResponse(response) 138 if err != nil { 139 if err == io.EOF { 140 return nil 141 } 142 143 fmt.Printf("%v\n", err) 144 return err 145 } 146 147 return nil 148 } 149 150 /** 151 * @brief 查询实例 152 */ 153 func (c *Client) GetInstances(instances []*apiservice.Instance) error { 154 fmt.Printf("\nget instances\n") 155 156 url := fmt.Sprintf("http://%v/naming/%v/instances", c.Address, c.Version) 157 158 params := map[string][]interface{}{ 159 "service": {instances[0].GetService().GetValue()}, 160 "namespace": {instances[0].GetNamespace().GetValue()}, 161 } 162 163 url = c.CompleteURL(url, params) 164 response, err := c.SendRequest("GET", url, nil) 165 if err != nil { 166 return err 167 } 168 169 ret, err := GetBatchQueryResponse(response) 170 if err != nil { 171 fmt.Printf("%v\n", err) 172 return err 173 } 174 175 if ret.GetCode() == nil || ret.GetCode().GetValue() != uint32(apimodel.Code_ExecuteSuccess) { 176 return errors.New("invalid batch code") 177 } 178 179 instancesSize := len(instances) 180 181 if ret.GetAmount() == nil || ret.GetAmount().GetValue() != uint32(instancesSize) { 182 return fmt.Errorf("invalid batch amount, expect %d, obtain %v", instancesSize, ret.GetAmount()) 183 } 184 185 if ret.GetSize() == nil || ret.GetSize().GetValue() != uint32(instancesSize) { 186 return errors.New("invalid batch size") 187 } 188 189 collection := make(map[string]*apiservice.Instance) 190 for _, instance := range instances { 191 collection[instance.GetId().GetValue()] = instance 192 } 193 194 items := ret.GetInstances() 195 if items == nil || len(items) != instancesSize { 196 return errors.New("invalid batch instances") 197 } 198 199 for _, item := range items { 200 if correctItem, ok := collection[item.GetId().GetValue()]; ok { 201 if result := compareInstance(correctItem, item); !result { 202 return fmt.Errorf("invalid instance %v %v", correctItem, item) 203 } 204 } else { 205 return fmt.Errorf("instance %v not found", item.GetId().GetValue()) 206 } 207 } 208 return nil 209 } 210 211 /** 212 * @brief 检查创建实例的回复 213 */ 214 func checkCreateInstancesResponse(ret *apiservice.BatchWriteResponse, instances []*apiservice.Instance) ( 215 *apiservice.BatchWriteResponse, error) { 216 217 switch { 218 case ret.GetCode().GetValue() != uint32(apimodel.Code_ExecuteSuccess): 219 return nil, errors.New("invalid batch code") 220 case ret.GetSize().GetValue() != uint32(len(instances)): 221 return nil, errors.New("invalid batch size") 222 case len(ret.GetResponses()) != len(instances): 223 return nil, errors.New("invalid batch response") 224 } 225 226 return ret, checkInstancesResponseEntry(ret, instances) 227 } 228 229 /** 230 * @brief 检查创建实例每个实例的信息 231 */ 232 func checkInstancesResponseEntry(ret *apiservice.BatchWriteResponse, instances []*apiservice.Instance) error { 233 items := ret.GetResponses() 234 for index, item := range items { 235 instance := item.GetInstance() 236 switch { 237 case item.GetCode().GetValue() != uint32(apimodel.Code_ExecuteSuccess): 238 return errors.New("invalid code") 239 case item.GetInstance() == nil: 240 return errors.New("empty instance") 241 case item.GetInstance().GetId().GetValue() == "": 242 return errors.New("invalid instance id") 243 case instance.GetService().GetValue() != instances[index].GetService().GetValue(): 244 return errors.New("invalid service") 245 case instance.GetNamespace().GetValue() != instances[index].GetNamespace().GetValue(): 246 return errors.New("invalid namespace") 247 case instance.GetHost().GetValue() != instances[index].GetHost().GetValue(): 248 return errors.New("invalid host") 249 case instance.GetPort().GetValue() != instances[index].GetPort().GetValue(): 250 return errors.New("invalid port") 251 } 252 } 253 254 return nil 255 } 256 257 /** 258 * @brief 比较instance是否相等 259 */ 260 func compareInstance(correctItem *apiservice.Instance, item *apiservice.Instance) bool { 261 // #lizard forgives 262 correctID := correctItem.GetId().GetValue() 263 correctService := correctItem.GetService().GetValue() 264 correctNamespace := correctItem.GetNamespace().GetValue() 265 correctHost := correctItem.GetHost().GetValue() 266 correctPort := correctItem.GetPort().GetValue() 267 correctProtocol := correctItem.GetProtocol().GetValue() 268 correctVersion := correctItem.GetVersion().GetValue() 269 correctPriority := correctItem.GetPriority().GetValue() 270 correctWeight := correctItem.GetWeight().GetValue() 271 correctHealthType := correctItem.GetHealthCheck().GetType() 272 correctHealthTTL := correctItem.GetHealthCheck().GetHeartbeat().GetTtl().GetValue() 273 correctHealthy := correctItem.GetHealthy().GetValue() 274 correctIsolate := correctItem.GetIsolate().GetValue() 275 correctMeta := correctItem.GetMetadata() 276 correctLogicSet := correctItem.GetLogicSet().GetValue() 277 /*correctCmdbRegion := correctItem.GetLocation().GetRegion().GetValue() 278 correctCmdbZone := correctItem.GetLocation().GetZone().GetValue() 279 correctCmdbCampus := correctItem.GetLocation().GetCampus().GetValue()*/ 280 281 id := item.GetId().GetValue() 282 service := item.GetService().GetValue() 283 namespace := item.GetNamespace().GetValue() 284 host := item.GetHost().GetValue() 285 port := item.GetPort().GetValue() 286 protocol := item.GetProtocol().GetValue() 287 version := item.GetVersion().GetValue() 288 priority := item.GetPriority().GetValue() 289 weight := item.GetWeight().GetValue() 290 healthType := item.GetHealthCheck().GetType() 291 healthTTL := item.GetHealthCheck().GetHeartbeat().GetTtl().GetValue() 292 healthy := item.GetHealthy().GetValue() 293 isolate := item.GetIsolate().GetValue() 294 meta := item.GetMetadata() 295 logicSet := item.GetLogicSet().GetValue() 296 /*cmdbRegion := item.GetLocation().GetRegion().GetValue() 297 cmdbZone := item.GetLocation().GetZone().GetValue() 298 cmdbCampus := item.GetLocation().GetCampus().GetValue()*/ 299 300 if correctID == id && correctService == service && correctNamespace == namespace && correctHost == host && 301 correctPort == port && correctProtocol == protocol && correctVersion == version && 302 correctPriority == priority && correctWeight == weight && correctHealthType == healthType && 303 correctHealthTTL == healthTTL && correctHealthy == healthy && correctIsolate == isolate && 304 reflect.DeepEqual(correctMeta, meta) && correctLogicSet == logicSet { 305 return true 306 } 307 return false 308 }