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  }