github.com/polarismesh/polaris@v1.17.8/service/service.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 service
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"strings"
    24  	"time"
    25  
    26  	"github.com/gogo/protobuf/jsonpb"
    27  	"github.com/golang/protobuf/ptypes/wrappers"
    28  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    29  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    30  	"go.uber.org/zap"
    31  
    32  	cachetypes "github.com/polarismesh/polaris/cache/api"
    33  	api "github.com/polarismesh/polaris/common/api/v1"
    34  	"github.com/polarismesh/polaris/common/model"
    35  	commonstore "github.com/polarismesh/polaris/common/store"
    36  	commontime "github.com/polarismesh/polaris/common/time"
    37  	"github.com/polarismesh/polaris/common/utils"
    38  )
    39  
    40  const (
    41  	MetadataInternalAutoCreated string = "internal-auto-created"
    42  )
    43  
    44  // Service2Api *model.service转换为*api.service
    45  type Service2Api func(service *model.Service) *apiservice.Service
    46  
    47  var (
    48  	serviceFilter           = 1 // 过滤服务的
    49  	instanceFilter          = 2 // 过滤实例的
    50  	serviceMetaFilter       = 3 // 过滤service Metadata的
    51  	instanceMetaFilter      = 4 // 过滤instance Metadata的
    52  	ServiceFilterAttributes = map[string]int{
    53  		"name":            serviceFilter,
    54  		"namespace":       serviceFilter,
    55  		"business":        serviceFilter,
    56  		"department":      serviceFilter,
    57  		"cmdb_mod1":       serviceFilter,
    58  		"cmdb_mod2":       serviceFilter,
    59  		"cmdb_mod3":       serviceFilter,
    60  		"owner":           serviceFilter,
    61  		"offset":          serviceFilter,
    62  		"limit":           serviceFilter,
    63  		"platform_id":     serviceFilter,
    64  		"host":            instanceFilter,
    65  		"port":            instanceFilter,
    66  		"keys":            serviceMetaFilter,
    67  		"values":          serviceMetaFilter,
    68  		"instance_keys":   instanceMetaFilter,
    69  		"instance_values": instanceMetaFilter,
    70  	}
    71  )
    72  
    73  // CreateServices 批量创建服务
    74  func (s *Server) CreateServices(ctx context.Context, req []*apiservice.Service) *apiservice.BatchWriteResponse {
    75  	if checkError := checkBatchService(req); checkError != nil {
    76  		return checkError
    77  	}
    78  
    79  	responses := api.NewBatchWriteResponse(apimodel.Code_ExecuteSuccess)
    80  	for _, service := range req {
    81  		response := s.CreateService(ctx, service)
    82  		api.Collect(responses, response)
    83  	}
    84  
    85  	return api.FormatBatchWriteResponse(responses)
    86  }
    87  
    88  // CreateService 创建单个服务
    89  func (s *Server) CreateService(ctx context.Context, req *apiservice.Service) *apiservice.Response {
    90  	requestID := utils.ParseRequestID(ctx)
    91  	platformID := utils.ParsePlatformID(ctx)
    92  	// 参数检查
    93  	if checkError := checkCreateService(req); checkError != nil {
    94  		return checkError
    95  	}
    96  
    97  	if _, errResp := s.createNamespaceIfAbsent(ctx, req); errResp != nil {
    98  		return errResp
    99  	}
   100  
   101  	namespaceName := req.GetNamespace().GetValue()
   102  	serviceName := req.GetName().GetValue()
   103  
   104  	// 检查命名空间是否存在
   105  	namespace, err := s.storage.GetNamespace(namespaceName)
   106  	if err != nil {
   107  		log.Error("[Service] get namespace fail",
   108  			utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID), zap.Error(err))
   109  		return api.NewServiceResponse(commonstore.StoreCode2APICode(err), req)
   110  	}
   111  	if namespace == nil {
   112  		return api.NewServiceResponse(apimodel.Code_NotFoundNamespace, req)
   113  	}
   114  
   115  	// 检查是否存在
   116  	service, err := s.storage.GetService(serviceName, namespaceName)
   117  	if err != nil {
   118  		log.Error("[Service] get service fail",
   119  			utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID), zap.Error(err))
   120  		return api.NewServiceResponse(commonstore.StoreCode2APICode(err), req)
   121  	}
   122  	if service != nil {
   123  		req.Id = utils.NewStringValue(service.ID)
   124  		return api.NewServiceResponse(apimodel.Code_ExistedResource, req)
   125  	}
   126  
   127  	// 存储层操作
   128  	data := s.createServiceModel(req)
   129  	if err := s.storage.AddService(data); err != nil {
   130  		log.Error("[Service] save service fail",
   131  			utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID), zap.Error(err))
   132  		// 如果在存储层发现资源存在错误,则需要再一次从存储层获取响应的信息,填充响应的 svc_id 信息
   133  		if commonstore.StoreCode2APICode(err) == apimodel.Code_ExistedResource {
   134  			// 检查是否存在
   135  			service, err := s.storage.GetService(serviceName, namespaceName)
   136  			if err != nil {
   137  				log.Error("[Service] get service fail", utils.ZapRequestID(requestID), zap.Error(err))
   138  				return api.NewServiceResponse(commonstore.StoreCode2APICode(err), req)
   139  			}
   140  			if service != nil {
   141  				req.Id = utils.NewStringValue(service.ID)
   142  				return api.NewServiceResponse(apimodel.Code_ExistedResource, req)
   143  			}
   144  		}
   145  		return wrapperServiceStoreResponse(req, err)
   146  	}
   147  
   148  	msg := fmt.Sprintf("create service: namespace=%v, name=%v, meta=%+v",
   149  		namespaceName, serviceName, req.GetMetadata())
   150  	log.Info(msg, utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   151  	s.RecordHistory(ctx, serviceRecordEntry(ctx, req, data, model.OCreate))
   152  
   153  	out := &apiservice.Service{
   154  		Id:        utils.NewStringValue(data.ID),
   155  		Name:      req.GetName(),
   156  		Namespace: req.GetNamespace(),
   157  		Token:     utils.NewStringValue(data.Token),
   158  	}
   159  
   160  	if err := s.afterServiceResource(ctx, req, data, false); err != nil {
   161  		return api.NewResponseWithMsg(apimodel.Code_ExecuteException, err.Error())
   162  	}
   163  
   164  	return api.NewServiceResponse(apimodel.Code_ExecuteSuccess, out)
   165  }
   166  
   167  // DeleteServices 批量删除服务
   168  func (s *Server) DeleteServices(ctx context.Context, req []*apiservice.Service) *apiservice.BatchWriteResponse {
   169  	if checkError := checkBatchService(req); checkError != nil {
   170  		return checkError
   171  	}
   172  
   173  	responses := api.NewBatchWriteResponse(apimodel.Code_ExecuteSuccess)
   174  	for _, service := range req {
   175  		response := s.DeleteService(ctx, service)
   176  		api.Collect(responses, response)
   177  	}
   178  
   179  	return api.FormatBatchWriteResponse(responses)
   180  }
   181  
   182  // DeleteService 删除单个服务
   183  //
   184  //	删除操作需要对服务进行加锁操作,
   185  //	防止有与服务关联的实例或者配置有新增的操作
   186  func (s *Server) DeleteService(ctx context.Context, req *apiservice.Service) *apiservice.Response {
   187  	requestID := utils.ParseRequestID(ctx)
   188  	platformID := utils.ParsePlatformID(ctx)
   189  
   190  	// 参数检查
   191  	if checkError := checkReviseService(req); checkError != nil {
   192  		return checkError
   193  	}
   194  
   195  	namespaceName := req.GetNamespace().GetValue()
   196  	serviceName := req.GetName().GetValue()
   197  
   198  	// 检查是否存在
   199  	service, err := s.storage.GetService(serviceName, namespaceName)
   200  	if err != nil {
   201  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   202  		return api.NewServiceResponse(commonstore.StoreCode2APICode(err), req)
   203  	}
   204  	if service == nil {
   205  		return api.NewServiceResponse(apimodel.Code_ExecuteSuccess, req)
   206  	}
   207  
   208  	// 判断service下的资源是否已经全部被删除
   209  	if resp := s.isServiceExistedResource(requestID, platformID, service); resp != nil {
   210  		return resp
   211  	}
   212  
   213  	if err := s.storage.DeleteService(service.ID, serviceName, namespaceName); err != nil {
   214  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   215  		return wrapperServiceStoreResponse(req, err)
   216  	}
   217  
   218  	msg := fmt.Sprintf("delete service: namespace=%v, name=%v", namespaceName, serviceName)
   219  	log.Info(msg, utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   220  	s.RecordHistory(ctx, serviceRecordEntry(ctx, req, nil, model.ODelete))
   221  
   222  	if err := s.afterServiceResource(ctx, req, service, true); err != nil {
   223  		return api.NewServiceResponse(apimodel.Code_ExecuteException, req)
   224  	}
   225  	return api.NewServiceResponse(apimodel.Code_ExecuteSuccess, req)
   226  }
   227  
   228  // UpdateServices 批量修改服务
   229  func (s *Server) UpdateServices(ctx context.Context, req []*apiservice.Service) *apiservice.BatchWriteResponse {
   230  	if checkError := checkBatchService(req); checkError != nil {
   231  		return checkError
   232  	}
   233  
   234  	responses := api.NewBatchWriteResponse(apimodel.Code_ExecuteSuccess)
   235  	for _, service := range req {
   236  		response := s.UpdateService(ctx, service)
   237  		api.Collect(responses, response)
   238  	}
   239  
   240  	return api.FormatBatchWriteResponse(responses)
   241  }
   242  
   243  // UpdateService 修改单个服务
   244  func (s *Server) UpdateService(ctx context.Context, req *apiservice.Service) *apiservice.Response {
   245  	requestID := utils.ParseRequestID(ctx)
   246  	platformID := utils.ParsePlatformID(ctx)
   247  	// 校验基础参数合法性
   248  	if resp := checkReviseService(req); resp != nil {
   249  		return resp
   250  	}
   251  
   252  	// 鉴权
   253  	service, _, resp := s.checkServiceAuthority(ctx, req)
   254  	if resp != nil {
   255  		return resp
   256  	}
   257  
   258  	// [2020.02.18]If service is alias, not allowed to modify
   259  	if service.IsAlias() {
   260  		return api.NewServiceResponse(apimodel.Code_NotAllowAliasUpdate, req)
   261  	}
   262  
   263  	log.Info(fmt.Sprintf("old service: %+v", service), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   264  
   265  	// 修改
   266  	err, needUpdate, needUpdateOwner := s.updateServiceAttribute(req, service)
   267  	if err != nil {
   268  		return err
   269  	}
   270  	// 判断是否需要更新
   271  	if !needUpdate {
   272  		log.Info("update service data no change, no need update",
   273  			utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID), zap.String("service", req.String()))
   274  		if err := s.afterServiceResource(ctx, req, service, false); err != nil {
   275  			return api.NewServiceResponse(apimodel.Code_ExecuteException, req)
   276  		}
   277  
   278  		return api.NewServiceResponse(apimodel.Code_NoNeedUpdate, req)
   279  	}
   280  
   281  	// 存储层操作
   282  	if err := s.storage.UpdateService(service, needUpdateOwner); err != nil {
   283  		log.Error(err.Error(), utils.ZapRequestID(requestID))
   284  		return wrapperServiceStoreResponse(req, err)
   285  	}
   286  
   287  	msg := fmt.Sprintf("update service: namespace=%v, name=%v", service.Namespace, service.Name)
   288  	log.Info(msg, utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   289  	s.RecordHistory(ctx, serviceRecordEntry(ctx, req, service, model.OUpdate))
   290  
   291  	if err := s.afterServiceResource(ctx, req, service, false); err != nil {
   292  		return api.NewServiceResponse(apimodel.Code_ExecuteException, req)
   293  	}
   294  
   295  	return api.NewServiceResponse(apimodel.Code_ExecuteSuccess, req)
   296  }
   297  
   298  // UpdateServiceToken 更新服务token
   299  func (s *Server) UpdateServiceToken(ctx context.Context, req *apiservice.Service) *apiservice.Response {
   300  	// 校验参数合法性
   301  	if resp := checkReviseService(req); resp != nil {
   302  		return resp
   303  	}
   304  
   305  	// 鉴权
   306  	service, _, resp := s.checkServiceAuthority(ctx, req)
   307  	if resp != nil {
   308  		return resp
   309  	}
   310  	if service.IsAlias() {
   311  		return api.NewServiceResponse(apimodel.Code_NotAllowAliasUpdate, req)
   312  	}
   313  	rid := utils.ParseRequestID(ctx)
   314  	pid := utils.ParsePlatformID(ctx)
   315  
   316  	// 生成一个新的token和revision
   317  	service.Token = utils.NewUUID()
   318  	service.Revision = utils.NewUUID()
   319  	// 更新数据库
   320  	if err := s.storage.UpdateServiceToken(service.ID, service.Token, service.Revision); err != nil {
   321  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   322  		return wrapperServiceStoreResponse(req, err)
   323  	}
   324  	log.Info("update service token", zap.String("namespace", service.Namespace),
   325  		zap.String("name", service.Name), zap.String("service-id", service.ID),
   326  		utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   327  	s.RecordHistory(ctx, serviceRecordEntry(ctx, req, service, model.OUpdateToken))
   328  
   329  	// 填充新的token返回
   330  	out := &apiservice.Service{
   331  		Name:      req.GetName(),
   332  		Namespace: req.GetNamespace(),
   333  		Token:     utils.NewStringValue(service.Token),
   334  	}
   335  	return api.NewServiceResponse(apimodel.Code_ExecuteSuccess, out)
   336  }
   337  
   338  // GetAllServices query all service list by namespace
   339  func (s *Server) GetAllServices(ctx context.Context, query map[string]string) *apiservice.BatchQueryResponse {
   340  	var (
   341  		svcs []*model.Service
   342  	)
   343  
   344  	if ns, ok := query["namespace"]; ok && len(ns) > 0 {
   345  		_, svcs = s.Cache().Service().ListServices(ns)
   346  	} else {
   347  		_, svcs = s.Cache().Service().ListAllServices()
   348  	}
   349  
   350  	ret := make([]*apiservice.Service, 0, len(svcs))
   351  	for i := range svcs {
   352  		count := s.Cache().Instance().GetInstancesCountByServiceID(svcs[i].ID)
   353  		ret = append(ret, &apiservice.Service{
   354  			Namespace:            utils.NewStringValue(svcs[i].Namespace),
   355  			Name:                 utils.NewStringValue(svcs[i].Name),
   356  			TotalInstanceCount:   utils.NewUInt32Value(count.TotalInstanceCount),
   357  			HealthyInstanceCount: utils.NewUInt32Value(count.HealthyInstanceCount),
   358  			Metadata:             svcs[i].Meta,
   359  		})
   360  	}
   361  
   362  	resp := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess)
   363  	resp.Amount = utils.NewUInt32Value(uint32(len(ret)))
   364  	resp.Size = utils.NewUInt32Value(uint32(len(ret)))
   365  	resp.Services = ret
   366  	return resp
   367  }
   368  
   369  // GetServices 查询服务 注意:不包括别名
   370  func (s *Server) GetServices(ctx context.Context, query map[string]string) *apiservice.BatchQueryResponse {
   371  	serviceFilters := make(map[string]string)
   372  	instanceFilters := make(map[string]string)
   373  	var (
   374  		metaKeys, metaValues                   string
   375  		inputInstMetaKeys, inputInstMetaValues string
   376  	)
   377  	for key, value := range query {
   378  		typ, ok := ServiceFilterAttributes[key]
   379  		if !ok {
   380  			log.Errorf("[Server][Service][Query] attribute(%s) it not allowed", key)
   381  			return api.NewBatchQueryResponseWithMsg(apimodel.Code_InvalidParameter, key+" is not allowed")
   382  		}
   383  		// 元数据value允许为空
   384  		if key != "values" && value == "" {
   385  			log.Errorf("[Server][Service][Query] attribute(%s: %s) is not allowed empty", key, value)
   386  			return api.NewBatchQueryResponseWithMsg(
   387  				apimodel.Code_InvalidParameter, "the value for "+key+" is empty")
   388  		}
   389  		switch {
   390  		case typ == serviceFilter:
   391  			serviceFilters[key] = value
   392  		case typ == serviceMetaFilter:
   393  			if key == "keys" {
   394  				metaKeys = value
   395  			} else {
   396  				metaValues = value
   397  			}
   398  		case typ == instanceMetaFilter:
   399  			if key == "instance_keys" {
   400  				inputInstMetaKeys = value
   401  			} else {
   402  				inputInstMetaValues = value
   403  			}
   404  		default:
   405  			instanceFilters[key] = value
   406  		}
   407  	}
   408  
   409  	instanceMetas := make(map[string]string)
   410  	if inputInstMetaKeys != "" {
   411  		instMetaKeys := strings.Split(inputInstMetaKeys, ",")
   412  		instMetaValues := strings.Split(inputInstMetaValues, ",")
   413  		if len(instMetaKeys) != len(instMetaValues) {
   414  			log.Errorf("[Server][Service][Query] length of instance meta %s and %s should be equal",
   415  				inputInstMetaKeys, inputInstMetaValues)
   416  			return api.NewBatchQueryResponseWithMsg(apimodel.Code_InvalidParameter,
   417  				" length of instance_keys and instance_values are not equal")
   418  		}
   419  		for idx, key := range instMetaKeys {
   420  			instanceMetas[key] = instMetaValues[idx]
   421  		}
   422  	}
   423  
   424  	instanceArgs, err := ParseInstanceArgs(instanceFilters, instanceMetas)
   425  	if err != nil {
   426  		log.Errorf("[Server][Service][Query] instance args error: %s", err.Error())
   427  		return api.NewBatchQueryResponseWithMsg(apimodel.Code_InvalidParameter, err.Error())
   428  	}
   429  
   430  	// 解析metaKeys,metaValues
   431  	serviceMetas := make(map[string]string)
   432  	if metaKeys != "" {
   433  		serviceMetas[metaKeys] = metaValues
   434  	}
   435  
   436  	// 判断offset和limit是否为int,并从filters清除offset/limit参数
   437  	offset, limit, err := utils.ParseOffsetAndLimit(serviceFilters)
   438  	if err != nil {
   439  		return api.NewBatchQueryResponse(apimodel.Code_InvalidParameter)
   440  	}
   441  
   442  	serviceArgs := parseServiceArgs(serviceFilters, serviceMetas, ctx)
   443  	total, services, err := s.caches.Service().GetServicesByFilter(serviceArgs, instanceArgs, offset, limit)
   444  	if err != nil {
   445  		log.Errorf("[Server][Service][Query] req(%+v) store err: %s", query, err.Error())
   446  		return api.NewBatchQueryResponse(commonstore.StoreCode2APICode(err))
   447  	}
   448  
   449  	resp := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess)
   450  	resp.Amount = utils.NewUInt32Value(total)
   451  	resp.Size = utils.NewUInt32Value(uint32(len(services)))
   452  	resp.Services = enhancedServices2Api(services, service2Api)
   453  	return resp
   454  }
   455  
   456  // parseServiceArgs 解析服务的查询条件
   457  func parseServiceArgs(filter map[string]string, metaFilter map[string]string,
   458  	ctx context.Context) *cachetypes.ServiceArgs {
   459  
   460  	res := &cachetypes.ServiceArgs{
   461  		Filter:    filter,
   462  		Metadata:  metaFilter,
   463  		Namespace: filter["namespace"],
   464  	}
   465  	var ok bool
   466  	if res.Name, ok = filter["name"]; ok && utils.IsPrefixWildName(res.Name) {
   467  		log.Infof("[Server][Service][Query] fuzzy search with name %s", res.Name)
   468  		res.WildName = true
   469  	}
   470  	if utils.IsWildName(res.Namespace) {
   471  		log.Infof("[Server][Service][Query] fuzzy search with namespace %s", res.Namespace)
   472  		res.WildNamespace = true
   473  	}
   474  	if business, ok := filter["business"]; ok {
   475  		log.Infof("[Server][Service][Query] fuzzy search with business %s, operator %s",
   476  			business, utils.ParseOperator(ctx))
   477  		res.WildBusiness = true
   478  	}
   479  	// 如果元数据条件是空的话,判断是否是空条件匹配
   480  	if len(metaFilter) == 0 {
   481  		// 如果没有匹配条件,那么就是空条件匹配
   482  		if len(filter) == 0 {
   483  			res.EmptyCondition = true
   484  		}
   485  		// 只有一个命名空间条件,也是在这个命名空间下面的空条件匹配
   486  		if len(filter) == 1 && res.Namespace != "" && !res.WildNamespace {
   487  			res.EmptyCondition = true
   488  		}
   489  	}
   490  	log.Infof("[Server][Service][Query] service query args: %+v", res)
   491  	return res
   492  }
   493  
   494  // GetServicesCount 查询服务总数
   495  func (s *Server) GetServicesCount(ctx context.Context) *apiservice.BatchQueryResponse {
   496  	count, err := s.storage.GetServicesCount()
   497  	if err != nil {
   498  		log.Errorf("[Server][Service][Count] get service count storage err: %s", err.Error())
   499  		return api.NewBatchQueryResponse(commonstore.StoreCode2APICode(err))
   500  	}
   501  
   502  	out := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess)
   503  	out.Amount = utils.NewUInt32Value(count)
   504  	out.Services = make([]*apiservice.Service, 0)
   505  	return out
   506  }
   507  
   508  // GetServiceToken 查询Service的token
   509  func (s *Server) GetServiceToken(ctx context.Context, req *apiservice.Service) *apiservice.Response {
   510  	// 校验参数合法性
   511  	if resp := checkReviseService(req); resp != nil {
   512  		return resp
   513  	}
   514  
   515  	// 鉴权
   516  	_, token, resp := s.checkServiceAuthority(ctx, req)
   517  	if resp != nil {
   518  		return resp
   519  	}
   520  
   521  	// s.RecordHistory(serviceRecordEntry(ctx, req, model.OGetToken))
   522  	out := api.NewResponse(apimodel.Code_ExecuteSuccess)
   523  	out.Service = &apiservice.Service{
   524  		Name:      req.GetName(),
   525  		Namespace: req.GetNamespace(),
   526  		Token:     utils.NewStringValue(token),
   527  	}
   528  	return out
   529  }
   530  
   531  // GetServiceOwner 查询服务负责人
   532  func (s *Server) GetServiceOwner(ctx context.Context, req []*apiservice.Service) *apiservice.BatchQueryResponse {
   533  	requestID := utils.ParseRequestID(ctx)
   534  	platformID := utils.ParseRequestID(ctx)
   535  
   536  	if err := checkBatchReadService(req); err != nil {
   537  		return err
   538  	}
   539  
   540  	services, err := s.storage.GetServicesBatch(apis2ServicesName(req))
   541  	if err != nil {
   542  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   543  		return api.NewBatchQueryResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error())
   544  	}
   545  
   546  	resp := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess)
   547  	resp.Amount = utils.NewUInt32Value(uint32(len(services)))
   548  	resp.Size = utils.NewUInt32Value(uint32(len(services)))
   549  	resp.Services = services2Api(services, serviceOwner2Api)
   550  	return resp
   551  }
   552  
   553  // createNamespaceIfAbsent Automatically create namespaces
   554  func (s *Server) createNamespaceIfAbsent(ctx context.Context, svc *apiservice.Service) (string, *apiservice.Response) {
   555  	val, errResp := s.Namespace().CreateNamespaceIfAbsent(ctx, &apimodel.Namespace{
   556  		Name:   utils.NewStringValue(svc.GetNamespace().GetValue()),
   557  		Owners: svc.Owners,
   558  	})
   559  	return val, errResp
   560  }
   561  
   562  // createServiceModel 创建存储层服务模型
   563  func (s *Server) createServiceModel(req *apiservice.Service) *model.Service {
   564  	return &model.Service{
   565  		ID:         utils.NewUUID(),
   566  		Name:       req.GetName().GetValue(),
   567  		Namespace:  req.GetNamespace().GetValue(),
   568  		Meta:       req.GetMetadata(),
   569  		Ports:      req.GetPorts().GetValue(),
   570  		Business:   req.GetBusiness().GetValue(),
   571  		Department: req.GetDepartment().GetValue(),
   572  		CmdbMod1:   req.GetCmdbMod1().GetValue(),
   573  		CmdbMod2:   req.GetCmdbMod2().GetValue(),
   574  		CmdbMod3:   req.GetCmdbMod3().GetValue(),
   575  		Comment:    req.GetComment().GetValue(),
   576  		Owner:      req.GetOwners().GetValue(),
   577  		PlatformID: req.GetPlatformId().GetValue(),
   578  		Token:      utils.NewUUID(),
   579  		Revision:   utils.NewUUID(),
   580  	}
   581  }
   582  
   583  // updateServiceAttribute 修改服务属性
   584  func (s *Server) updateServiceAttribute(
   585  	req *apiservice.Service, service *model.Service) (*apiservice.Response, bool, bool) {
   586  	// 待更新的参数检查
   587  	if err := checkMetadata(req.GetMetadata()); err != nil {
   588  		return api.NewServiceResponse(apimodel.Code_InvalidMetadata, req), false, false
   589  	}
   590  
   591  	var (
   592  		needUpdate      = false
   593  		needNewRevision = false
   594  		needUpdateOwner = false
   595  	)
   596  
   597  	if req.GetMetadata() != nil {
   598  		if need := serviceMetaNeedUpdate(req, service); need {
   599  			needUpdate = need
   600  			needNewRevision = true
   601  			service.Meta = req.GetMetadata()
   602  		}
   603  	}
   604  	if !needUpdate {
   605  		// 不需要更新metadata
   606  		service.Meta = nil
   607  	}
   608  
   609  	if req.GetPorts() != nil && req.GetPorts().GetValue() != service.Ports {
   610  		service.Ports = req.GetPorts().GetValue()
   611  		needUpdate = true
   612  	}
   613  
   614  	if req.GetBusiness() != nil && req.GetBusiness().GetValue() != service.Business {
   615  		service.Business = req.GetBusiness().GetValue()
   616  		needUpdate = true
   617  	}
   618  
   619  	if req.GetDepartment() != nil && req.GetDepartment().GetValue() != service.Department {
   620  		service.Department = req.GetDepartment().GetValue()
   621  		needUpdate = true
   622  	}
   623  
   624  	if req.GetCmdbMod1() != nil && req.GetCmdbMod1().GetValue() != service.CmdbMod1 {
   625  		service.CmdbMod1 = req.GetCmdbMod1().GetValue()
   626  		needUpdate = true
   627  	}
   628  	if req.GetCmdbMod2() != nil && req.GetCmdbMod2().GetValue() != service.CmdbMod2 {
   629  		service.CmdbMod2 = req.GetCmdbMod2().GetValue()
   630  		needUpdate = true
   631  	}
   632  	if req.GetCmdbMod3() != nil && req.GetCmdbMod3().GetValue() != service.CmdbMod3 {
   633  		service.CmdbMod3 = req.GetCmdbMod3().GetValue()
   634  		needUpdate = true
   635  	}
   636  
   637  	if req.GetComment() != nil && req.GetComment().GetValue() != service.Comment {
   638  		service.Comment = req.GetComment().GetValue()
   639  		needUpdate = true
   640  	}
   641  
   642  	if req.GetOwners() != nil && req.GetOwners().GetValue() != service.Owner {
   643  		service.Owner = req.GetOwners().GetValue()
   644  		needUpdate = true
   645  		needUpdateOwner = true
   646  	}
   647  
   648  	if req.GetPlatformId() != nil && req.GetPlatformId().GetValue() != service.PlatformID {
   649  		service.PlatformID = req.GetPlatformId().GetValue()
   650  		needUpdate = true
   651  	}
   652  
   653  	if needNewRevision {
   654  		service.Revision = utils.NewUUID()
   655  	}
   656  
   657  	return nil, needUpdate, needUpdateOwner
   658  }
   659  
   660  // getServiceAliasCountWithService 获取服务下别名的总数
   661  func (s *Server) getServiceAliasCountWithService(name string, namespace string) (uint32, error) {
   662  	filter := map[string]string{
   663  		"service":   name,
   664  		"namespace": namespace,
   665  	}
   666  	total, _, err := s.storage.GetServiceAliases(filter, 0, 1)
   667  	if err != nil {
   668  		return 0, err
   669  	}
   670  	return total, nil
   671  }
   672  
   673  // getInstancesCountWithService 获取服务下实例的总数
   674  func (s *Server) getInstancesCountWithService(name string, namespace string) (uint32, error) {
   675  	filter := map[string]string{
   676  		"name":      name,
   677  		"namespace": namespace,
   678  	}
   679  	total, _, err := s.storage.GetExpandInstances(filter, nil, 0, 1)
   680  	if err != nil {
   681  		return 0, err
   682  	}
   683  	return total, nil
   684  }
   685  
   686  // getRoutingCountWithService 获取服务下路由配置总数
   687  func (s *Server) getRoutingCountWithService(id string) (uint32, error) {
   688  	routing, err := s.storage.GetRoutingConfigWithID(id)
   689  	if err != nil {
   690  		return 0, err
   691  	}
   692  
   693  	if routing == nil {
   694  		return 0, nil
   695  	}
   696  	return 1, nil
   697  }
   698  
   699  // getRateLimitingCountWithService 获取服务下限流规则总数
   700  func (s *Server) getRateLimitingCountWithService(name string, namespace string) (uint32, error) {
   701  	filter := map[string]string{
   702  		"service":   name,
   703  		"namespace": namespace,
   704  	}
   705  	total, _, err := s.storage.GetExtendRateLimits(filter, 0, 1)
   706  	if err != nil {
   707  		return 0, err
   708  	}
   709  	return total, nil
   710  }
   711  
   712  // isServiceExistedResource 检查服务下的资源存在情况,在删除服务的时候需要用到
   713  func (s *Server) isServiceExistedResource(rid, pid string, service *model.Service) *apiservice.Response {
   714  	// 服务别名,不需要判断
   715  	if service.IsAlias() {
   716  		return nil
   717  	}
   718  	out := &apiservice.Service{
   719  		Name:      utils.NewStringValue(service.Name),
   720  		Namespace: utils.NewStringValue(service.Namespace),
   721  	}
   722  	total, err := s.getInstancesCountWithService(service.Name, service.Namespace)
   723  	if err != nil {
   724  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   725  		return api.NewServiceResponse(commonstore.StoreCode2APICode(err), out)
   726  	}
   727  	if total != 0 {
   728  		return api.NewServiceResponse(apimodel.Code_ServiceExistedInstances, out)
   729  	}
   730  
   731  	total, err = s.getServiceAliasCountWithService(service.Name, service.Namespace)
   732  	if err != nil {
   733  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   734  		return api.NewServiceResponse(commonstore.StoreCode2APICode(err), out)
   735  	}
   736  	if total != 0 {
   737  		return api.NewServiceResponse(apimodel.Code_ServiceExistedAlias, out)
   738  	}
   739  
   740  	// TODO will remove until have sync router rule v1 to v2
   741  	total, err = s.getRoutingCountWithService(service.ID)
   742  	if err != nil {
   743  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   744  		return api.NewServiceResponse(commonstore.StoreCode2APICode(err), out)
   745  	}
   746  
   747  	if total != 0 {
   748  		return api.NewServiceResponse(apimodel.Code_ServiceExistedRoutings, out)
   749  	}
   750  	return nil
   751  }
   752  
   753  // checkServiceAuthority 对服务进行鉴权,并且返回model.Service
   754  // return service, token, response
   755  func (s *Server) checkServiceAuthority(ctx context.Context, req *apiservice.Service) (*model.Service,
   756  	string, *apiservice.Response) {
   757  	rid := utils.ParseRequestID(ctx)
   758  	pid := utils.ParsePlatformID(ctx)
   759  	namespaceName := req.GetNamespace().GetValue()
   760  	serviceName := req.GetName().GetValue()
   761  
   762  	// 检查是否存在
   763  	svc, err := s.storage.GetService(serviceName, namespaceName)
   764  	if err != nil {
   765  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   766  		return nil, "", api.NewServiceResponse(commonstore.StoreCode2APICode(err), req)
   767  	}
   768  	if svc == nil {
   769  		return nil, "", api.NewServiceResponse(apimodel.Code_NotFoundResource, req)
   770  	}
   771  	if svc.Reference != "" {
   772  		svc, err = s.storage.GetServiceByID(svc.Reference)
   773  		if err != nil {
   774  			log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   775  			return nil, "", api.NewServiceResponse(commonstore.StoreCode2APICode(err), req)
   776  		}
   777  		if svc == nil {
   778  			return nil, "", api.NewServiceResponse(apimodel.Code_NotFoundResource, req)
   779  		}
   780  	}
   781  
   782  	expectToken := svc.Token
   783  
   784  	return svc, expectToken, nil
   785  }
   786  
   787  // service2Api model.Service 转为 api.Service
   788  func service2Api(service *model.Service) *apiservice.Service {
   789  	if service == nil {
   790  		return nil
   791  	}
   792  
   793  	// note: 不包括token,token比较特殊
   794  	out := &apiservice.Service{
   795  		Id:         utils.NewStringValue(service.ID),
   796  		Name:       utils.NewStringValue(service.Name),
   797  		Namespace:  utils.NewStringValue(service.Namespace),
   798  		Metadata:   service.Meta,
   799  		Ports:      utils.NewStringValue(service.Ports),
   800  		Business:   utils.NewStringValue(service.Business),
   801  		Department: utils.NewStringValue(service.Department),
   802  		CmdbMod1:   utils.NewStringValue(service.CmdbMod1),
   803  		CmdbMod2:   utils.NewStringValue(service.CmdbMod2),
   804  		CmdbMod3:   utils.NewStringValue(service.CmdbMod3),
   805  		Comment:    utils.NewStringValue(service.Comment),
   806  		Owners:     utils.NewStringValue(service.Owner),
   807  		Revision:   utils.NewStringValue(service.Revision),
   808  		PlatformId: utils.NewStringValue(service.PlatformID),
   809  		Ctime:      utils.NewStringValue(commontime.Time2String(service.CreateTime)),
   810  		Mtime:      utils.NewStringValue(commontime.Time2String(service.ModifyTime)),
   811  	}
   812  
   813  	return out
   814  }
   815  
   816  // serviceOwner2Api model.Service转为api.Service
   817  // 只转name+namespace+owner
   818  func serviceOwner2Api(service *model.Service) *apiservice.Service {
   819  	if service == nil {
   820  		return nil
   821  	}
   822  	out := &apiservice.Service{
   823  		Name:      utils.NewStringValue(service.Name),
   824  		Namespace: utils.NewStringValue(service.Namespace),
   825  		Owners:    utils.NewStringValue(service.Owner),
   826  	}
   827  	return out
   828  }
   829  
   830  // services2Api service数组转为[]*api.Service
   831  func services2Api(services []*model.Service, handler Service2Api) []*apiservice.Service {
   832  	out := make([]*apiservice.Service, 0, len(services))
   833  	for _, entry := range services {
   834  		out = append(out, handler(entry))
   835  	}
   836  
   837  	return out
   838  }
   839  
   840  // enhancedServices2Api service数组转为[]*api.Service
   841  func enhancedServices2Api(services []*model.EnhancedService, handler Service2Api) []*apiservice.Service {
   842  	out := make([]*apiservice.Service, 0, len(services))
   843  	for _, entry := range services {
   844  		outSvc := handler(entry.Service)
   845  		outSvc.HealthyInstanceCount = &wrappers.UInt32Value{Value: entry.HealthyInstanceCount}
   846  		outSvc.TotalInstanceCount = &wrappers.UInt32Value{Value: entry.TotalInstanceCount}
   847  		out = append(out, outSvc)
   848  	}
   849  
   850  	return out
   851  }
   852  
   853  // apis2ServicesName api数组转为[]*model.Service
   854  func apis2ServicesName(reqs []*apiservice.Service) []*model.Service {
   855  	if reqs == nil {
   856  		return nil
   857  	}
   858  
   859  	out := make([]*model.Service, 0, len(reqs))
   860  	for _, req := range reqs {
   861  		out = append(out, api2ServiceName(req))
   862  	}
   863  	return out
   864  }
   865  
   866  // api2ServiceName api转为*model.Service
   867  func api2ServiceName(req *apiservice.Service) *model.Service {
   868  	if req == nil {
   869  		return nil
   870  	}
   871  	service := &model.Service{
   872  		Name:      req.GetName().GetValue(),
   873  		Namespace: req.GetNamespace().GetValue(),
   874  	}
   875  	return service
   876  }
   877  
   878  // serviceMetaNeedUpdate 检查服务metadata是否需要更新
   879  func serviceMetaNeedUpdate(req *apiservice.Service, service *model.Service) bool {
   880  	// 收到的请求的metadata为空,则代表metadata不需要更新
   881  	if req.GetMetadata() == nil {
   882  		return false
   883  	}
   884  
   885  	// metadata个数不一致,肯定需要更新
   886  	if len(req.GetMetadata()) != len(service.Meta) {
   887  		return true
   888  	}
   889  
   890  	needUpdate := false
   891  	// 新数据为标准,对比老数据,发现不一致,则需要更新
   892  	for key, value := range req.GetMetadata() {
   893  		oldValue, ok := service.Meta[key]
   894  		if !ok {
   895  			needUpdate = true
   896  			break
   897  		}
   898  		if value != oldValue {
   899  			needUpdate = true
   900  			break
   901  		}
   902  	}
   903  	if needUpdate {
   904  		return true
   905  	}
   906  
   907  	// 老数据作为标准,对比新数据,发现不一致,则需要更新
   908  	for key, value := range service.Meta {
   909  		newValue, ok := req.Metadata[key]
   910  		if !ok {
   911  			needUpdate = true
   912  			break
   913  		}
   914  		if value != newValue {
   915  			needUpdate = true
   916  			break
   917  		}
   918  	}
   919  
   920  	return needUpdate
   921  }
   922  
   923  // checkBatchService检查批量请求
   924  func checkBatchService(req []*apiservice.Service) *apiservice.BatchWriteResponse {
   925  	if len(req) == 0 {
   926  		return api.NewBatchWriteResponse(apimodel.Code_EmptyRequest)
   927  	}
   928  
   929  	if len(req) > MaxBatchSize {
   930  		return api.NewBatchWriteResponse(apimodel.Code_BatchSizeOverLimit)
   931  	}
   932  
   933  	return nil
   934  }
   935  
   936  // checkBatchReadService 检查批量读请求
   937  func checkBatchReadService(req []*apiservice.Service) *apiservice.BatchQueryResponse {
   938  	if len(req) == 0 {
   939  		return api.NewBatchQueryResponse(apimodel.Code_EmptyRequest)
   940  	}
   941  
   942  	if len(req) > MaxBatchSize {
   943  		return api.NewBatchQueryResponse(apimodel.Code_BatchSizeOverLimit)
   944  	}
   945  
   946  	return nil
   947  }
   948  
   949  // checkCreateService 检查创建服务请求参数
   950  func checkCreateService(req *apiservice.Service) *apiservice.Response {
   951  	if req == nil {
   952  		return api.NewServiceResponse(apimodel.Code_EmptyRequest, req)
   953  	}
   954  
   955  	if err := checkResourceName(req.GetName()); err != nil {
   956  		return api.NewServiceResponse(apimodel.Code_InvalidServiceName, req)
   957  	}
   958  
   959  	if err := checkResourceName(req.GetNamespace()); err != nil {
   960  		return api.NewServiceResponse(apimodel.Code_InvalidNamespaceName, req)
   961  	}
   962  
   963  	if err := checkMetadata(req.GetMetadata()); err != nil {
   964  		return api.NewServiceResponse(apimodel.Code_InvalidMetadata, req)
   965  	}
   966  
   967  	// 检查字段长度是否大于DB中对应字段长
   968  	err, notOk := CheckDbServiceFieldLen(req)
   969  	if notOk {
   970  		return err
   971  	}
   972  
   973  	return nil
   974  }
   975  
   976  // checkReviseService 检查删除/修改/服务token的服务请求参数
   977  func checkReviseService(req *apiservice.Service) *apiservice.Response {
   978  	if req == nil {
   979  		return api.NewServiceResponse(apimodel.Code_EmptyRequest, req)
   980  	}
   981  
   982  	if err := checkResourceName(req.GetName()); err != nil {
   983  		return api.NewServiceResponse(apimodel.Code_InvalidServiceName, req)
   984  	}
   985  
   986  	if err := checkResourceName(req.GetNamespace()); err != nil {
   987  		return api.NewServiceResponse(apimodel.Code_InvalidNamespaceName, req)
   988  	}
   989  
   990  	// 检查字段长度是否大于DB中对应字段长
   991  	err, notOk := CheckDbServiceFieldLen(req)
   992  	if notOk {
   993  		return err
   994  	}
   995  
   996  	return nil
   997  }
   998  
   999  // wrapperServiceStoreResponse wrapper service error
  1000  func wrapperServiceStoreResponse(service *apiservice.Service, err error) *apiservice.Response {
  1001  	resp := storeError2Response(err)
  1002  	if resp == nil {
  1003  		return nil
  1004  	}
  1005  
  1006  	resp.Service = service
  1007  	return resp
  1008  }
  1009  
  1010  // parseRequestToken 从request中获取服务token
  1011  func parseRequestToken(ctx context.Context, value string) string {
  1012  	if value != "" {
  1013  		return value
  1014  	}
  1015  
  1016  	return utils.ParseToken(ctx)
  1017  }
  1018  
  1019  // serviceRecordEntry 生成服务的记录entry
  1020  func serviceRecordEntry(ctx context.Context, req *apiservice.Service, md *model.Service,
  1021  	operationType model.OperationType) *model.RecordEntry {
  1022  
  1023  	marshaler := jsonpb.Marshaler{}
  1024  	detail, _ := marshaler.MarshalToString(req)
  1025  
  1026  	entry := &model.RecordEntry{
  1027  		ResourceType:  model.RService,
  1028  		ResourceName:  req.GetName().GetValue(),
  1029  		Namespace:     req.GetNamespace().GetValue(),
  1030  		OperationType: operationType,
  1031  		Operator:      utils.ParseOperator(ctx),
  1032  		Detail:        detail,
  1033  		HappenTime:    time.Now(),
  1034  	}
  1035  
  1036  	return entry
  1037  }
  1038  
  1039  // CheckDbServiceFieldLen 检查DB中service表对应的入参字段合法性
  1040  func CheckDbServiceFieldLen(req *apiservice.Service) (*apiservice.Response, bool) {
  1041  	if err := utils.CheckDbStrFieldLen(req.GetName(), MaxDbServiceNameLength); err != nil {
  1042  		return api.NewServiceResponse(apimodel.Code_InvalidServiceName, req), true
  1043  	}
  1044  	if err := utils.CheckDbStrFieldLen(req.GetNamespace(), MaxDbServiceNamespaceLength); err != nil {
  1045  		return api.NewServiceResponse(apimodel.Code_InvalidNamespaceName, req), true
  1046  	}
  1047  	if err := utils.CheckDbMetaDataFieldLen(req.GetMetadata()); err != nil {
  1048  		return api.NewServiceResponse(apimodel.Code_InvalidMetadata, req), true
  1049  	}
  1050  	if err := utils.CheckDbStrFieldLen(req.GetPorts(), MaxDbServicePortsLength); err != nil {
  1051  		return api.NewServiceResponse(apimodel.Code_InvalidServicePorts, req), true
  1052  	}
  1053  	if err := utils.CheckDbStrFieldLen(req.GetBusiness(), MaxDbServiceBusinessLength); err != nil {
  1054  		return api.NewServiceResponse(apimodel.Code_InvalidServiceBusiness, req), true
  1055  	}
  1056  	if err := utils.CheckDbStrFieldLen(req.GetDepartment(), MaxDbServiceDeptLength); err != nil {
  1057  		return api.NewServiceResponse(apimodel.Code_InvalidServiceDepartment, req), true
  1058  	}
  1059  	if err := utils.CheckDbStrFieldLen(req.GetCmdbMod1(), MaxDbServiceCMDBLength); err != nil {
  1060  		return api.NewServiceResponse(apimodel.Code_InvalidServiceCMDB, req), true
  1061  	}
  1062  	if err := utils.CheckDbStrFieldLen(req.GetCmdbMod2(), MaxDbServiceCMDBLength); err != nil {
  1063  		return api.NewServiceResponse(apimodel.Code_InvalidServiceCMDB, req), true
  1064  	}
  1065  	if err := utils.CheckDbStrFieldLen(req.GetCmdbMod3(), MaxDbServiceCMDBLength); err != nil {
  1066  		return api.NewServiceResponse(apimodel.Code_InvalidServiceCMDB, req), true
  1067  	}
  1068  	if err := utils.CheckDbStrFieldLen(req.GetComment(), MaxDbServiceCommentLength); err != nil {
  1069  		return api.NewServiceResponse(apimodel.Code_InvalidServiceComment, req), true
  1070  	}
  1071  	if err := utils.CheckDbStrFieldLen(req.GetOwners(), MaxDbServiceOwnerLength); err != nil {
  1072  		return api.NewServiceResponse(apimodel.Code_InvalidServiceOwners, req), true
  1073  	}
  1074  	if err := utils.CheckDbStrFieldLen(req.GetToken(), MaxDbServiceToken); err != nil {
  1075  		return api.NewServiceResponse(apimodel.Code_InvalidServiceToken, req), true
  1076  	}
  1077  	if err := utils.CheckDbStrFieldLen(req.GetPlatformId(), MaxPlatformIDLength); err != nil {
  1078  		return api.NewServiceResponse(apimodel.Code_InvalidPlatformID, req), true
  1079  	}
  1080  	return nil, false
  1081  }