github.com/polarismesh/polaris@v1.17.8/store/boltdb/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 boltdb
    19  
    20  import (
    21  	"database/sql"
    22  	"errors"
    23  	"sort"
    24  	"strconv"
    25  	"strings"
    26  	"time"
    27  
    28  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    29  	"go.uber.org/zap"
    30  
    31  	"github.com/polarismesh/polaris/common/model"
    32  	"github.com/polarismesh/polaris/common/utils"
    33  	"github.com/polarismesh/polaris/store"
    34  )
    35  
    36  type serviceStore struct {
    37  	handler BoltHandler
    38  }
    39  
    40  var (
    41  	ErrMultipleSvcFound = errors.New("multiple service find")
    42  )
    43  
    44  const (
    45  	tblNameService     string = "service"
    46  	SvcFieldID         string = "ID"
    47  	SvcFieldName       string = "Name"
    48  	SvcFieldNamespace  string = "Namespace"
    49  	SvcFieldBusiness   string = "Business"
    50  	SvcFieldPorts      string = "Ports"
    51  	SvcFieldMeta       string = "Meta"
    52  	SvcFieldComment    string = "Comment"
    53  	SvcFieldDepartment string = "Department"
    54  	SvcFieldModifyTime string = "ModifyTime"
    55  	SvcFieldToken      string = "Token"
    56  	SvcFieldOwner      string = "Owner"
    57  	SvcFieldRevision   string = "Revision"
    58  	SvcFieldReference  string = "Reference"
    59  	SvcFieldValid      string = "Valid"
    60  	SvcFieldCmdbMod1   string = "CmdbMod1"
    61  	SvcFieldCmdbMod2   string = "CmdbMod2"
    62  	SvcFieldCmdbMod3   string = "CmdbMod3"
    63  )
    64  
    65  // AddService save a service
    66  func (ss *serviceStore) AddService(s *model.Service) error {
    67  
    68  	// 删除之前同名的服务
    69  	if err := ss.cleanInValidService(s.Name, s.Namespace); err != nil {
    70  		return err
    71  	}
    72  
    73  	initService(s)
    74  
    75  	if s.ID == "" || s.Name == "" || s.Namespace == "" {
    76  		return store.NewStatusError(store.EmptyParamsErr, "add Service missing some params")
    77  	}
    78  
    79  	err := ss.handler.SaveValue(tblNameService, s.ID, s)
    80  
    81  	return store.Error(err)
    82  }
    83  
    84  // DeleteService delete a service
    85  func (ss *serviceStore) DeleteService(id, serviceName, namespaceName string) error {
    86  	if id == "" {
    87  		return store.NewStatusError(store.EmptyParamsErr, "delete Service missing some params")
    88  	}
    89  
    90  	properties := make(map[string]interface{})
    91  	properties[SvcFieldValid] = false
    92  	properties[SvcFieldModifyTime] = time.Now()
    93  
    94  	err := ss.handler.UpdateValue(tblNameService, id, properties)
    95  	return store.Error(err)
    96  }
    97  
    98  // DeleteServiceAlias delete a service alias
    99  func (ss *serviceStore) DeleteServiceAlias(name string, namespace string) error {
   100  	if name == "" || namespace == "" {
   101  		return store.NewStatusError(store.EmptyParamsErr, "delete Service alias missing some params")
   102  	}
   103  
   104  	svc, err := ss.getServiceByNameAndNs(name, namespace)
   105  	if err != nil {
   106  		log.Error("[Store][boltdb] get service alias error", zap.Error(err))
   107  		return err
   108  	}
   109  	if svc == nil {
   110  		return nil
   111  	}
   112  
   113  	properties := make(map[string]interface{})
   114  	properties[SvcFieldValid] = false
   115  	properties[SvcFieldModifyTime] = time.Now()
   116  
   117  	if err = ss.handler.UpdateValue(tblNameService, svc.ID, properties); err != nil {
   118  		log.Errorf("[Store][boltdb] delete service alias error, %v", err)
   119  	}
   120  
   121  	return store.Error(err)
   122  }
   123  
   124  // UpdateServiceAlias update service alias
   125  func (ss *serviceStore) UpdateServiceAlias(alias *model.Service, needUpdateOwner bool) error {
   126  	if alias.ID == "" || alias.Name == "" || alias.Namespace == "" ||
   127  		alias.Revision == "" || alias.Reference == "" || (needUpdateOwner && alias.Owner == "") {
   128  		return store.NewStatusError(store.EmptyParamsErr, "update Service Alias missing some params")
   129  	}
   130  
   131  	properties := make(map[string]interface{})
   132  	properties[SvcFieldName] = alias.Name
   133  	properties[SvcFieldNamespace] = alias.Namespace
   134  	properties[SvcFieldComment] = alias.Comment
   135  	properties[SvcFieldRevision] = alias.Revision
   136  	properties[SvcFieldToken] = alias.Token
   137  	properties[SvcFieldOwner] = alias.Owner
   138  	properties[SvcFieldReference] = alias.Reference
   139  	properties[SvcFieldModifyTime] = time.Now()
   140  
   141  	err := ss.handler.UpdateValue(tblNameService, alias.ID, properties)
   142  
   143  	return store.Error(err)
   144  }
   145  
   146  // UpdateService update service
   147  func (ss *serviceStore) UpdateService(service *model.Service, needUpdateOwner bool) error {
   148  	if service.ID == "" || service.Name == "" || service.Namespace == "" ||
   149  		service.Token == "" || service.Owner == "" || service.Revision == "" {
   150  		return store.NewStatusError(store.EmptyParamsErr, "Update Service missing some params")
   151  	}
   152  
   153  	properties := make(map[string]interface{})
   154  
   155  	properties[SvcFieldName] = service.Name
   156  	properties[SvcFieldNamespace] = service.Namespace
   157  	properties[SvcFieldDepartment] = service.Department
   158  	properties[SvcFieldBusiness] = service.Business
   159  	properties[SvcFieldMeta] = service.Meta
   160  	properties[SvcFieldComment] = service.Comment
   161  	properties[SvcFieldRevision] = service.Revision
   162  	properties[SvcFieldToken] = service.Token
   163  	properties[SvcFieldOwner] = service.Owner
   164  	properties[SvcFieldPorts] = service.Ports
   165  	properties[SvcFieldReference] = service.Reference
   166  	properties[SvcFieldCmdbMod1] = service.CmdbMod1
   167  	properties[SvcFieldCmdbMod2] = service.CmdbMod2
   168  	properties[SvcFieldCmdbMod3] = service.CmdbMod3
   169  	properties[SvcFieldModifyTime] = time.Now()
   170  
   171  	err := ss.handler.UpdateValue(tblNameService, service.ID, properties)
   172  
   173  	serr := store.Error(err)
   174  	if store.Code(serr) == store.DuplicateEntryErr {
   175  		serr = store.NewStatusError(store.DataConflictErr, err.Error())
   176  	}
   177  	return serr
   178  }
   179  
   180  // UpdateServiceToken update service token
   181  func (ss *serviceStore) UpdateServiceToken(serviceID string, token string, revision string) error {
   182  
   183  	properties := make(map[string]interface{})
   184  	properties[SvcFieldToken] = token
   185  	properties[SvcFieldRevision] = revision
   186  	properties[SvcFieldModifyTime] = time.Now()
   187  
   188  	err := ss.handler.UpdateValue(tblNameService, serviceID, properties)
   189  
   190  	return store.Error(err)
   191  }
   192  
   193  // GetSourceServiceToken get source service token
   194  func (ss *serviceStore) GetSourceServiceToken(name string, namespace string) (*model.Service, error) {
   195  	var out model.Service
   196  	s, err := ss.getServiceByNameAndNs(name, namespace)
   197  	switch {
   198  	case err == sql.ErrNoRows:
   199  		return nil, nil
   200  	case err != nil:
   201  		return nil, err
   202  	case s == nil:
   203  		return nil, nil
   204  	default:
   205  		out.ID = s.ID
   206  		out.Token = s.Token
   207  		out.PlatformID = s.PlatformID
   208  		out.Name = name
   209  		out.Namespace = namespace
   210  		return &out, nil
   211  	}
   212  }
   213  
   214  // GetService get service details based on service name and namespace
   215  func (ss *serviceStore) GetService(name string, namespace string) (*model.Service, error) {
   216  	s, err := ss.getServiceByNameAndNs(name, namespace)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  
   221  	if s == nil {
   222  		return nil, nil
   223  	}
   224  
   225  	return s, nil
   226  }
   227  
   228  // GetServiceByID get service detail by service id
   229  func (ss *serviceStore) GetServiceByID(id string) (*model.Service, error) {
   230  	service, err := ss.getServiceByID(id)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	return service, nil
   236  }
   237  
   238  // GetServices query corresponding services and numbers according to relevant conditions
   239  func (ss *serviceStore) GetServices(serviceFilters, serviceMetas map[string]string,
   240  	instanceFilters *store.InstanceArgs, offset, limit uint32) (uint32, []*model.Service, error) {
   241  
   242  	totalCount, services, err := ss.getServices(serviceFilters, serviceMetas, instanceFilters, offset, limit)
   243  	if err != nil {
   244  		return 0, nil, err
   245  	}
   246  
   247  	return totalCount, services, nil
   248  }
   249  
   250  // GetServicesCount get the total number of all services
   251  func (ss *serviceStore) GetServicesCount() (uint32, error) {
   252  
   253  	count, err := ss.handler.CountValues(tblNameService)
   254  	if err != nil {
   255  		log.Errorf("[Store][boltdb] load service from kv error %v", err)
   256  		return 0, err
   257  	}
   258  
   259  	return uint32(count), nil
   260  }
   261  
   262  // GetMoreServices get incremental services
   263  func (ss *serviceStore) GetMoreServices(
   264  	mtime time.Time, firstUpdate, disableBusiness, needMeta bool) (map[string]*model.Service, error) {
   265  
   266  	fields := []string{SvcFieldModifyTime, SvcFieldValid}
   267  	if disableBusiness {
   268  		fields = append(fields, SvcFieldNamespace)
   269  	}
   270  
   271  	services, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   272  		func(m map[string]interface{}) bool {
   273  			if disableBusiness {
   274  				serviceNs, ok := m[SvcFieldNamespace]
   275  				if !ok {
   276  					return false
   277  				}
   278  				if serviceNs.(string) != SystemNamespace {
   279  					return false
   280  				}
   281  			}
   282  
   283  			svcMTime, ok := m[SvcFieldModifyTime]
   284  			if !ok {
   285  				return false
   286  			}
   287  
   288  			serviceMtime := svcMTime.(time.Time)
   289  
   290  			return !serviceMtime.Before(mtime)
   291  		})
   292  
   293  	if err != nil {
   294  		log.Errorf("[Store][boltdb] load service from kv error, %v", err)
   295  		return nil, err
   296  	}
   297  
   298  	res := make(map[string]*model.Service)
   299  	for k, v := range services {
   300  		res[k] = v.(*model.Service)
   301  	}
   302  
   303  	return res, nil
   304  }
   305  
   306  // GetServiceAliases get list of service aliases
   307  func (ss *serviceStore) GetServiceAliases(
   308  	filter map[string]string, offset uint32, limit uint32) (uint32, []*model.ServiceAlias, error) {
   309  
   310  	// find all alias service with filters
   311  	fields := []string{SvcFieldReference, SvcFieldValid, SvcFieldName, SvcFieldNamespace,
   312  		SvcFieldMeta, SvcFieldDepartment, SvcFieldBusiness}
   313  	for k := range filter {
   314  		fields = append(fields, k)
   315  	}
   316  
   317  	referenceService, services, err := ss.getServiceAliases(filter, fields)
   318  	if err != nil {
   319  		return 0, nil, err
   320  	}
   321  
   322  	// find source service for every alias
   323  	fields = []string{SvcFieldID, SvcFieldName, SvcFieldNamespace, SvcFieldValid}
   324  
   325  	svcName, hasSvcName := filter["service"]
   326  	svcNs, hasSvcNs := filter["namespace"]
   327  
   328  	refServices, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   329  		func(m map[string]interface{}) bool {
   330  			if valid, _ := m[SvcFieldValid].(bool); !valid {
   331  				return false
   332  			}
   333  
   334  			if hasSvcName && m[SvcFieldName].(string) != svcName {
   335  				return false
   336  			}
   337  
   338  			if hasSvcNs && m[SvcFieldNamespace].(string) != svcNs {
   339  				return false
   340  			}
   341  
   342  			_, ok := referenceService[m[SvcFieldID].(string)]
   343  			return ok
   344  		})
   345  
   346  	var serviceAlias []*model.ServiceAlias
   347  	for _, service := range services {
   348  
   349  		if _, ok := refServices[service.Reference]; !ok {
   350  			continue
   351  		}
   352  
   353  		alias := model.ServiceAlias{}
   354  		alias.ID = service.ID
   355  		alias.Alias = service.Name
   356  		alias.AliasNamespace = service.Namespace
   357  		alias.ServiceID = service.Reference
   358  		alias.Service = refServices[service.Reference].(*model.Service).Name
   359  		alias.ModifyTime = service.ModifyTime
   360  		alias.CreateTime = service.CreateTime
   361  		alias.Comment = service.Comment
   362  		alias.Namespace = refServices[service.Reference].(*model.Service).Namespace
   363  		alias.Owner = service.Owner
   364  
   365  		serviceAlias = append(serviceAlias, &alias)
   366  	}
   367  
   368  	return uint32(len(serviceAlias)), doPageAliasServices(serviceAlias, offset, limit), nil
   369  }
   370  
   371  func (ss *serviceStore) getServiceAliases(
   372  	filter map[string]string, fields []string) (map[string]bool, map[string]*model.Service, error) {
   373  	aliasName, isAliasName := filter["alias"]
   374  	aliasNamespace, isAliasNamespace := filter["alias_namespace"]
   375  	keys, isKeys := filter["keys"]
   376  	values, isValues := filter["values"]
   377  	department, isDepartment := filter["department"]
   378  	business, isBusiness := filter["business"]
   379  
   380  	referenceService := make(map[string]bool)
   381  	services, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   382  		func(m map[string]interface{}) bool {
   383  			if valid, _ := m[SvcFieldValid].(bool); !valid {
   384  				return false
   385  			}
   386  
   387  			// judge whether it is alias by whether there is a reference
   388  			if reference, _ := m[SvcFieldReference].(string); reference == "" {
   389  				return false
   390  			}
   391  
   392  			// filter by other
   393  			if isAliasName {
   394  				svcName, _ := m[SvcFieldName].(string)
   395  				aliasName, isWild := utils.ParseWildName(aliasName)
   396  				if isWild && !strings.Contains(svcName, aliasName) {
   397  					return false
   398  				}
   399  				if svcName != aliasName {
   400  					return false
   401  				}
   402  			}
   403  			if isAliasNamespace {
   404  				svcNamespace, _ := m[SvcFieldNamespace].(string)
   405  				aliasNamespace, isWild := utils.ParseWildName(aliasNamespace)
   406  				if isWild && !strings.Contains(svcNamespace, aliasNamespace) {
   407  					return false
   408  				}
   409  				if svcNamespace != aliasNamespace {
   410  					return false
   411  				}
   412  			}
   413  
   414  			if isKeys {
   415  				svcMeta, ok := m[SvcFieldMeta]
   416  				if !ok {
   417  					return false
   418  				}
   419  				metaValue, ok := svcMeta.(map[string]string)[keys]
   420  				if !ok {
   421  					return false
   422  				}
   423  				if isValues && values != metaValue {
   424  					return false
   425  				}
   426  			}
   427  
   428  			if isDepartment {
   429  				svcDepartment, ok := m[SvcFieldDepartment]
   430  				if !ok {
   431  					return false
   432  				}
   433  				if department != svcDepartment.(string) {
   434  					return false
   435  				}
   436  			}
   437  			if isBusiness && business != m[SvcFieldBusiness].(string) {
   438  				svcBusiness, ok := m[SvcFieldBusiness]
   439  				if !ok {
   440  					return false
   441  				}
   442  				if business != svcBusiness.(string) {
   443  					return false
   444  				}
   445  			}
   446  			referenceService[m[SvcFieldReference].(string)] = true
   447  			return true
   448  		})
   449  	if err != nil {
   450  		log.Errorf("[Store][boltdb] load service from kv error, %v", err)
   451  		return nil, nil, err
   452  	}
   453  	if len(services) == 0 {
   454  		return referenceService, map[string]*model.Service{}, nil
   455  	}
   456  
   457  	ret := make(map[string]*model.Service, len(services))
   458  	for k := range services {
   459  		ret[k] = services[k].(*model.Service)
   460  	}
   461  
   462  	return referenceService, ret, nil
   463  }
   464  
   465  // GetSystemServices get system services
   466  func (ss *serviceStore) GetSystemServices() ([]*model.Service, error) {
   467  
   468  	fields := []string{SvcFieldNamespace}
   469  
   470  	services, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   471  		func(m map[string]interface{}) bool {
   472  			svcNamespace, ok := m[SvcFieldNamespace]
   473  			if !ok {
   474  				return false
   475  			}
   476  			if svcNamespace.(string) == SystemNamespace {
   477  				return true
   478  			}
   479  			return false
   480  		})
   481  	if err != nil {
   482  		log.Errorf("[Store][boltdb] load service from kv error, %v", err)
   483  		return nil, err
   484  	}
   485  
   486  	ret := make(map[string]*model.Service, len(services))
   487  	for k := range services {
   488  		ret[k] = services[k].(*model.Service)
   489  	}
   490  
   491  	return getRealServicesList(ret, 0, uint32(len(services))), nil
   492  }
   493  
   494  // GetServicesBatch get service id and other information in batch
   495  func (ss *serviceStore) GetServicesBatch(services []*model.Service) ([]*model.Service, error) {
   496  
   497  	if len(services) == 0 {
   498  		return nil, nil
   499  	}
   500  
   501  	fields := []string{SvcFieldName, SvcFieldNamespace}
   502  
   503  	serviceInfo := make(map[string]string)
   504  
   505  	for _, service := range services {
   506  		serviceInfo[service.Name] = service.Namespace
   507  	}
   508  
   509  	svcs, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   510  		func(m map[string]interface{}) bool {
   511  
   512  			svcName, ok := m[SvcFieldName]
   513  			if !ok {
   514  				return false
   515  			}
   516  			svcNs, ok := m[SvcFieldNamespace]
   517  			if !ok {
   518  				return false
   519  			}
   520  
   521  			name := svcName.(string)
   522  			namespace := svcNs.(string)
   523  			ns, ok := serviceInfo[name]
   524  			if !ok {
   525  				return false
   526  			}
   527  			if ns != namespace {
   528  				return false
   529  			}
   530  			return true
   531  		})
   532  	if err != nil {
   533  		log.Errorf("[Store][boltdb] load service from kv error, %v", err)
   534  		return nil, err
   535  	}
   536  
   537  	ret := make(map[string]*model.Service, len(svcs))
   538  	for k := range svcs {
   539  		ret[k] = svcs[k].(*model.Service)
   540  	}
   541  
   542  	return getRealServicesList(ret, 0, uint32(len(services))), nil
   543  }
   544  
   545  func (ss *serviceStore) getServiceByNameAndNs(name string, namespace string) (*model.Service, error) {
   546  
   547  	out, err := ss.getServiceByNameAndNsCommon(name, namespace, true)
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  
   552  	if out == nil || len(out) == 0 {
   553  		return nil, nil
   554  	}
   555  
   556  	return out[0], err
   557  }
   558  
   559  // getServiceByNameAndNsCommon 根据服务名和命名空间查询服务,支持模糊查询
   560  func (ss *serviceStore) getServiceByNameAndNsCommon(name string, namespace string, forceValid bool) (
   561  	[]*model.Service, error) {
   562  
   563  	var out []*model.Service
   564  	fields := []string{svcFieldName, SvcFieldNamespace, SvcFieldValid}
   565  
   566  	isNameWild := utils.IsWildName(name)
   567  	isNamespaceWild := utils.IsWildName(namespace)
   568  
   569  	svcSlice, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   570  		func(m map[string]interface{}) bool {
   571  			// valid field filter
   572  			if forceValid {
   573  				valid, ok := m[SvcFieldValid]
   574  				if ok && !valid.(bool) {
   575  					return false
   576  				}
   577  			}
   578  
   579  			// service name field filter
   580  			svcName, ok := m[SvcFieldName]
   581  			if !ok {
   582  				return false
   583  			}
   584  			if len(name) > 0 {
   585  				if isNameWild {
   586  					if !utils.IsWildMatch(svcName.(string), name) {
   587  						return false
   588  					}
   589  				} else if svcName.(string) != name {
   590  					return false
   591  				}
   592  			}
   593  
   594  			// namespace field filter
   595  			svcNs, ok := m[SvcFieldNamespace]
   596  			if !ok {
   597  				return false
   598  			}
   599  			if len(namespace) > 0 {
   600  				if isNamespaceWild {
   601  					if !utils.IsWildMatch(svcNs.(string), namespace) {
   602  						return false
   603  					}
   604  				} else if svcNs.(string) != namespace {
   605  					return false
   606  				}
   607  			}
   608  			return true
   609  		})
   610  	if err != nil {
   611  		return nil, err
   612  	}
   613  
   614  	if len(svcSlice) == 0 {
   615  		return nil, nil
   616  	}
   617  
   618  	out = make([]*model.Service, 0, len(svcSlice))
   619  	for _, v := range svcSlice {
   620  		svc := v.(*model.Service)
   621  		if !svc.Valid {
   622  			continue
   623  		}
   624  		out = append(out, v.(*model.Service))
   625  	}
   626  	if len(out) == 0 {
   627  		return nil, nil
   628  	}
   629  	return out, err
   630  }
   631  
   632  func (ss *serviceStore) getServiceByNameAndNsIgnoreValid(name string, namespace string) (*model.Service, error) {
   633  	var out *model.Service
   634  
   635  	fields := []string{SvcFieldName, SvcFieldNamespace, SvcFieldValid}
   636  
   637  	svc, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   638  		func(m map[string]interface{}) bool {
   639  			svcName, ok := m[SvcFieldName]
   640  			if !ok {
   641  				return false
   642  			}
   643  			svcNs, ok := m[SvcFieldNamespace]
   644  			if !ok {
   645  				return false
   646  			}
   647  
   648  			if svcName.(string) == name && svcNs.(string) == namespace {
   649  				return true
   650  			}
   651  			return false
   652  		})
   653  	if err != nil {
   654  		return nil, err
   655  	}
   656  
   657  	if len(svc) > 1 {
   658  		log.Errorf("[Store][boltdb] multiple services found %v", svc)
   659  		return nil, ErrMultipleSvcFound
   660  	}
   661  
   662  	if len(svc) == 0 {
   663  		return nil, nil
   664  	}
   665  
   666  	// should only find one service
   667  	for _, v := range svc {
   668  		out = v.(*model.Service)
   669  	}
   670  
   671  	return out, err
   672  }
   673  
   674  func (ss *serviceStore) getServiceByID(id string) (*model.Service, error) {
   675  
   676  	fields := []string{SvcFieldID}
   677  
   678  	svc, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   679  		func(m map[string]interface{}) bool {
   680  			svcId, ok := m[SvcFieldID]
   681  			if !ok {
   682  				return false
   683  			}
   684  			if svcId.(string) != id {
   685  				return false
   686  			}
   687  			return true
   688  		})
   689  	if err != nil {
   690  		return nil, err
   691  	}
   692  
   693  	if len(svc) > 1 {
   694  		log.Errorf("[Store][boltdb] multiple services found %v", svc)
   695  		return nil, ErrMultipleSvcFound
   696  	}
   697  
   698  	svcRet := svc[id].(*model.Service)
   699  	if svcRet.Valid {
   700  		return svcRet, nil
   701  	}
   702  
   703  	return nil, err
   704  }
   705  
   706  func (ss *serviceStore) getServices(serviceFilters, serviceMetas map[string]string,
   707  	instanceFilters *store.InstanceArgs, offset, limit uint32) (uint32, []*model.Service, error) {
   708  
   709  	insFiltersIds := make(map[string]bool)
   710  	// int array to string array
   711  	if instanceFilters != nil && (len(instanceFilters.Ports) > 0 || len(instanceFilters.Hosts) > 0) {
   712  
   713  		portArray := make([]string, len(instanceFilters.Ports))
   714  		for i, port := range instanceFilters.Ports {
   715  			portArray[i] = strconv.Itoa(int(port))
   716  		}
   717  
   718  		// get the filtered list of serviceIDs from instanceFilters
   719  		filter := []string{insFieldProto, insFieldValid}
   720  
   721  		inss, err := ss.handler.LoadValuesByFilter(tblNameInstance, filter, &model.Instance{},
   722  			func(m map[string]interface{}) bool {
   723  				valid, ok := m[SvcFieldValid]
   724  				if ok && !valid.(bool) {
   725  					return false
   726  				}
   727  				insPorto, ok := m[insFieldProto]
   728  				if !ok {
   729  					return false
   730  				}
   731  				ins := insPorto.(*apiservice.Instance)
   732  				insHost := ins.GetHost().GetValue()
   733  				insPort := ins.GetPort().GetValue()
   734  
   735  				if len(instanceFilters.Hosts) > 0 {
   736  					ifFound := false
   737  					for _, h := range instanceFilters.Hosts {
   738  						if h == insHost {
   739  							ifFound = true
   740  							break
   741  						}
   742  					}
   743  					if !ifFound {
   744  						return false
   745  					}
   746  				}
   747  				if len(instanceFilters.Ports) > 0 {
   748  					ifFound := false
   749  					for _, p := range instanceFilters.Ports {
   750  						if p == insPort {
   751  							ifFound = true
   752  							break
   753  						}
   754  					}
   755  					if !ifFound {
   756  						return false
   757  					}
   758  				}
   759  				return true
   760  			})
   761  		if err != nil {
   762  			log.Errorf("[Store][boltdb] load instance from kv error %v", err)
   763  			return 0, nil, err
   764  		}
   765  		for _, i := range inss {
   766  			insFiltersIds[i.(*model.Instance).ServiceID] = true
   767  		}
   768  	}
   769  
   770  	fields := []string{SvcFieldValid, SvcFieldNamespace, SvcFieldName, SvcFieldMeta, SvcFieldDepartment,
   771  		SvcFieldBusiness, SvcFieldReference}
   772  	if len(insFiltersIds) > 0 {
   773  		fields = append(fields, SvcFieldID)
   774  	}
   775  
   776  	isKeys := true
   777  	isValues := true
   778  	var keys string
   779  	var values string
   780  
   781  	if len(serviceMetas) == 0 {
   782  		isKeys = false
   783  		isValues = false
   784  	} else {
   785  		for k, v := range serviceMetas {
   786  			keys = k
   787  			values = v
   788  			if values == "" {
   789  				isValues = false
   790  			}
   791  			break
   792  		}
   793  	}
   794  
   795  	name, isName := serviceFilters["name"]
   796  	department, isDepartment := serviceFilters["department"]
   797  	business, isBusiness := serviceFilters["business"]
   798  	namespace, isNamespace := serviceFilters["namespace"]
   799  
   800  	svcs, err := ss.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{},
   801  		func(m map[string]interface{}) bool {
   802  			valid, ok := m[SvcFieldValid]
   803  			if ok && !valid.(bool) {
   804  				return false
   805  			}
   806  			// filter by id
   807  			if len(insFiltersIds) > 0 {
   808  				svcId, ok := m[SvcFieldID]
   809  				if !ok {
   810  					return false
   811  				}
   812  				_, ok = insFiltersIds[svcId.(string)]
   813  				if !ok {
   814  					return false
   815  				}
   816  			}
   817  
   818  			if isNamespace && namespace != "" {
   819  				svcNs, ok := m[SvcFieldNamespace]
   820  				if !ok {
   821  					return false
   822  				}
   823  				if utils.IsPrefixWildName(namespace) {
   824  					return strings.Contains(svcNs.(string), namespace[0:len(namespace)-1])
   825  				}
   826  				if svcNs.(string) != namespace {
   827  					return false
   828  				}
   829  			}
   830  
   831  			// filter by other
   832  			if isName && name != "" {
   833  				svcName, ok := m[SvcFieldName]
   834  				if !ok {
   835  					return false
   836  				}
   837  				if utils.IsPrefixWildName(name) {
   838  					return strings.Contains(svcName.(string), name[0:len(name)-1])
   839  				}
   840  				if svcName.(string) != name {
   841  					return false
   842  				}
   843  			}
   844  
   845  			if isKeys {
   846  				svcMeta, ok := m[SvcFieldMeta]
   847  				if !ok {
   848  					return false
   849  				}
   850  				metaValue, ok := svcMeta.(map[string]string)[keys]
   851  				if !ok {
   852  					return false
   853  				}
   854  				if isValues && values != metaValue {
   855  					return false
   856  				}
   857  			}
   858  
   859  			if isDepartment && department != "" {
   860  				svcDepartment, ok := m[SvcFieldDepartment]
   861  				if !ok {
   862  					return false
   863  				}
   864  				if utils.IsPrefixWildName(department) {
   865  					return strings.Contains(svcDepartment.(string), department[0:len(department)-1])
   866  				}
   867  				if svcDepartment.(string) != department {
   868  					return false
   869  				}
   870  			}
   871  
   872  			if isBusiness && business != "" {
   873  				svcBusiness, ok := m[SvcFieldBusiness]
   874  				if !ok {
   875  					return false
   876  				}
   877  				if utils.IsPrefixWildName(business) {
   878  					return strings.Contains(svcBusiness.(string), business[0:len(business)-1])
   879  				}
   880  				if svcBusiness.(string) != business {
   881  					return false
   882  				}
   883  			}
   884  
   885  			return true
   886  		})
   887  	if err != nil {
   888  		log.Errorf("[Store][boltdb] load service from kv error %v", err)
   889  		return 0, nil, err
   890  	}
   891  	totalCount := len(svcs)
   892  
   893  	ret := make(map[string]*model.Service, len(svcs))
   894  	for k := range svcs {
   895  		ret[k] = svcs[k].(*model.Service)
   896  	}
   897  
   898  	return uint32(totalCount), getRealServicesList(ret, offset, limit), nil
   899  }
   900  
   901  func (ss *serviceStore) cleanInValidService(name, namespace string) error {
   902  	old, err := ss.getServiceByNameAndNsIgnoreValid(name, namespace)
   903  
   904  	if err != nil {
   905  		return err
   906  	}
   907  
   908  	if old == nil {
   909  		return nil
   910  	}
   911  
   912  	if err := ss.handler.DeleteValues(tblNameService, []string{old.ID}); err != nil {
   913  		log.Errorf("[Store][boltdb] delete invalid service error, %+v", err)
   914  		return err
   915  	}
   916  
   917  	return nil
   918  }
   919  
   920  func (ss *serviceStore) GetServiceByNameAndNamespace(name string, namespace string) ([]*model.Service, error) {
   921  	return ss.getServiceByNameAndNsCommon(name, namespace, true)
   922  }
   923  
   924  func getRealServicesList(originServices map[string]*model.Service, offset, limit uint32) []*model.Service {
   925  	services := make([]*model.Service, 0)
   926  	beginIndex := offset
   927  	endIndex := beginIndex + limit
   928  	totalCount := uint32(len(originServices))
   929  	// handle special offset, limit
   930  	if totalCount == 0 {
   931  		return services
   932  	}
   933  	if beginIndex >= endIndex {
   934  		return services
   935  	}
   936  	if beginIndex >= totalCount {
   937  		return services
   938  	}
   939  	if endIndex > totalCount {
   940  		endIndex = totalCount
   941  	}
   942  
   943  	for _, s := range originServices {
   944  		services = append(services, s)
   945  	}
   946  
   947  	sort.Slice(services, func(i, j int) bool {
   948  		// sort by modifyTime
   949  		if services[i].ModifyTime.After(services[j].ModifyTime) {
   950  			return true
   951  		} else if services[i].ModifyTime.Before(services[j].ModifyTime) {
   952  			return false
   953  		} else {
   954  			// compare id if modifyTime is the same
   955  			return services[i].ID < services[j].ID
   956  		}
   957  	})
   958  
   959  	return services[beginIndex:endIndex]
   960  }
   961  
   962  func doPageAliasServices(originServices []*model.ServiceAlias, offset, limit uint32) []*model.ServiceAlias {
   963  	services := make([]*model.ServiceAlias, 0)
   964  	beginIndex := offset
   965  	endIndex := beginIndex + limit
   966  	totalCount := uint32(len(originServices))
   967  	// handle special offset, limit
   968  	if totalCount == 0 {
   969  		return services
   970  	}
   971  	if beginIndex >= endIndex {
   972  		return services
   973  	}
   974  	if beginIndex >= totalCount {
   975  		return services
   976  	}
   977  	if endIndex > totalCount {
   978  		endIndex = totalCount
   979  	}
   980  
   981  	services = append(services, originServices...)
   982  	sort.Slice(services, func(i, j int) bool {
   983  		// sort by modifyTime
   984  		if services[i].ModifyTime.After(services[j].ModifyTime) {
   985  			return true
   986  		} else if services[i].ModifyTime.Before(services[j].ModifyTime) {
   987  			return false
   988  		} else {
   989  			// compare id if modifyTime is the same
   990  			return services[i].ID < services[j].ID
   991  		}
   992  	})
   993  
   994  	return services[beginIndex:endIndex]
   995  }
   996  
   997  func initService(s *model.Service) {
   998  	current := time.Now()
   999  	if s != nil {
  1000  		s.CreateTime = current
  1001  		s.ModifyTime = current
  1002  		s.Valid = true
  1003  	}
  1004  }