github.com/polarismesh/polaris@v1.17.8/common/model/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 model
    19  
    20  import (
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/golang/protobuf/ptypes/wrappers"
    25  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    26  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    27  
    28  	commontime "github.com/polarismesh/polaris/common/time"
    29  	"github.com/polarismesh/polaris/common/utils"
    30  )
    31  
    32  const (
    33  	MetadataInstanceLastHeartbeatTime = "internal-lastheartbeat"
    34  )
    35  
    36  // Instance 组合了api的Instance对象
    37  type Instance struct {
    38  	Proto             *apiservice.Instance
    39  	ServiceID         string
    40  	ServicePlatformID string
    41  	// Valid Whether it is deleted by logic
    42  	Valid bool
    43  	// ModifyTime Update time of instance
    44  	ModifyTime time.Time
    45  }
    46  
    47  // ID get id
    48  func (i *Instance) ID() string {
    49  	if i.Proto == nil {
    50  		return ""
    51  	}
    52  	return i.Proto.GetId().GetValue()
    53  }
    54  
    55  // Service get service
    56  func (i *Instance) Service() string {
    57  	if i.Proto == nil {
    58  		return ""
    59  	}
    60  	return i.Proto.GetService().GetValue()
    61  }
    62  
    63  // Namespace get namespace
    64  func (i *Instance) Namespace() string {
    65  	if i.Proto == nil {
    66  		return ""
    67  	}
    68  	return i.Proto.GetNamespace().GetValue()
    69  }
    70  
    71  // VpcID get vpcid
    72  func (i *Instance) VpcID() string {
    73  	if i.Proto == nil {
    74  		return ""
    75  	}
    76  	return i.Proto.GetVpcId().GetValue()
    77  }
    78  
    79  // Host get host
    80  func (i *Instance) Host() string {
    81  	if i.Proto == nil {
    82  		return ""
    83  	}
    84  	return i.Proto.GetHost().GetValue()
    85  }
    86  
    87  // Port get port
    88  func (i *Instance) Port() uint32 {
    89  	if i.Proto == nil {
    90  		return 0
    91  	}
    92  	return i.Proto.GetPort().GetValue()
    93  }
    94  
    95  // Protocol get protocol
    96  func (i *Instance) Protocol() string {
    97  	if i.Proto == nil {
    98  		return ""
    99  	}
   100  	return i.Proto.GetProtocol().GetValue()
   101  }
   102  
   103  // Version get version
   104  func (i *Instance) Version() string {
   105  	if i.Proto == nil {
   106  		return ""
   107  	}
   108  	return i.Proto.GetVersion().GetValue()
   109  }
   110  
   111  // Priority gets priority
   112  func (i *Instance) Priority() uint32 {
   113  	if i.Proto == nil {
   114  		return 0
   115  	}
   116  	return i.Proto.GetPriority().GetValue()
   117  }
   118  
   119  // Weight get weight
   120  func (i *Instance) Weight() uint32 {
   121  	if i.Proto == nil {
   122  		return 0
   123  	}
   124  	return i.Proto.GetWeight().GetValue()
   125  }
   126  
   127  // EnableHealthCheck get enables health check
   128  func (i *Instance) EnableHealthCheck() bool {
   129  	if i.Proto == nil {
   130  		return false
   131  	}
   132  	return i.Proto.GetEnableHealthCheck().GetValue()
   133  }
   134  
   135  // HealthCheck get health check
   136  func (i *Instance) HealthCheck() *apiservice.HealthCheck {
   137  	if i.Proto == nil {
   138  		return nil
   139  	}
   140  	return i.Proto.GetHealthCheck()
   141  }
   142  
   143  // Healthy get healthy
   144  func (i *Instance) Healthy() bool {
   145  	if i.Proto == nil {
   146  		return false
   147  	}
   148  	return i.Proto.GetHealthy().GetValue()
   149  }
   150  
   151  // Isolate get isolate
   152  func (i *Instance) Isolate() bool {
   153  	if i.Proto == nil {
   154  		return false
   155  	}
   156  	return i.Proto.GetIsolate().GetValue()
   157  }
   158  
   159  // Location gets location
   160  func (i *Instance) Location() *apimodel.Location {
   161  	if i.Proto == nil {
   162  		return nil
   163  	}
   164  	return i.Proto.GetLocation()
   165  }
   166  
   167  // Metadata get metadata
   168  func (i *Instance) Metadata() map[string]string {
   169  	if i.Proto == nil {
   170  		return nil
   171  	}
   172  	return i.Proto.GetMetadata()
   173  }
   174  
   175  // LogicSet get logic set
   176  func (i *Instance) LogicSet() string {
   177  	if i.Proto == nil {
   178  		return ""
   179  	}
   180  	return i.Proto.GetLogicSet().GetValue()
   181  }
   182  
   183  // Ctime get ctime
   184  func (i *Instance) Ctime() string {
   185  	if i.Proto == nil {
   186  		return ""
   187  	}
   188  	return i.Proto.GetCtime().GetValue()
   189  }
   190  
   191  // Mtime get mtime
   192  func (i *Instance) Mtime() string {
   193  	if i.Proto == nil {
   194  		return ""
   195  	}
   196  	return i.Proto.GetMtime().GetValue()
   197  }
   198  
   199  // Revision get revision
   200  func (i *Instance) Revision() string {
   201  	if i.Proto == nil {
   202  		return ""
   203  	}
   204  	return i.Proto.GetRevision().GetValue()
   205  }
   206  
   207  // ServiceToken get service token
   208  func (i *Instance) ServiceToken() string {
   209  	if i.Proto == nil {
   210  		return ""
   211  	}
   212  	return i.Proto.GetServiceToken().GetValue()
   213  }
   214  
   215  // MallocProto malloc proto if proto is null
   216  func (i *Instance) MallocProto() {
   217  	if i.Proto == nil {
   218  		i.Proto = &apiservice.Instance{}
   219  	}
   220  }
   221  
   222  // InstanceStore 对应store层(database)的对象
   223  type InstanceStore struct {
   224  	ID                string
   225  	ServiceID         string
   226  	Host              string
   227  	VpcID             string
   228  	Port              uint32
   229  	Protocol          string
   230  	Version           string
   231  	HealthStatus      int
   232  	Isolate           int
   233  	Weight            uint32
   234  	EnableHealthCheck int
   235  	CheckType         int32
   236  	TTL               uint32
   237  	Priority          uint32
   238  	Revision          string
   239  	LogicSet          string
   240  	Region            string
   241  	Zone              string
   242  	Campus            string
   243  	Meta              map[string]string
   244  	Flag              int
   245  	CreateTime        int64
   246  	ModifyTime        int64
   247  }
   248  
   249  // ExpandInstanceStore 包含服务名的store信息
   250  type ExpandInstanceStore struct {
   251  	ServiceName       string
   252  	Namespace         string
   253  	ServiceToken      string
   254  	ServicePlatformID string
   255  	ServiceInstance   *InstanceStore
   256  }
   257  
   258  // Store2Instance store的数据转换为组合了api的数据结构
   259  func Store2Instance(is *InstanceStore) *Instance {
   260  	ins := &Instance{
   261  		Proto: &apiservice.Instance{
   262  			Id:                &wrappers.StringValue{Value: is.ID},
   263  			VpcId:             &wrappers.StringValue{Value: is.VpcID},
   264  			Host:              &wrappers.StringValue{Value: is.Host},
   265  			Port:              &wrappers.UInt32Value{Value: is.Port},
   266  			Protocol:          &wrappers.StringValue{Value: is.Protocol},
   267  			Version:           &wrappers.StringValue{Value: is.Version},
   268  			Priority:          &wrappers.UInt32Value{Value: is.Priority},
   269  			Weight:            &wrappers.UInt32Value{Value: is.Weight},
   270  			EnableHealthCheck: &wrappers.BoolValue{Value: Int2bool(is.EnableHealthCheck)},
   271  			Healthy:           &wrappers.BoolValue{Value: Int2bool(is.HealthStatus)},
   272  			Location: &apimodel.Location{
   273  				Region: &wrappers.StringValue{Value: is.Region},
   274  				Zone:   &wrappers.StringValue{Value: is.Zone},
   275  				Campus: &wrappers.StringValue{Value: is.Campus},
   276  			},
   277  			Isolate:  &wrappers.BoolValue{Value: Int2bool(is.Isolate)},
   278  			Metadata: is.Meta,
   279  			LogicSet: &wrappers.StringValue{Value: is.LogicSet},
   280  			Ctime:    &wrappers.StringValue{Value: commontime.Int64Time2String(is.CreateTime)},
   281  			Mtime:    &wrappers.StringValue{Value: commontime.Int64Time2String(is.ModifyTime)},
   282  			Revision: &wrappers.StringValue{Value: is.Revision},
   283  		},
   284  		ServiceID:  is.ServiceID,
   285  		Valid:      flag2valid(is.Flag),
   286  		ModifyTime: time.Unix(is.ModifyTime, 0),
   287  	}
   288  	// 如果不存在checkType,即checkType==-1。HealthCheck置为nil
   289  	if is.CheckType != -1 {
   290  		ins.Proto.HealthCheck = &apiservice.HealthCheck{
   291  			Type: apiservice.HealthCheck_HealthCheckType(is.CheckType),
   292  			Heartbeat: &apiservice.HeartbeatHealthCheck{
   293  				Ttl: &wrappers.UInt32Value{Value: is.TTL},
   294  			},
   295  		}
   296  	}
   297  	// 如果location不为空,那么填充一下location
   298  	if is.Region != "" {
   299  		ins.Proto.Location = &apimodel.Location{
   300  			Region: &wrappers.StringValue{Value: is.Region},
   301  			Zone:   &wrappers.StringValue{Value: is.Zone},
   302  			Campus: &wrappers.StringValue{Value: is.Campus},
   303  		}
   304  	}
   305  
   306  	return ins
   307  }
   308  
   309  // ExpandStore2Instance 扩展store转换
   310  func ExpandStore2Instance(es *ExpandInstanceStore) *Instance {
   311  	out := Store2Instance(es.ServiceInstance)
   312  	out.Proto.Service = &wrappers.StringValue{Value: es.ServiceName}
   313  	out.Proto.Namespace = &wrappers.StringValue{Value: es.Namespace}
   314  	if es.ServiceToken != "" {
   315  		out.Proto.ServiceToken = &wrappers.StringValue{Value: es.ServiceToken}
   316  	}
   317  	out.ServicePlatformID = es.ServicePlatformID
   318  	return out
   319  }
   320  
   321  // CreateInstanceModel 创建存储层服务实例模型
   322  func CreateInstanceModel(serviceID string, req *apiservice.Instance) *Instance {
   323  	// 默认为健康的
   324  	healthy := true
   325  	if req.GetHealthy() != nil {
   326  		healthy = req.GetHealthy().GetValue()
   327  	}
   328  
   329  	// 默认为不隔离的
   330  	isolate := false
   331  	if req.GetIsolate() != nil {
   332  		isolate = req.GetIsolate().GetValue()
   333  	}
   334  
   335  	// 权重默认是100
   336  	var weight uint32 = 100
   337  	if req.GetWeight() != nil {
   338  		weight = req.GetWeight().GetValue()
   339  	}
   340  
   341  	instance := &Instance{
   342  		ServiceID: serviceID,
   343  	}
   344  
   345  	protoIns := &apiservice.Instance{
   346  		Id:       req.GetId(),
   347  		Host:     utils.NewStringValue(strings.TrimSpace(req.GetHost().GetValue())),
   348  		VpcId:    req.GetVpcId(),
   349  		Port:     req.GetPort(),
   350  		Protocol: req.GetProtocol(),
   351  		Version:  req.GetVersion(),
   352  		Priority: req.GetPriority(),
   353  		Weight:   utils.NewUInt32Value(weight),
   354  		Healthy:  utils.NewBoolValue(healthy),
   355  		Isolate:  utils.NewBoolValue(isolate),
   356  		Location: req.Location,
   357  		Metadata: req.Metadata,
   358  		LogicSet: req.GetLogicSet(),
   359  		Revision: utils.NewStringValue(utils.NewUUID()), // 更新版本号
   360  	}
   361  
   362  	// health Check,healthCheck不能为空,且没有显示把enable_health_check置为false
   363  	// 如果create的时候,打开了healthCheck,那么实例模式是unhealthy,必须要一次心跳才会healthy
   364  	if req.GetHealthCheck().GetHeartbeat() != nil &&
   365  		(req.GetEnableHealthCheck() == nil || req.GetEnableHealthCheck().GetValue()) {
   366  		protoIns.EnableHealthCheck = utils.NewBoolValue(true)
   367  		protoIns.HealthCheck = req.HealthCheck
   368  		protoIns.HealthCheck.Type = apiservice.HealthCheck_HEARTBEAT
   369  		// ttl range: (0, 60]
   370  		ttl := protoIns.GetHealthCheck().GetHeartbeat().GetTtl().GetValue()
   371  		if ttl == 0 || ttl > 60 {
   372  			if protoIns.HealthCheck.Heartbeat.Ttl == nil {
   373  				protoIns.HealthCheck.Heartbeat.Ttl = utils.NewUInt32Value(5)
   374  			}
   375  			protoIns.HealthCheck.Heartbeat.Ttl.Value = 5
   376  		}
   377  	}
   378  
   379  	instance.Proto = protoIns
   380  	return instance
   381  }