github.com/polarismesh/polaris@v1.17.8/test/suit/test_suit.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 testsuit
    19  
    20  import (
    21  	"context"
    22  	"database/sql"
    23  	"errors"
    24  	"fmt"
    25  	"net/http"
    26  	_ "net/http/pprof"
    27  	"os"
    28  	"path/filepath"
    29  	"strings"
    30  	"time"
    31  
    32  	_ "github.com/go-sql-driver/mysql"
    33  	"github.com/google/uuid"
    34  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    35  	apitraffic "github.com/polarismesh/specification/source/go/api/v1/traffic_manage"
    36  	bolt "go.etcd.io/bbolt"
    37  	"gopkg.in/yaml.v2"
    38  
    39  	"github.com/polarismesh/polaris/auth"
    40  	_ "github.com/polarismesh/polaris/auth/defaultauth"
    41  	"github.com/polarismesh/polaris/cache"
    42  	cachetypes "github.com/polarismesh/polaris/cache/api"
    43  	api "github.com/polarismesh/polaris/common/api/v1"
    44  	"github.com/polarismesh/polaris/common/eventhub"
    45  	"github.com/polarismesh/polaris/common/log"
    46  	commonlog "github.com/polarismesh/polaris/common/log"
    47  	"github.com/polarismesh/polaris/common/metrics"
    48  	"github.com/polarismesh/polaris/common/utils"
    49  	"github.com/polarismesh/polaris/config"
    50  	ns "github.com/polarismesh/polaris/namespace"
    51  	"github.com/polarismesh/polaris/plugin"
    52  	_ "github.com/polarismesh/polaris/plugin/cmdb/memory"
    53  	_ "github.com/polarismesh/polaris/plugin/crypto/aes"
    54  	_ "github.com/polarismesh/polaris/plugin/discoverevent/local"
    55  	_ "github.com/polarismesh/polaris/plugin/healthchecker/leader"
    56  	_ "github.com/polarismesh/polaris/plugin/healthchecker/memory"
    57  	_ "github.com/polarismesh/polaris/plugin/healthchecker/redis"
    58  	_ "github.com/polarismesh/polaris/plugin/history/logger"
    59  	_ "github.com/polarismesh/polaris/plugin/password"
    60  	_ "github.com/polarismesh/polaris/plugin/ratelimit/lrurate"
    61  	_ "github.com/polarismesh/polaris/plugin/ratelimit/token"
    62  	_ "github.com/polarismesh/polaris/plugin/statis/logger"
    63  	_ "github.com/polarismesh/polaris/plugin/statis/prometheus"
    64  	"github.com/polarismesh/polaris/service"
    65  	"github.com/polarismesh/polaris/service/batch"
    66  	"github.com/polarismesh/polaris/service/healthcheck"
    67  	"github.com/polarismesh/polaris/store"
    68  	"github.com/polarismesh/polaris/store/boltdb"
    69  	_ "github.com/polarismesh/polaris/store/boltdb"
    70  	sqldb "github.com/polarismesh/polaris/store/mysql"
    71  	testdata "github.com/polarismesh/polaris/test/data"
    72  )
    73  
    74  func init() {
    75  	go func() {
    76  		http.ListenAndServe("0.0.0.0:16060", nil)
    77  	}()
    78  }
    79  
    80  const (
    81  	tblNameNamespace          = "namespace"
    82  	tblNameInstance           = "instance"
    83  	tblNameService            = "service"
    84  	tblNameRouting            = "routing"
    85  	tblRateLimitConfig        = "ratelimit_config"
    86  	tblRateLimitRevision      = "ratelimit_revision"
    87  	tblCircuitBreaker         = "circuitbreaker_rule"
    88  	tblCircuitBreakerRelation = "circuitbreaker_rule_relation"
    89  	tblNameL5                 = "l5"
    90  	tblNameRoutingV2          = "routing_config_v2"
    91  	tblClient                 = "client"
    92  )
    93  
    94  var (
    95  	testNamespace = "testNamespace123qwe"
    96  	testGroup     = "testGroup"
    97  	testFile      = "testFile"
    98  	testContent   = "testContent"
    99  	operator      = "polaris"
   100  	size          = 7
   101  )
   102  
   103  const (
   104  	templateName1 = "t1"
   105  	templateName2 = "t2"
   106  )
   107  
   108  type Bootstrap struct {
   109  	Logger map[string]*commonlog.Options
   110  }
   111  
   112  type TestConfig struct {
   113  	Bootstrap    Bootstrap          `yaml:"bootstrap"`
   114  	Cache        cache.Config       `yaml:"cache"`
   115  	Namespace    ns.Config          `yaml:"namespace"`
   116  	Naming       service.Config     `yaml:"naming"`
   117  	Config       config.Config      `yaml:"config"`
   118  	HealthChecks healthcheck.Config `yaml:"healthcheck"`
   119  	Store        store.Config       `yaml:"store"`
   120  	Auth         auth.Config        `yaml:"auth"`
   121  	Plugin       plugin.Config      `yaml:"plugin"`
   122  	ReplaceStore store.Store
   123  }
   124  
   125  var InjectTestDataClean func() TestDataClean
   126  
   127  func SetTestDataClean(callback func() TestDataClean) {
   128  	InjectTestDataClean = callback
   129  }
   130  
   131  type DiscoverTestSuit struct {
   132  	cfg                 *TestConfig
   133  	configServer        config.ConfigCenterServer
   134  	configOriginSvr     config.ConfigCenterServer
   135  	server              service.DiscoverServer
   136  	originSvr           service.DiscoverServer
   137  	healthCheckServer   *healthcheck.Server
   138  	cacheMgr            *cache.CacheManager
   139  	userMgn             auth.UserServer
   140  	strategyMgn         auth.StrategyServer
   141  	namespaceSvr        ns.NamespaceOperateServer
   142  	cancelFlag          bool
   143  	updateCacheInterval time.Duration
   144  	DefaultCtx          context.Context
   145  	cancel              context.CancelFunc
   146  	Storage             store.Store
   147  	bc                  *batch.Controller
   148  	cleanDataOp         TestDataClean
   149  	caller              func() store.Store
   150  }
   151  
   152  func (d *DiscoverTestSuit) InjectSuit(*DiscoverTestSuit) {
   153  
   154  }
   155  
   156  func (d *DiscoverTestSuit) CacheMgr() *cache.CacheManager {
   157  	return d.cacheMgr
   158  }
   159  
   160  func (d *DiscoverTestSuit) GetTestDataClean() TestDataClean {
   161  	return d.cleanDataOp
   162  }
   163  
   164  func (d *DiscoverTestSuit) DiscoverServer() service.DiscoverServer {
   165  	return d.server
   166  }
   167  
   168  func (d *DiscoverTestSuit) OriginDiscoverServer() service.DiscoverServer {
   169  	return d.originSvr
   170  }
   171  
   172  func (d *DiscoverTestSuit) ConfigServer() config.ConfigCenterServer {
   173  	return d.configServer
   174  }
   175  
   176  func (d *DiscoverTestSuit) OriginConfigServer() *config.Server {
   177  	return d.configOriginSvr.(*config.Server)
   178  }
   179  
   180  func (d *DiscoverTestSuit) HealthCheckServer() *healthcheck.Server {
   181  	return d.healthCheckServer
   182  }
   183  
   184  func (d *DiscoverTestSuit) NamespaceServer() ns.NamespaceOperateServer {
   185  	return d.namespaceSvr
   186  }
   187  
   188  func (d *DiscoverTestSuit) UserServer() auth.UserServer {
   189  	return d.userMgn
   190  }
   191  
   192  func (d *DiscoverTestSuit) StrategyServer() auth.StrategyServer {
   193  	return d.strategyMgn
   194  }
   195  
   196  func (d *DiscoverTestSuit) UpdateCacheInterval() time.Duration {
   197  	return d.updateCacheInterval
   198  }
   199  
   200  func (d *DiscoverTestSuit) BatchController() *batch.Controller {
   201  	return d.bc
   202  }
   203  
   204  // 加载配置
   205  func (d *DiscoverTestSuit) loadConfig() error {
   206  
   207  	d.cfg = new(TestConfig)
   208  
   209  	confFileName := testdata.Path("service_test.yaml")
   210  	if os.Getenv("STORE_MODE") == "sqldb" {
   211  		fmt.Printf("run store mode : sqldb\n")
   212  		confFileName = testdata.Path("service_test_sqldb.yaml")
   213  		d.DefaultCtx = context.WithValue(d.DefaultCtx, utils.ContextAuthTokenKey,
   214  			"nu/0WRA4EqSR1FagrjRj0fZwPXuGlMpX+zCuWu4uMqy8xr1vRjisSbA25aAC3mtU8MeeRsKhQiDAynUR09I=")
   215  	} else {
   216  		fmt.Printf("run store mode : boltdb\n")
   217  	}
   218  	// 如果有额外定制的配置文件,优先采用
   219  	if val := os.Getenv("POLARIS_TEST_BOOTSTRAP_FILE"); val != "" {
   220  		confFileName = val
   221  	}
   222  	buf, err := os.ReadFile(confFileName)
   223  	if nil != err {
   224  		return fmt.Errorf("read file %s error", confFileName)
   225  	}
   226  
   227  	if err = parseYamlContent(string(buf), d.cfg); err != nil {
   228  		fmt.Printf("[ERROR] %v\n", err)
   229  		return err
   230  	}
   231  
   232  	resources := d.cfg.Cache.Resources
   233  	for i := range resources {
   234  		item := resources[i]
   235  		if item.Name == "configFile" {
   236  			item.Option = map[string]interface{}{
   237  				"cachePath": filepath.Join("/tmp/polaris/cache/", uuid.NewString()),
   238  			}
   239  		}
   240  		resources[i] = item
   241  	}
   242  	d.cfg.Cache.Resources = resources
   243  
   244  	return err
   245  }
   246  
   247  func parseYamlContent(content string, conf *TestConfig) error {
   248  	if err := yaml.Unmarshal([]byte(replaceEnv(content)), conf); nil != err {
   249  		return fmt.Errorf("parse yaml %s error:%w", content, err)
   250  	}
   251  	return nil
   252  }
   253  
   254  // replaceEnv replace holder by env list
   255  func replaceEnv(configContent string) string {
   256  	return os.ExpandEnv(configContent)
   257  }
   258  
   259  // 判断一个resp是否执行成功
   260  func RespSuccess(resp api.ResponseMessage) bool {
   261  	ret := api.CalcCode(resp) == 200
   262  	return ret
   263  }
   264  
   265  type options func(cfg *TestConfig)
   266  
   267  func (d *DiscoverTestSuit) Initialize(opts ...options) error {
   268  	return d.initialize(opts...)
   269  }
   270  
   271  func (d *DiscoverTestSuit) ReplaceStore(caller func() store.Store) {
   272  	d.caller = caller
   273  }
   274  
   275  // 内部初始化函数
   276  func (d *DiscoverTestSuit) initialize(opts ...options) error {
   277  	// 初始化defaultCtx
   278  	d.DefaultCtx = context.WithValue(context.Background(), utils.StringContext("request-id"), "test-1")
   279  	d.DefaultCtx = context.WithValue(d.DefaultCtx, utils.ContextAuthTokenKey,
   280  		"nu/0WRA4EqSR1FagrjRj0fZwPXuGlMpX+zCuWu4uMqy8xr1vRjisSbA25aAC3mtU8MeeRsKhQiDAynUR09I=")
   281  
   282  	if err := os.RemoveAll("polaris.bolt"); err != nil {
   283  		if !errors.Is(err, os.ErrNotExist) {
   284  			panic(err)
   285  		}
   286  	}
   287  
   288  	if err := d.loadConfig(); err != nil {
   289  		panic(err)
   290  	}
   291  
   292  	for i := range opts {
   293  		opts[i](d.cfg)
   294  	}
   295  
   296  	d.cleanDataOp = d
   297  	if InjectTestDataClean != nil {
   298  		d.cleanDataOp = InjectTestDataClean()
   299  	}
   300  	// 注入测试套件相关数据信息
   301  	d.cleanDataOp.InjectSuit(d)
   302  
   303  	_ = commonlog.Configure(d.cfg.Bootstrap.Logger)
   304  
   305  	metrics.InitMetrics()
   306  	eventhub.InitEventHub()
   307  
   308  	// 初始化存储层
   309  	if d.caller != nil {
   310  		d.Storage = d.caller()
   311  	} else {
   312  		store.SetStoreConfig(&d.cfg.Store)
   313  		s, _ := store.TestGetStore()
   314  		d.Storage = s
   315  	}
   316  
   317  	plugin.SetPluginConfig(&d.cfg.Plugin)
   318  
   319  	ctx, cancel := context.WithCancel(context.Background())
   320  
   321  	d.cancel = cancel
   322  
   323  	// 初始化缓存模块
   324  	cacheMgn, err := cache.TestCacheInitialize(ctx, &d.cfg.Cache, d.Storage)
   325  	if err != nil {
   326  		panic(err)
   327  	}
   328  	d.cacheMgr = cacheMgn
   329  
   330  	// 初始化鉴权层
   331  	userMgn, strategyMgn, err := auth.TestInitialize(ctx, &d.cfg.Auth, d.Storage, cacheMgn)
   332  	if err != nil {
   333  		panic(err)
   334  	}
   335  	d.userMgn = userMgn
   336  	d.strategyMgn = strategyMgn
   337  
   338  	// 初始化命名空间模块
   339  	namespaceSvr, err := ns.TestInitialize(ctx, &d.cfg.Namespace, d.Storage, cacheMgn, userMgn, strategyMgn)
   340  	if err != nil {
   341  		panic(err)
   342  	}
   343  	d.namespaceSvr = namespaceSvr
   344  
   345  	// 批量控制器
   346  	namingBatchConfig, err := batch.ParseBatchConfig(d.cfg.Naming.Batch)
   347  	if err != nil {
   348  		panic(err)
   349  	}
   350  	healthBatchConfig, err := batch.ParseBatchConfig(d.cfg.HealthChecks.Batch)
   351  	if err != nil {
   352  		panic(err)
   353  	}
   354  
   355  	batchConfig := &batch.Config{
   356  		Register:         namingBatchConfig.Register,
   357  		Deregister:       namingBatchConfig.Register,
   358  		ClientRegister:   namingBatchConfig.ClientRegister,
   359  		ClientDeregister: namingBatchConfig.ClientDeregister,
   360  		Heartbeat:        healthBatchConfig.Heartbeat,
   361  	}
   362  
   363  	bc, err := batch.NewBatchCtrlWithConfig(d.Storage, cacheMgn, batchConfig)
   364  	if err != nil {
   365  		log.Errorf("new batch ctrl with config err: %s", err.Error())
   366  		panic(err)
   367  	}
   368  	bc.Start(ctx)
   369  	d.bc = bc
   370  
   371  	if len(d.cfg.HealthChecks.LocalHost) == 0 {
   372  		d.cfg.HealthChecks.LocalHost = utils.LocalHost // 补充healthCheck的配置
   373  	}
   374  	healthCheckServer, err := healthcheck.TestInitialize(ctx, &d.cfg.HealthChecks, d.cfg.Cache.Open, bc, d.Storage)
   375  	if err != nil {
   376  		panic(err)
   377  	}
   378  	healthcheck.SetServer(healthCheckServer)
   379  	d.healthCheckServer = healthCheckServer
   380  	cacheProvider, err := healthCheckServer.CacheProvider()
   381  	if err != nil {
   382  		panic(err)
   383  	}
   384  	healthCheckServer.SetServiceCache(cacheMgn.Service())
   385  	healthCheckServer.SetInstanceCache(cacheMgn.Instance())
   386  
   387  	// 为 instance 的 cache 添加 健康检查的 Listener
   388  	cacheMgn.AddListener(cachetypes.CacheInstance, []cachetypes.Listener{cacheProvider})
   389  	cacheMgn.AddListener(cachetypes.CacheClient, []cachetypes.Listener{cacheProvider})
   390  
   391  	val, originVal, err := service.TestInitialize(ctx, &d.cfg.Naming, &d.cfg.Cache, bc, cacheMgn, d.Storage, namespaceSvr,
   392  		healthCheckServer, userMgn, strategyMgn)
   393  	if err != nil {
   394  		panic(err)
   395  	}
   396  	d.server = val
   397  	d.originSvr = originVal
   398  
   399  	confVal, confOriginVal, err := config.TestInitialize(ctx, d.cfg.Config, d.Storage, cacheMgn, namespaceSvr, userMgn, strategyMgn)
   400  	if err != nil {
   401  		panic(err)
   402  	}
   403  	d.configServer = confVal
   404  	d.configOriginSvr = confOriginVal
   405  
   406  	// 多等待一会
   407  	d.updateCacheInterval = d.server.Cache().GetUpdateCacheInterval() + time.Millisecond*500
   408  
   409  	time.Sleep(5 * time.Second)
   410  	return nil
   411  }
   412  
   413  func (d *DiscoverTestSuit) Destroy() {
   414  	d.cancel()
   415  	d.healthCheckServer.Destroy()
   416  	_ = d.cacheMgr.Close()
   417  	_ = d.Storage.Destroy()
   418  }
   419  
   420  func (d *DiscoverTestSuit) CleanReportClient() {
   421  	if d.Storage.Name() == sqldb.STORENAME {
   422  		func() {
   423  			tx, err := d.Storage.StartTx()
   424  			if err != nil {
   425  				panic(err)
   426  			}
   427  
   428  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   429  			defer rollbackDbTx(dbTx)
   430  
   431  			if _, err := dbTx.Exec("delete from client"); err != nil {
   432  				panic(err)
   433  			}
   434  			if _, err := dbTx.Exec("delete from client_stat"); err != nil {
   435  				panic(err)
   436  			}
   437  
   438  			commitDbTx(dbTx)
   439  		}()
   440  	} else if d.Storage.Name() == boltdb.STORENAME {
   441  		func() {
   442  			tx, err := d.Storage.StartTx()
   443  			if err != nil {
   444  				panic(err)
   445  			}
   446  
   447  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   448  			defer rollbackBoltTx(dbTx)
   449  
   450  			if err := dbTx.DeleteBucket([]byte(tblClient)); err != nil {
   451  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   452  					rollbackBoltTx(dbTx)
   453  					panic(err)
   454  				}
   455  			}
   456  
   457  			commitBoltTx(dbTx)
   458  		}()
   459  	}
   460  }
   461  
   462  func rollbackDbTx(dbTx *sqldb.BaseTx) {
   463  	if err := dbTx.Rollback(); err != nil {
   464  		log.Errorf("fail to rollback db tx, err %v", err)
   465  	}
   466  }
   467  
   468  func commitDbTx(dbTx *sqldb.BaseTx) {
   469  	if err := dbTx.Commit(); err != nil {
   470  		log.Errorf("fail to commit db tx, err %v", err)
   471  	}
   472  }
   473  
   474  func rollbackBoltTx(tx *bolt.Tx) {
   475  	if err := tx.Rollback(); err != nil {
   476  		log.Errorf("fail to rollback bolt tx, err %v", err)
   477  	}
   478  }
   479  
   480  func commitBoltTx(tx *bolt.Tx) {
   481  	if err := tx.Commit(); err != nil {
   482  		log.Errorf("fail to commit bolt tx, err %v", err)
   483  	}
   484  }
   485  
   486  // 从数据库彻底删除命名空间
   487  func (d *DiscoverTestSuit) CleanNamespace(name string) {
   488  	if name == "" {
   489  		panic("name is empty")
   490  	}
   491  
   492  	log.Infof("clean namespace: %s", name)
   493  
   494  	if d.Storage.Name() == sqldb.STORENAME {
   495  		str := "delete from namespace where name = ?"
   496  		func() {
   497  			tx, err := d.Storage.StartTx()
   498  			if err != nil {
   499  				panic(err)
   500  			}
   501  
   502  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   503  			defer rollbackDbTx(dbTx)
   504  
   505  			if _, err := dbTx.Exec(str, name); err != nil {
   506  				panic(err)
   507  			}
   508  
   509  			commitDbTx(dbTx)
   510  		}()
   511  	} else if d.Storage.Name() == boltdb.STORENAME {
   512  		func() {
   513  			tx, err := d.Storage.StartTx()
   514  			if err != nil {
   515  				panic(err)
   516  			}
   517  
   518  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   519  			if err := dbTx.Bucket([]byte(tblNameNamespace)).DeleteBucket([]byte(name)); err != nil {
   520  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   521  					rollbackBoltTx(dbTx)
   522  					panic(err)
   523  				}
   524  			}
   525  
   526  			commitBoltTx(dbTx)
   527  		}()
   528  	}
   529  }
   530  
   531  // 从数据库彻底删除全部服务
   532  func (d *DiscoverTestSuit) CleanAllService() {
   533  
   534  	if d.Storage.Name() == sqldb.STORENAME {
   535  		func() {
   536  			tx, err := d.Storage.StartTx()
   537  			if err != nil {
   538  				panic(err)
   539  			}
   540  
   541  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   542  
   543  			defer rollbackDbTx(dbTx)
   544  
   545  			if _, err := dbTx.Exec("delete from service_metadata"); err != nil {
   546  				rollbackDbTx(dbTx)
   547  				panic(err)
   548  			}
   549  
   550  			if _, err := dbTx.Exec("delete from service"); err != nil {
   551  				rollbackDbTx(dbTx)
   552  				panic(err)
   553  			}
   554  
   555  			if _, err := dbTx.Exec("delete from owner_service_map"); err != nil {
   556  				rollbackDbTx(dbTx)
   557  				panic(err)
   558  			}
   559  
   560  			commitDbTx(dbTx)
   561  		}()
   562  	} else if d.Storage.Name() == boltdb.STORENAME {
   563  		func() {
   564  			tx, err := d.Storage.StartTx()
   565  			if err != nil {
   566  				panic(err)
   567  			}
   568  
   569  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   570  			defer rollbackBoltTx(dbTx)
   571  
   572  			if err := dbTx.DeleteBucket([]byte(tblNameService)); err != nil {
   573  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   574  					rollbackBoltTx(dbTx)
   575  					panic(err)
   576  				}
   577  			}
   578  
   579  			commitBoltTx(dbTx)
   580  		}()
   581  	}
   582  }
   583  
   584  // 从数据库彻底删除服务
   585  func (d *DiscoverTestSuit) CleanService(name, namespace string) {
   586  
   587  	if d.Storage.Name() == sqldb.STORENAME {
   588  		func() {
   589  			tx, err := d.Storage.StartTx()
   590  			if err != nil {
   591  				panic(err)
   592  			}
   593  
   594  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   595  
   596  			defer rollbackDbTx(dbTx)
   597  
   598  			str := "select id from service where name = ? and namespace = ?"
   599  			var id string
   600  			err = dbTx.QueryRow(str, name, namespace).Scan(&id)
   601  			switch {
   602  			case err == sql.ErrNoRows:
   603  				return
   604  			case err != nil:
   605  				panic(err)
   606  			}
   607  
   608  			if _, err := dbTx.Exec("delete from service_metadata where id = ?", id); err != nil {
   609  				rollbackDbTx(dbTx)
   610  				panic(err)
   611  			}
   612  
   613  			if _, err := dbTx.Exec("delete from service where id = ?", id); err != nil {
   614  				rollbackDbTx(dbTx)
   615  				panic(err)
   616  			}
   617  
   618  			if _, err := dbTx.Exec(
   619  				"delete from owner_service_map where service=? and namespace=?", name, namespace); err != nil {
   620  				rollbackDbTx(dbTx)
   621  				panic(err)
   622  			}
   623  
   624  			commitDbTx(dbTx)
   625  		}()
   626  	} else if d.Storage.Name() == boltdb.STORENAME {
   627  		func() {
   628  			svc, err := d.Storage.GetService(name, namespace)
   629  			if err != nil {
   630  				panic(err)
   631  			}
   632  			if svc == nil {
   633  				return
   634  			}
   635  
   636  			tx, err := d.Storage.StartTx()
   637  			if err != nil {
   638  				panic(err)
   639  			}
   640  
   641  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   642  			defer rollbackBoltTx(dbTx)
   643  
   644  			if err := dbTx.Bucket([]byte(tblNameService)).DeleteBucket([]byte(svc.ID)); err != nil {
   645  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   646  					rollbackBoltTx(dbTx)
   647  					panic(err)
   648  				}
   649  			}
   650  
   651  			commitBoltTx(dbTx)
   652  		}()
   653  	}
   654  }
   655  
   656  // clean services
   657  func (d *DiscoverTestSuit) CleanServices(services []*apiservice.Service) {
   658  
   659  	if d.Storage.Name() == sqldb.STORENAME {
   660  		func() {
   661  			tx, err := d.Storage.StartTx()
   662  			if err != nil {
   663  				panic(err)
   664  			}
   665  
   666  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   667  
   668  			defer rollbackDbTx(dbTx)
   669  
   670  			str := "delete from service where name = ? and namespace = ?"
   671  			cleanOwnerSql := "delete from owner_service_map where service=? and namespace=?"
   672  			for _, service := range services {
   673  				if _, err := dbTx.Exec(
   674  					str, service.GetName().GetValue(), service.GetNamespace().GetValue()); err != nil {
   675  					panic(err)
   676  				}
   677  				if _, err := dbTx.Exec(
   678  					cleanOwnerSql, service.GetName().GetValue(), service.GetNamespace().GetValue()); err != nil {
   679  					panic(err)
   680  				}
   681  			}
   682  
   683  			commitDbTx(dbTx)
   684  		}()
   685  	} else if d.Storage.Name() == boltdb.STORENAME {
   686  		func() {
   687  			ids := make([]string, 0, len(services))
   688  
   689  			for _, service := range services {
   690  				svc, err := d.Storage.GetService(service.GetName().GetValue(), service.GetNamespace().GetValue())
   691  				if err != nil {
   692  					panic(err)
   693  				}
   694  
   695  				ids = append(ids, svc.ID)
   696  			}
   697  
   698  			tx, err := d.Storage.StartTx()
   699  			if err != nil {
   700  				panic(err)
   701  			}
   702  
   703  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   704  
   705  			for i := range ids {
   706  				if err := dbTx.Bucket([]byte(tblNameService)).DeleteBucket([]byte(ids[i])); err != nil {
   707  					if !errors.Is(err, bolt.ErrBucketNotFound) {
   708  						rollbackBoltTx(dbTx)
   709  						panic(err)
   710  					}
   711  				}
   712  			}
   713  			commitBoltTx(dbTx)
   714  		}()
   715  	}
   716  
   717  }
   718  
   719  // 从数据库彻底删除实例
   720  func (d *DiscoverTestSuit) CleanInstance(instanceID string) {
   721  	if instanceID == "" {
   722  		panic("instanceID is empty")
   723  	}
   724  	log.Infof("clean instance: %s", instanceID)
   725  
   726  	if d.Storage.Name() == sqldb.STORENAME {
   727  		func() {
   728  			tx, err := d.Storage.StartTx()
   729  			if err != nil {
   730  				panic(err)
   731  			}
   732  
   733  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   734  
   735  			defer rollbackDbTx(dbTx)
   736  
   737  			str := "delete from instance where id = ?"
   738  			if _, err := dbTx.Exec(str, instanceID); err != nil {
   739  				rollbackDbTx(dbTx)
   740  				panic(err)
   741  			}
   742  
   743  			commitDbTx(dbTx)
   744  		}()
   745  	} else if d.Storage.Name() == boltdb.STORENAME {
   746  		func() {
   747  			tx, err := d.Storage.StartTx()
   748  			if err != nil {
   749  				panic(err)
   750  			}
   751  
   752  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   753  
   754  			if err := dbTx.Bucket([]byte(tblNameInstance)).DeleteBucket([]byte(instanceID)); err != nil {
   755  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   756  					rollbackBoltTx(dbTx)
   757  					panic(err)
   758  				}
   759  			}
   760  			commitBoltTx(dbTx)
   761  		}()
   762  	}
   763  }
   764  
   765  // 彻底删除一个路由配置
   766  func (d *DiscoverTestSuit) CleanCommonRoutingConfig(service string, namespace string) {
   767  
   768  	if d.Storage.Name() == sqldb.STORENAME {
   769  		func() {
   770  			tx, err := d.Storage.StartTx()
   771  			if err != nil {
   772  				panic(err)
   773  			}
   774  
   775  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   776  
   777  			defer rollbackDbTx(dbTx)
   778  
   779  			str := "delete from routing_config where id in (select id from service where name = ? and namespace = ?)"
   780  			// fmt.Printf("%s %s %s\n", str, service, namespace)
   781  			if _, err := dbTx.Exec(str, service, namespace); err != nil {
   782  				panic(err)
   783  			}
   784  			str = "delete from routing_config_v2"
   785  			// fmt.Printf("%s %s %s\n", str, service, namespace)
   786  			if _, err := dbTx.Exec(str); err != nil {
   787  				panic(err)
   788  			}
   789  
   790  			commitDbTx(dbTx)
   791  		}()
   792  	} else if d.Storage.Name() == boltdb.STORENAME {
   793  		func() {
   794  			svc, err := d.Storage.GetService(service, namespace)
   795  			if err != nil {
   796  				panic(err)
   797  			}
   798  
   799  			if svc == nil {
   800  				return
   801  			}
   802  
   803  			tx, err := d.Storage.StartTx()
   804  			if err != nil {
   805  				panic(err)
   806  			}
   807  
   808  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   809  			defer rollbackBoltTx(dbTx)
   810  
   811  			v1Bucket := dbTx.Bucket([]byte(tblNameRouting))
   812  			if v1Bucket != nil {
   813  				if err := v1Bucket.DeleteBucket([]byte(svc.ID)); err != nil {
   814  					if !errors.Is(err, bolt.ErrBucketNotFound) {
   815  						rollbackBoltTx(dbTx)
   816  						panic(err)
   817  					}
   818  				}
   819  			}
   820  
   821  			if err := dbTx.DeleteBucket([]byte(tblNameRoutingV2)); err != nil {
   822  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   823  					rollbackBoltTx(dbTx)
   824  					panic(err)
   825  				}
   826  			}
   827  			commitBoltTx(dbTx)
   828  		}()
   829  	}
   830  }
   831  
   832  func (d *DiscoverTestSuit) TruncateCommonRoutingConfigV2() {
   833  	if d.Storage.Name() == sqldb.STORENAME {
   834  		func() {
   835  			tx, err := d.Storage.StartTx()
   836  			if err != nil {
   837  				panic(err)
   838  			}
   839  
   840  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   841  			defer rollbackDbTx(dbTx)
   842  
   843  			str := "delete from routing_config_v2"
   844  			if _, err := dbTx.Exec(str); err != nil {
   845  				panic(err)
   846  			}
   847  
   848  			commitDbTx(dbTx)
   849  		}()
   850  	} else if d.Storage.Name() == boltdb.STORENAME {
   851  		func() {
   852  
   853  			tx, err := d.Storage.StartTx()
   854  			if err != nil {
   855  				panic(err)
   856  			}
   857  
   858  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   859  			defer rollbackBoltTx(dbTx)
   860  
   861  			if err := dbTx.DeleteBucket([]byte(tblNameRoutingV2)); err != nil {
   862  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   863  					rollbackBoltTx(dbTx)
   864  					panic(err)
   865  				}
   866  			}
   867  
   868  			commitBoltTx(dbTx)
   869  		}()
   870  	}
   871  }
   872  
   873  // 彻底删除一个路由配置
   874  func (d *DiscoverTestSuit) CleanCommonRoutingConfigV2(rules []*apitraffic.RouteRule) {
   875  
   876  	if d.Storage.Name() == sqldb.STORENAME {
   877  		func() {
   878  			tx, err := d.Storage.StartTx()
   879  			if err != nil {
   880  				panic(err)
   881  			}
   882  
   883  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   884  			defer rollbackDbTx(dbTx)
   885  
   886  			str := "delete from routing_config_v2 where id in (%s)"
   887  
   888  			places := []string{}
   889  			args := []interface{}{}
   890  			for i := range rules {
   891  				places = append(places, "?")
   892  				args = append(args, rules[i].Id)
   893  			}
   894  
   895  			str = fmt.Sprintf(str, strings.Join(places, ","))
   896  			// fmt.Printf("%s %s %s\n", str, service, namespace)
   897  			if _, err := dbTx.Exec(str, args...); err != nil {
   898  				panic(err)
   899  			}
   900  
   901  			commitDbTx(dbTx)
   902  		}()
   903  	} else if d.Storage.Name() == boltdb.STORENAME {
   904  		func() {
   905  
   906  			tx, err := d.Storage.StartTx()
   907  			if err != nil {
   908  				panic(err)
   909  			}
   910  
   911  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   912  			defer rollbackBoltTx(dbTx)
   913  
   914  			for i := range rules {
   915  				if err := dbTx.Bucket([]byte(tblNameRoutingV2)).DeleteBucket([]byte(rules[i].Id)); err != nil {
   916  					if !errors.Is(err, bolt.ErrBucketNotFound) {
   917  						rollbackBoltTx(dbTx)
   918  						panic(err)
   919  					}
   920  				}
   921  			}
   922  
   923  			commitBoltTx(dbTx)
   924  		}()
   925  	}
   926  }
   927  
   928  // 彻底删除限流规则
   929  func (d *DiscoverTestSuit) CleanRateLimit(id string) {
   930  
   931  	if d.Storage.Name() == sqldb.STORENAME {
   932  		func() {
   933  			tx, err := d.Storage.StartTx()
   934  			if err != nil {
   935  				panic(err)
   936  			}
   937  
   938  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   939  
   940  			defer rollbackDbTx(dbTx)
   941  
   942  			str := `delete from ratelimit_config where id = ?`
   943  			if _, err := dbTx.Exec(str, id); err != nil {
   944  				panic(err)
   945  			}
   946  
   947  			commitDbTx(dbTx)
   948  		}()
   949  	} else if d.Storage.Name() == boltdb.STORENAME {
   950  		func() {
   951  			tx, err := d.Storage.StartTx()
   952  			if err != nil {
   953  				panic(err)
   954  			}
   955  
   956  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
   957  
   958  			if err := dbTx.Bucket([]byte(tblRateLimitConfig)).DeleteBucket([]byte(id)); err != nil {
   959  				if !errors.Is(err, bolt.ErrBucketNotFound) {
   960  					rollbackBoltTx(dbTx)
   961  					panic(err)
   962  				}
   963  			}
   964  			commitBoltTx(dbTx)
   965  		}()
   966  	}
   967  }
   968  
   969  func buildCircuitBreakerKey(id, version string) string {
   970  	return fmt.Sprintf("%s_%s", id, version)
   971  }
   972  
   973  // 彻底删除熔断规则
   974  func (d *DiscoverTestSuit) CleanCircuitBreaker(id, version string) {
   975  	log.Infof("clean circuit breaker, id: %s, version: %s", id, version)
   976  
   977  	if d.Storage.Name() == sqldb.STORENAME {
   978  		func() {
   979  			tx, err := d.Storage.StartTx()
   980  			if err != nil {
   981  				panic(err)
   982  			}
   983  
   984  			dbTx := tx.GetDelegateTx().(*sqldb.BaseTx)
   985  
   986  			defer rollbackDbTx(dbTx)
   987  
   988  			str := `delete from circuitbreaker_rule where id = ? and version = ?`
   989  			if _, err := dbTx.Exec(str, id, version); err != nil {
   990  				panic(err)
   991  			}
   992  
   993  			commitDbTx(dbTx)
   994  		}()
   995  	} else if d.Storage.Name() == boltdb.STORENAME {
   996  		func() {
   997  			tx, err := d.Storage.StartTx()
   998  			if err != nil {
   999  				panic(err)
  1000  			}
  1001  
  1002  			dbTx := tx.GetDelegateTx().(*bolt.Tx)
  1003  
  1004  			if err := dbTx.Bucket(
  1005  				[]byte(tblCircuitBreaker)).DeleteBucket([]byte(buildCircuitBreakerKey(id, version))); err != nil {
  1006  				if !errors.Is(err, bolt.ErrBucketNotFound) {
  1007  					panic(err)
  1008  				}
  1009  			}
  1010  
  1011  			commitBoltTx(dbTx)
  1012  		}()
  1013  	}
  1014  }
  1015  
  1016  // 彻底删除熔断规则发布记录
  1017  func (d *DiscoverTestSuit) CleanCircuitBreakerRelation(name, namespace, ruleID, ruleVersion string) {
  1018  }
  1019  
  1020  func (d *DiscoverTestSuit) ClearTestDataWhenUseRDS() error {
  1021  	if d.Storage.Name() == boltdb.STORENAME {
  1022  		proxyTx, err := d.Storage.StartTx()
  1023  		if err != nil {
  1024  			return err
  1025  		}
  1026  
  1027  		tx := proxyTx.GetDelegateTx().(*bolt.Tx)
  1028  
  1029  		bucketName := []string{
  1030  			"ConfigFileGroup",
  1031  			"ConfigFileGroupID",
  1032  			"ConfigFile",
  1033  			"ConfigFileID",
  1034  			"ConfigFileReleaseHistory",
  1035  			"ConfigFileReleaseHistoryID",
  1036  			"ConfigFileRelease",
  1037  			"ConfigFileReleaseID",
  1038  			"ConfigFileTag",
  1039  			"ConfigFileTagID",
  1040  			"namespace",
  1041  		}
  1042  
  1043  		defer tx.Rollback()
  1044  
  1045  		for i := range bucketName {
  1046  			if err := tx.DeleteBucket([]byte(bucketName[i])); err != nil {
  1047  				if !errors.Is(err, bolt.ErrBucketNotFound) {
  1048  					return err
  1049  				}
  1050  			}
  1051  		}
  1052  		return tx.Commit()
  1053  	}
  1054  	if d.Storage.Name() == sqldb.STORENAME {
  1055  		proxyTx, err := d.Storage.StartTx()
  1056  		if err != nil {
  1057  			return err
  1058  		}
  1059  
  1060  		tx := proxyTx.GetDelegateTx().(*sqldb.BaseTx)
  1061  
  1062  		defer tx.Rollback()
  1063  
  1064  		_, err = tx.Exec("delete from config_file_group where namespace = ? ", testNamespace)
  1065  		if err != nil {
  1066  			return err
  1067  		}
  1068  		_, err = tx.Exec("delete from config_file where namespace = ? ", testNamespace)
  1069  		if err != nil {
  1070  			return err
  1071  		}
  1072  		_, err = tx.Exec("delete from config_file_release where namespace = ? ", testNamespace)
  1073  		if err != nil {
  1074  			return err
  1075  		}
  1076  		_, err = tx.Exec("delete from config_file_release_history where namespace = ? ", testNamespace)
  1077  		if err != nil {
  1078  			return err
  1079  		}
  1080  		_, err = tx.Exec("delete from config_file_tag where namespace = ? ", testNamespace)
  1081  		if err != nil {
  1082  			return err
  1083  		}
  1084  		_, err = tx.Exec("delete from namespace where name = ? ", testNamespace)
  1085  		if err != nil {
  1086  			return err
  1087  		}
  1088  		_, err = tx.Exec("delete from config_file_template where name in (?,?) ", templateName1, templateName2)
  1089  		if err != nil {
  1090  			return err
  1091  		}
  1092  		return tx.Commit()
  1093  	}
  1094  	return nil
  1095  }