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 }