未验证 提交 e12438aa 编写于 作者: C chris-sun-star 提交者: GitHub

add ob configserver (#943)

上级 bd06e657
......@@ -116,3 +116,8 @@ tools/deploy/distributed.yaml
tools/deploy/obd_profile.sh
tools/deploy/single-with-proxy.yaml
tools/deploy/single.yaml
###### binary and test logs
tools/ob-configserver/bin/*
tools/ob-configserver/tests/*.log
tools/ob-configserver/tests/*.out
Legal Disclaimer
Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail.
法律免责声明
关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。
\ No newline at end of file
include Makefile.common
.PHONY: all test clean build configserver
default: clean fmt build
build: build-debug
build-debug: set-debug-flags configserver
build-release: set-release-flags configserver
set-debug-flags:
@echo Build with debug flags
$(eval LDFLAGS += $(LDFLAGS_DEBUG))
set-release-flags:
@echo Build with release flags
$(eval LDFLAGS += -s -w)
$(eval LDFLAGS += $(LDFLAGS_RELEASE))
configserver:
$(GOBUILD) $(GO_RACE_FLAG) -ldflags '$(OB_CONFIGSERVER_LDFLAGS)' -o bin/ob-configserver cmd/main.go
test:
$(GOTEST) $(GOTEST_PACKAGES)
fmt:
@gofmt -s -w $(filter-out , $(GOFILES))
fmt-check:
@if [ -z "$(UNFMT_FILES)" ]; then \
echo "gofmt check passed"; \
exit 0; \
else \
echo "gofmt check failed, not formatted files:"; \
echo "$(UNFMT_FILES)" | tr -s " " "\n"; \
exit 1; \
fi
tidy:
$(GO) mod tidy
vet:
go vet $$(go list ./...)
clean:
rm -rf $(GOCOVERAGE_FILE)
rm -rf tests/mock/*
rm -rf bin/ob-configserver
$(GO) clean -i ./...
PROJECT=ob-configserver
PROCESSOR=2
VERSION=1.0
PWD ?= $(shell pwd)
GO := GO111MODULE=on GOPROXY=https://mirrors.aliyun.com/goproxy/,direct go
BUILD_FLAG := -p $(PROCESSOR)
GOBUILD := $(GO) build $(BUILD_FLAG)
GOBUILDCOVERAGE := $(GO) test -covermode=count -coverpkg="../..." -c .
GOCOVERAGE_FILE := tests/coverage.out
GOCOVERAGE_REPORT := tests/coverage-report
GOTEST := OB_CONFIGSERVER_CONFIG_PATH=$(PWD) $(GO) test -tags test -covermode=count -coverprofile=$(GOCOVERAGE_FILE) -p $(PROCESSOR)
GO_RACE_FLAG =-race
LDFLAGS += -X "github.com/oceanbase/configserver/config.Version=${VERSION}"
LDFLAGS += -X "github.com/oceanbase/configserver/config.BuildTimestamp=$(shell date -u '+%Y-%m-%d %H:%M:%S')"
LDFLAGS += -X "github.com/oceanbase/configserver/config.GitBranch=$(shell git rev-parse --abbrev-ref HEAD)"
LDFLAGS += -X "github.com/oceanbase/configserver/config.GitHash=$(shell git rev-parse HEAD)"
LDFLAGS_DEBUG = -X "github.com/oceanbase/configserver/config.Mode=debug"
LDFLAGS_RELEASE = -X "github.com/oceanbase/configserver/config.Mode=release"
OB_CONFIGSERVER_LDFLAGS = $(LDFLAGS) -X "github.com/oceanbase/configserver/config.CurProcess=ob-configserver"
GOFILES ?= $(shell git ls-files '*.go')
GOTEST_PACKAGES = $(shell go list ./... | grep -v -f tests/excludes.txt)
UNFMT_FILES ?= $(shell gofmt -l -s $(filter-out , $(GOFILES)))
# ob-configserver
## What is ob-configserver
Ob-configserver is a web application provides oceanbase metadata storage and query.
## How to build
To build ob-configserver requires go 1.16 or above
### build binary
You can build ob-configserver using the commands list below
```bash
# build debug version
make build
# build release version
make build-release
```
You will get the compiled binary file in folder bin
### build rpm
You can build a rpm package using the following command
```
cd {project_home}/rpm
bash ob-configserver-build.sh {project_home} ob-configserver 1
```
## How to run ob-configserver
### run binary directly
* copy the config.yaml file from etc/config.yaml and modify it to match the real environment
* start ob-configserver with the following command
```bash
bin/ob-configserver -c path_to_config_file
```
### install rpm package
* install rpm package
```bash
rpm -ivh ob-configserver-xxx-x.el7.rpm
```
after installation, the directory looks like this
```bash
.
├── bin
│   └── ob-configserver
├── conf
│   └── config.yaml
├── log
└── run
```
* modify config file
* start ob-configserver
```bash
bin/ob-configserver -c conf/config.yaml
```
## How to use ob-configserver
### config oceanbase to use ob-configserver
* config ob-configserver when observer startup
```bash
add obconfig_url='http://{vip_address}:{vip_port}/services?Action=ObRootServiceInfo&ObCluster={ob_cluster_name}' in start command, specify with -o
```
* config ob-configserver when observer already starts using sql
```sql
# run the following sql using root user in tenant sys
alter system set obconfig_url = 'http://{vip_address}:{vip_port}/services?Action=ObRootServiceInfo&ObCluster={ob_cluster_name}'
```
### config obproxy to use ob-configserver
* config ob-configserver when obproxy startup
```bash
add obproxy_config_server_url='http://{vip_address}:{vip_port}/services?Action=GetObProxyConfig' in start command specify with -o
```
* config ob-configserver when obproxy already starts using sql
```sql
# run the following sql using root@proxysys
alter proxyconfig set obproxy_config_server_url='http://{vip_address}:{vip_port}/services?Action=GetObProxyConfig'
```
## API reference
[api reference](doc/api_reference.md)
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package main
import (
"os"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/oceanbase/configserver/config"
"github.com/oceanbase/configserver/logger"
"github.com/oceanbase/configserver/server"
)
var (
configserverCommand = &cobra.Command{
Use: "configserver",
Short: "configserver is used to store and query ob rs_list",
Long: "configserver is used to store and query ob rs_list, used by observer, obproxy and other tools",
Run: func(cmd *cobra.Command, args []string) {
err := runConfigServer()
if err != nil {
log.WithField("args:", args).Errorf("start configserver failed: %v", err)
}
},
}
)
func init() {
configserverCommand.PersistentFlags().StringP("config", "c", "etc/config.yaml", "config file")
_ = viper.BindPFlag("config", configserverCommand.PersistentFlags().Lookup("config"))
}
func main() {
if err := configserverCommand.Execute(); err != nil {
log.WithField("args", os.Args).Errorf("configserver execute failed %v", err)
}
}
func runConfigServer() error {
configFilePath := viper.GetString("config")
configServerConfig, err := config.ParseConfigServerConfig(configFilePath)
if err != nil {
return errors.Wrap(err, "read and parse configserver config")
}
// init logger
logger.InitLogger(logger.LoggerConfig{
Level: configServerConfig.Log.Level,
Filename: configServerConfig.Log.Filename,
MaxSize: configServerConfig.Log.MaxSize,
MaxAge: configServerConfig.Log.MaxAge,
MaxBackups: configServerConfig.Log.MaxBackups,
LocalTime: configServerConfig.Log.LocalTime,
Compress: configServerConfig.Log.Compress,
})
// init config server
configServer := server.NewConfigServer(configServerConfig)
err = configServer.Run()
if err != nil {
return errors.Wrap(err, "start config server")
}
return nil
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package config
var (
CurProcess string
Version string
Mode string
)
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package config
import (
"bytes"
"io/ioutil"
"os"
"gopkg.in/yaml.v3"
)
type ConfigServerConfig struct {
Log *LogConfig `yaml:"log"`
Server *ServerConfig `yaml:"server"`
Storage *StorageConfig `yaml:"storage"`
Vip *VipConfig `yaml:"vip"`
}
func ParseConfigServerConfig(configFilePath string) (*ConfigServerConfig, error) {
_, err := os.Stat(configFilePath)
if err != nil {
return nil, err
}
content, err := ioutil.ReadFile(configFilePath)
if err != nil {
return nil, err
}
config := new(ConfigServerConfig)
err = yaml.NewDecoder(bytes.NewReader(content)).Decode(config)
if err != nil {
return nil, err
}
return config, nil
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package config
type LogConfig struct {
Level string `yaml:"level"`
Filename string `yaml:"filename"`
MaxSize int `yaml:"maxsize"`
MaxAge int `yaml:"maxage"`
MaxBackups int `yaml:"maxbackups"`
LocalTime bool `yaml:"localtime"`
Compress bool `yaml:"compress"`
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package config
type ServerConfig struct {
Address string `yaml:"address"`
RunDir string `yaml:"run_dir"`
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package config
type StorageConfig struct {
DatabaseType string `yaml:"database_type"`
ConnectionUrl string `yaml:"connection_url"`
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package config
type VipConfig struct {
Address string `yaml:"address"`
Port int `yaml:"port"`
}
# ob-configserver api refenence
For compatibility consideration, ob-configserver uses parameter `Action` to distinguish different type of requests
## Register OceanBase rootservice list
- request url: http://{vip_address}:{vip_port}/services
- request method: POST
- request parameters:
| name | type | required | typical value | description |
| --- | --- | --- | --- | --- |
| Action | String | Yes | ObRootServiceInfo | |
| ObCluster | String | No | obcluster | ob cluster name |
| ObClusterId | int64 | No | 1 | ob cluster id |
| ObRegion | String | No | obcluster | ob cluster name, old format |
| ObRegionId | int64 | No | 1 | ob cluster id, old format |
| version | int | No | 1 | version supports 1 or 2, 2 means with standby ob cluster support |
request body:
```json
{
"ObClusterId": 1,
"ObRegionId": 1,
"ObCluster": "obcluster",
"ObRegion": "obcluster",
"ReadonlyRsList": [],
"RsList": [{
"address": "1.1.1.1:2882",
"role": "LEADER",
"sql_port": 2881
}],
"Type": "PRIMARY",
"timestamp": 1652419587417171
}
```
- response example:
```json
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": "successful",
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
```
## Query Oceanbase rootservice list
- request url: http://{vip_address}:{vip_port}/services
- request method: GET
- request parameters:
| name | type | required | typical value | description |
| --- | --- | --- | --- | --- |
| Action | String | Yes | ObRootServiceInfo | |
| ObCluster | String | No | obcluster | ob cluster name |
| ObClusterId | int64 | No | 1 | ob cluster id |
| ObRegion | String | No | obcluster | ob cluster name, old format |
| ObRegionId | int64 | No | 1 | ob cluster id, old format |
| version | int | No | 1 | version supports 1 or 2, 2 means with standby ob cluster support |
- response example:
```json
# return one item, when version=1 or version=2 and ObClusterId specified
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": {
"ObClusterId": 1,
"ObRegionId": 1,
"ObCluster": "obcluster",
"ObRegion": "obcluster",
"ReadonlyRsList": [],
"RsList": [{
"address": "1.1.1.1:2882",
"role": "LEADER",
"sql_port": 2881
}],
"Type": "PRIMARY",
"timestamp": 1652419587417171
},
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
# return a list when version=2 and ObClusterId not specified
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": [{
"ObClusterId": 1,
"ObRegionId": 1,
"ObCluster": "obcluster",
"ObRegion": "obcluster",
"ReadonlyRsList": [],
"RsList": [{
"address": "1.1.1.1:2882",
"role": "LEADER",
"sql_port": 2881
}],
"Type": "PRIMARY",
"timestamp": 1652419587417171
}, {
"ObClusterId": 2,
"ObRegionId": 2,
"ObCluster": "obcluster",
"ObRegion": "obcluster",
"ReadonlyRsList": [],
"RsList": [{
"address": "2.2.2.2:2882",
"role": "LEADER",
"sql_port": 2881
}],
"Type": "STANDBY",
"timestamp": 1652436572067984
}],
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
```
## Delete OceanBase rootservice info
- request url: http://{vip_address}:{vip_port}/services
- request method: DELETE
- request parameters:
| name | type | required | typical value | description |
| --- | --- | --- | --- | --- |
| Action | String | Yes | ObRootServiceInfo | |
| ObCluster | String | No | obcluster | ob cluster name |
| ObClusterId | int64 | No | 1 | ob cluster id |
| ObRegion | String | No | obcluster | ob cluster name, old format |
| ObRegionId | int64 | No | 1 | ob cluster id, old format |
| version | int | No | 1 | only version=2 is supported, and don't forget to specify ObClusterId |
- response example:
```json
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": "successful",
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
```
## Query rootservice info of all OceanBase clusters
- request url: http://{vip_address}:{vip_port}/services
- request method: GET/POST
- request parameters:
| name | type | required | typical value | description |
| --- | --- | --- | --- | --- |
| Action | String | Yes | GetObProxyConfig | |
| VersionOnly | Boolean | No | false | only return version |
- response example:
```json
# return all info
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": {
"ObProxyBinUrl": "http://1.1.1.1:8080/client?Action=GetObProxy",
"ObProxyDatabaseInfo": {
"DataBase": "***",
"MetaDataBase": "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&User_ID=alibaba&UID=admin&ObRegion=obdv1",
"Password": "***",
"User": "***"
},
"ObRootServiceInfoUrlList": [{
"ObRegion": "obcluster",
"ObRootServiceInfoUrl": "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=obcluster"
}],
"Version": "07c5563d293278097dc84e6b64ef6341"
},
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
# return version only
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": {
"Version": "07c5563d293278097dc84e6b64ef6341"
},
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
```
## Query rootservice info of all OceanBase clusters in template format
- request url: http://{vip_address}:{vip_port}/services
- request method: GET/POST
- request parameters:
| name | type | required | typical value | description |
| --- | --- | --- | --- | --- |
| Action | String | Yes | GetObRootServiceInfoUrlTemplate | |
| VersionOnly | Boolean | No | false | only return version |
- response example:
```json
# return all info
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": {
"ObProxyBinUrl": "http://1.1.1.1:8080/client?Action=GetObProxy",
"ObProxyDatabaseInfo": {
"DataBase": "***",
"MetaDataBase": "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&User_ID=alibaba&UID=admin&ObRegion=obdv1",
"Password": "***",
"User": "***"
},
"Version": "b34e6381994003c5d758890ededb82a4",
"ObClusterList": ["obcluster"],
"ObRootServiceInfoUrlTemplate": "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObRegion=${ObRegion}",
"ObRootServiceInfoUrlTemplateV2": "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&version=2&ObCluster=${ObCluster}&ObClusterId=${OBClusterId}"
},
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
# versiononly
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": {
"Version": "b34e6381994003c5d758890ededb82a4"
},
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
```
## Query idc and region info (empty implementation, just for compatibility)
- request url: http://{vip_address}:{vip_port}/services
- request method: GET/POST
- request parameters:
| name | type | required | typical value | description |
| --- | --- | --- | --- | --- |
| Action | String | Yes | ObIDCRegionInfo | |
| ObCluster | String | No | obcluster | ob cluster name |
| ObClusterId | int64 | No | 1 | ob cluster id |
| ObRegion | String | No | obcluster | ob cluster name, old format |
| ObRegionId | int64 | No | 1 | ob cluster id, old format |
| version | int | No | 1 | version supports 1 or 2, 2 means with standby ob cluster support |
- response example:
```json
# return single item when version=1 or version=2 and ObClusterId specified
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": {
"ObRegion": "obcluster",
"ObRegionId": 2,
"IDCList": [],
"ReadonlyRsList": ""
},
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
# return a list when version=2 and ObClusterId not specified
{
"Code": 200,
"Message": "successful",
"Success": true,
"Data": [{
"ObRegion": "obcluster",
"ObRegionId": 1,
"IDCList": [],
"ReadonlyRsList": ""
}, {
"ObRegion": "obcluster",
"ObRegionId": 2,
"IDCList": [],
"ReadonlyRsList": ""
}],
"Trace": "xxxx",
"Server": "1.1.1.1",
"Cost": 1
}
```
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"log"
"github.com/oceanbase/configserver/ent/migrate"
"github.com/oceanbase/configserver/ent/obcluster"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
)
// Client is the client that holds all ent builders.
type Client struct {
config
// Schema is the client for creating, migrating and dropping schema.
Schema *migrate.Schema
// ObCluster is the client for interacting with the ObCluster builders.
ObCluster *ObClusterClient
}
// NewClient creates a new client configured with the given options.
func NewClient(opts ...Option) *Client {
cfg := config{log: log.Println, hooks: &hooks{}}
cfg.options(opts...)
client := &Client{config: cfg}
client.init()
return client
}
func (c *Client) init() {
c.Schema = migrate.NewSchema(c.driver)
c.ObCluster = NewObClusterClient(c.config)
}
// Open opens a database/sql.DB specified by the driver name and
// the data source name, and returns a new client attached to it.
// Optional parameters can be added for configuring the client.
func Open(driverName, dataSourceName string, options ...Option) (*Client, error) {
switch driverName {
case dialect.MySQL, dialect.Postgres, dialect.SQLite:
drv, err := sql.Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
return NewClient(append(options, Driver(drv))...), nil
default:
return nil, fmt.Errorf("unsupported driver: %q", driverName)
}
}
// Tx returns a new transactional client. The provided context
// is used until the transaction is committed or rolled back.
func (c *Client) Tx(ctx context.Context) (*Tx, error) {
if _, ok := c.driver.(*txDriver); ok {
return nil, fmt.Errorf("ent: cannot start a transaction within a transaction")
}
tx, err := newTx(ctx, c.driver)
if err != nil {
return nil, fmt.Errorf("ent: starting a transaction: %w", err)
}
cfg := c.config
cfg.driver = tx
return &Tx{
ctx: ctx,
config: cfg,
ObCluster: NewObClusterClient(cfg),
}, nil
}
// BeginTx returns a transactional client with specified options.
func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
if _, ok := c.driver.(*txDriver); ok {
return nil, fmt.Errorf("ent: cannot start a transaction within a transaction")
}
tx, err := c.driver.(interface {
BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error)
}).BeginTx(ctx, opts)
if err != nil {
return nil, fmt.Errorf("ent: starting a transaction: %w", err)
}
cfg := c.config
cfg.driver = &txDriver{tx: tx, drv: c.driver}
return &Tx{
ctx: ctx,
config: cfg,
ObCluster: NewObClusterClient(cfg),
}, nil
}
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
//
// client.Debug().
// ObCluster.
// Query().
// Count(ctx)
//
func (c *Client) Debug() *Client {
if c.debug {
return c
}
cfg := c.config
cfg.driver = dialect.Debug(c.driver, c.log)
client := &Client{config: cfg}
client.init()
return client
}
// Close closes the database connection and prevents new queries from starting.
func (c *Client) Close() error {
return c.driver.Close()
}
// Use adds the mutation hooks to all the entity clients.
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
c.ObCluster.Use(hooks...)
}
// ObClusterClient is a client for the ObCluster schema.
type ObClusterClient struct {
config
}
// NewObClusterClient returns a client for the ObCluster from the given config.
func NewObClusterClient(c config) *ObClusterClient {
return &ObClusterClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `obcluster.Hooks(f(g(h())))`.
func (c *ObClusterClient) Use(hooks ...Hook) {
c.hooks.ObCluster = append(c.hooks.ObCluster, hooks...)
}
// Create returns a create builder for ObCluster.
func (c *ObClusterClient) Create() *ObClusterCreate {
mutation := newObClusterMutation(c.config, OpCreate)
return &ObClusterCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of ObCluster entities.
func (c *ObClusterClient) CreateBulk(builders ...*ObClusterCreate) *ObClusterCreateBulk {
return &ObClusterCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for ObCluster.
func (c *ObClusterClient) Update() *ObClusterUpdate {
mutation := newObClusterMutation(c.config, OpUpdate)
return &ObClusterUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *ObClusterClient) UpdateOne(oc *ObCluster) *ObClusterUpdateOne {
mutation := newObClusterMutation(c.config, OpUpdateOne, withObCluster(oc))
return &ObClusterUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *ObClusterClient) UpdateOneID(id int) *ObClusterUpdateOne {
mutation := newObClusterMutation(c.config, OpUpdateOne, withObClusterID(id))
return &ObClusterUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for ObCluster.
func (c *ObClusterClient) Delete() *ObClusterDelete {
mutation := newObClusterMutation(c.config, OpDelete)
return &ObClusterDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a delete builder for the given entity.
func (c *ObClusterClient) DeleteOne(oc *ObCluster) *ObClusterDeleteOne {
return c.DeleteOneID(oc.ID)
}
// DeleteOneID returns a delete builder for the given id.
func (c *ObClusterClient) DeleteOneID(id int) *ObClusterDeleteOne {
builder := c.Delete().Where(obcluster.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &ObClusterDeleteOne{builder}
}
// Query returns a query builder for ObCluster.
func (c *ObClusterClient) Query() *ObClusterQuery {
return &ObClusterQuery{
config: c.config,
}
}
// Get returns a ObCluster entity by its id.
func (c *ObClusterClient) Get(ctx context.Context, id int) (*ObCluster, error) {
return c.Query().Where(obcluster.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *ObClusterClient) GetX(ctx context.Context, id int) *ObCluster {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *ObClusterClient) Hooks() []Hook {
return c.hooks.ObCluster
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"entgo.io/ent"
"entgo.io/ent/dialect"
)
// Option function to configure the client.
type Option func(*config)
// Config is the configuration for the client and its builder.
type config struct {
// driver used for executing database requests.
driver dialect.Driver
// debug enable a debug logging.
debug bool
// log used for logging on debug mode.
log func(...interface{})
// hooks to execute on mutations.
hooks *hooks
}
// hooks per client, for fast access.
type hooks struct {
ObCluster []ent.Hook
}
// Options applies the options on the config object.
func (c *config) options(opts ...Option) {
for _, opt := range opts {
opt(c)
}
if c.debug {
c.driver = dialect.Debug(c.driver, c.log)
}
}
// Debug enables debug logging on the ent.Driver.
func Debug() Option {
return func(c *config) {
c.debug = true
}
}
// Log sets the logging function for debug mode.
func Log(fn func(...interface{})) Option {
return func(c *config) {
c.log = fn
}
}
// Driver configures the client driver.
func Driver(driver dialect.Driver) Option {
return func(c *config) {
c.driver = driver
}
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
)
type clientCtxKey struct{}
// FromContext returns a Client stored inside a context, or nil if there isn't one.
func FromContext(ctx context.Context) *Client {
c, _ := ctx.Value(clientCtxKey{}).(*Client)
return c
}
// NewContext returns a new context with the given Client attached.
func NewContext(parent context.Context, c *Client) context.Context {
return context.WithValue(parent, clientCtxKey{}, c)
}
type txCtxKey struct{}
// TxFromContext returns a Tx stored inside a context, or nil if there isn't one.
func TxFromContext(ctx context.Context) *Tx {
tx, _ := ctx.Value(txCtxKey{}).(*Tx)
return tx
}
// NewTxContext returns a new context with the given Tx attached.
func NewTxContext(parent context.Context, tx *Tx) context.Context {
return context.WithValue(parent, txCtxKey{}, tx)
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"errors"
"fmt"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/oceanbase/configserver/ent/obcluster"
)
// ent aliases to avoid import conflicts in user's code.
type (
Op = ent.Op
Hook = ent.Hook
Value = ent.Value
Query = ent.Query
Policy = ent.Policy
Mutator = ent.Mutator
Mutation = ent.Mutation
MutateFunc = ent.MutateFunc
)
// OrderFunc applies an ordering on the sql selector.
type OrderFunc func(*sql.Selector)
// columnChecker returns a function indicates if the column exists in the given column.
func columnChecker(table string) func(string) error {
checks := map[string]func(string) bool{
obcluster.Table: obcluster.ValidColumn,
}
check, ok := checks[table]
if !ok {
return func(string) error {
return fmt.Errorf("unknown table %q", table)
}
}
return func(column string) error {
if !check(column) {
return fmt.Errorf("unknown column %q for table %q", column, table)
}
return nil
}
}
// Asc applies the given fields in ASC order.
func Asc(fields ...string) OrderFunc {
return func(s *sql.Selector) {
check := columnChecker(s.TableName())
for _, f := range fields {
if err := check(f); err != nil {
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
}
s.OrderBy(sql.Asc(s.C(f)))
}
}
}
// Desc applies the given fields in DESC order.
func Desc(fields ...string) OrderFunc {
return func(s *sql.Selector) {
check := columnChecker(s.TableName())
for _, f := range fields {
if err := check(f); err != nil {
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
}
s.OrderBy(sql.Desc(s.C(f)))
}
}
}
// AggregateFunc applies an aggregation step on the group-by traversal/selector.
type AggregateFunc func(*sql.Selector) string
// As is a pseudo aggregation function for renaming another other functions with custom names. For example:
//
// GroupBy(field1, field2).
// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")).
// Scan(ctx, &v)
//
func As(fn AggregateFunc, end string) AggregateFunc {
return func(s *sql.Selector) string {
return sql.As(fn(s), end)
}
}
// Count applies the "count" aggregation function on each group.
func Count() AggregateFunc {
return func(s *sql.Selector) string {
return sql.Count("*")
}
}
// Max applies the "max" aggregation function on the given field of each group.
func Max(field string) AggregateFunc {
return func(s *sql.Selector) string {
check := columnChecker(s.TableName())
if err := check(field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Max(s.C(field))
}
}
// Mean applies the "mean" aggregation function on the given field of each group.
func Mean(field string) AggregateFunc {
return func(s *sql.Selector) string {
check := columnChecker(s.TableName())
if err := check(field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Avg(s.C(field))
}
}
// Min applies the "min" aggregation function on the given field of each group.
func Min(field string) AggregateFunc {
return func(s *sql.Selector) string {
check := columnChecker(s.TableName())
if err := check(field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Min(s.C(field))
}
}
// Sum applies the "sum" aggregation function on the given field of each group.
func Sum(field string) AggregateFunc {
return func(s *sql.Selector) string {
check := columnChecker(s.TableName())
if err := check(field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Sum(s.C(field))
}
}
// ValidationError returns when validating a field or edge fails.
type ValidationError struct {
Name string // Field or edge name.
err error
}
// Error implements the error interface.
func (e *ValidationError) Error() string {
return e.err.Error()
}
// Unwrap implements the errors.Wrapper interface.
func (e *ValidationError) Unwrap() error {
return e.err
}
// IsValidationError returns a boolean indicating whether the error is a validation error.
func IsValidationError(err error) bool {
if err == nil {
return false
}
var e *ValidationError
return errors.As(err, &e)
}
// NotFoundError returns when trying to fetch a specific entity and it was not found in the database.
type NotFoundError struct {
label string
}
// Error implements the error interface.
func (e *NotFoundError) Error() string {
return "ent: " + e.label + " not found"
}
// IsNotFound returns a boolean indicating whether the error is a not found error.
func IsNotFound(err error) bool {
if err == nil {
return false
}
var e *NotFoundError
return errors.As(err, &e)
}
// MaskNotFound masks not found error.
func MaskNotFound(err error) error {
if IsNotFound(err) {
return nil
}
return err
}
// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database.
type NotSingularError struct {
label string
}
// Error implements the error interface.
func (e *NotSingularError) Error() string {
return "ent: " + e.label + " not singular"
}
// IsNotSingular returns a boolean indicating whether the error is a not singular error.
func IsNotSingular(err error) bool {
if err == nil {
return false
}
var e *NotSingularError
return errors.As(err, &e)
}
// NotLoadedError returns when trying to get a node that was not loaded by the query.
type NotLoadedError struct {
edge string
}
// Error implements the error interface.
func (e *NotLoadedError) Error() string {
return "ent: " + e.edge + " edge was not loaded"
}
// IsNotLoaded returns a boolean indicating whether the error is a not loaded error.
func IsNotLoaded(err error) bool {
if err == nil {
return false
}
var e *NotLoadedError
return errors.As(err, &e)
}
// ConstraintError returns when trying to create/update one or more entities and
// one or more of their constraints failed. For example, violation of edge or
// field uniqueness.
type ConstraintError struct {
msg string
wrap error
}
// Error implements the error interface.
func (e ConstraintError) Error() string {
return "ent: constraint failed: " + e.msg
}
// Unwrap implements the errors.Wrapper interface.
func (e *ConstraintError) Unwrap() error {
return e.wrap
}
// IsConstraintError returns a boolean indicating whether the error is a constraint failure.
func IsConstraintError(err error) bool {
if err == nil {
return false
}
var e *ConstraintError
return errors.As(err, &e)
}
// Code generated by entc, DO NOT EDIT.
package enttest
import (
"context"
"github.com/oceanbase/configserver/ent"
// required by schema hooks.
_ "github.com/oceanbase/configserver/ent/runtime"
"entgo.io/ent/dialect/sql/schema"
)
type (
// TestingT is the interface that is shared between
// testing.T and testing.B and used by enttest.
TestingT interface {
FailNow()
Error(...interface{})
}
// Option configures client creation.
Option func(*options)
options struct {
opts []ent.Option
migrateOpts []schema.MigrateOption
}
)
// WithOptions forwards options to client creation.
func WithOptions(opts ...ent.Option) Option {
return func(o *options) {
o.opts = append(o.opts, opts...)
}
}
// WithMigrateOptions forwards options to auto migration.
func WithMigrateOptions(opts ...schema.MigrateOption) Option {
return func(o *options) {
o.migrateOpts = append(o.migrateOpts, opts...)
}
}
func newOptions(opts []Option) *options {
o := &options{}
for _, opt := range opts {
opt(o)
}
return o
}
// Open calls ent.Open and auto-run migration.
func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client {
o := newOptions(opts)
c, err := ent.Open(driverName, dataSourceName, o.opts...)
if err != nil {
t.Error(err)
t.FailNow()
}
if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil {
t.Error(err)
t.FailNow()
}
return c
}
// NewClient calls ent.NewClient and auto-run migration.
func NewClient(t TestingT, opts ...Option) *ent.Client {
o := newOptions(opts)
c := ent.NewClient(o.opts...)
if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil {
t.Error(err)
t.FailNow()
}
return c
}
package ent
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema
// Code generated by entc, DO NOT EDIT.
package hook
import (
"context"
"fmt"
"github.com/oceanbase/configserver/ent"
)
// The ObClusterFunc type is an adapter to allow the use of ordinary
// function as ObCluster mutator.
type ObClusterFunc func(context.Context, *ent.ObClusterMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f ObClusterFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
mv, ok := m.(*ent.ObClusterMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ObClusterMutation", m)
}
return f(ctx, mv)
}
// Condition is a hook condition function.
type Condition func(context.Context, ent.Mutation) bool
// And groups conditions with the AND operator.
func And(first, second Condition, rest ...Condition) Condition {
return func(ctx context.Context, m ent.Mutation) bool {
if !first(ctx, m) || !second(ctx, m) {
return false
}
for _, cond := range rest {
if !cond(ctx, m) {
return false
}
}
return true
}
}
// Or groups conditions with the OR operator.
func Or(first, second Condition, rest ...Condition) Condition {
return func(ctx context.Context, m ent.Mutation) bool {
if first(ctx, m) || second(ctx, m) {
return true
}
for _, cond := range rest {
if cond(ctx, m) {
return true
}
}
return false
}
}
// Not negates a given condition.
func Not(cond Condition) Condition {
return func(ctx context.Context, m ent.Mutation) bool {
return !cond(ctx, m)
}
}
// HasOp is a condition testing mutation operation.
func HasOp(op ent.Op) Condition {
return func(_ context.Context, m ent.Mutation) bool {
return m.Op().Is(op)
}
}
// HasAddedFields is a condition validating `.AddedField` on fields.
func HasAddedFields(field string, fields ...string) Condition {
return func(_ context.Context, m ent.Mutation) bool {
if _, exists := m.AddedField(field); !exists {
return false
}
for _, field := range fields {
if _, exists := m.AddedField(field); !exists {
return false
}
}
return true
}
}
// HasClearedFields is a condition validating `.FieldCleared` on fields.
func HasClearedFields(field string, fields ...string) Condition {
return func(_ context.Context, m ent.Mutation) bool {
if exists := m.FieldCleared(field); !exists {
return false
}
for _, field := range fields {
if exists := m.FieldCleared(field); !exists {
return false
}
}
return true
}
}
// HasFields is a condition validating `.Field` on fields.
func HasFields(field string, fields ...string) Condition {
return func(_ context.Context, m ent.Mutation) bool {
if _, exists := m.Field(field); !exists {
return false
}
for _, field := range fields {
if _, exists := m.Field(field); !exists {
return false
}
}
return true
}
}
// If executes the given hook under condition.
//
// hook.If(ComputeAverage, And(HasFields(...), HasAddedFields(...)))
//
func If(hk ent.Hook, cond Condition) ent.Hook {
return func(next ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if cond(ctx, m) {
return hk(next).Mutate(ctx, m)
}
return next.Mutate(ctx, m)
})
}
}
// On executes the given hook only for the given operation.
//
// hook.On(Log, ent.Delete|ent.Create)
//
func On(hk ent.Hook, op ent.Op) ent.Hook {
return If(hk, HasOp(op))
}
// Unless skips the given hook only for the given operation.
//
// hook.Unless(Log, ent.Update|ent.UpdateOne)
//
func Unless(hk ent.Hook, op ent.Op) ent.Hook {
return If(hk, Not(HasOp(op)))
}
// FixedError is a hook returning a fixed error.
func FixedError(err error) ent.Hook {
return func(ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(context.Context, ent.Mutation) (ent.Value, error) {
return nil, err
})
}
}
// Reject returns a hook that rejects all operations that match op.
//
// func (T) Hooks() []ent.Hook {
// return []ent.Hook{
// Reject(ent.Delete|ent.Update),
// }
// }
//
func Reject(op ent.Op) ent.Hook {
hk := FixedError(fmt.Errorf("%s operation is not allowed", op))
return On(hk, op)
}
// Chain acts as a list of hooks and is effectively immutable.
// Once created, it will always hold the same set of hooks in the same order.
type Chain struct {
hooks []ent.Hook
}
// NewChain creates a new chain of hooks.
func NewChain(hooks ...ent.Hook) Chain {
return Chain{append([]ent.Hook(nil), hooks...)}
}
// Hook chains the list of hooks and returns the final hook.
func (c Chain) Hook() ent.Hook {
return func(mutator ent.Mutator) ent.Mutator {
for i := len(c.hooks) - 1; i >= 0; i-- {
mutator = c.hooks[i](mutator)
}
return mutator
}
}
// Append extends a chain, adding the specified hook
// as the last ones in the mutation flow.
func (c Chain) Append(hooks ...ent.Hook) Chain {
newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks))
newHooks = append(newHooks, c.hooks...)
newHooks = append(newHooks, hooks...)
return Chain{newHooks}
}
// Extend extends a chain, adding the specified chain
// as the last ones in the mutation flow.
func (c Chain) Extend(chain Chain) Chain {
return c.Append(chain.hooks...)
}
// Code generated by entc, DO NOT EDIT.
package migrate
import (
"context"
"fmt"
"io"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql/schema"
)
var (
// WithGlobalUniqueID sets the universal ids options to the migration.
// If this option is enabled, ent migration will allocate a 1<<32 range
// for the ids of each entity (table).
// Note that this option cannot be applied on tables that already exist.
WithGlobalUniqueID = schema.WithGlobalUniqueID
// WithDropColumn sets the drop column option to the migration.
// If this option is enabled, ent migration will drop old columns
// that were used for both fields and edges. This defaults to false.
WithDropColumn = schema.WithDropColumn
// WithDropIndex sets the drop index option to the migration.
// If this option is enabled, ent migration will drop old indexes
// that were defined in the schema. This defaults to false.
// Note that unique constraints are defined using `UNIQUE INDEX`,
// and therefore, it's recommended to enable this option to get more
// flexibility in the schema changes.
WithDropIndex = schema.WithDropIndex
// WithFixture sets the foreign-key renaming option to the migration when upgrading
// ent from v0.1.0 (issue-#285). Defaults to false.
WithFixture = schema.WithFixture
// WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true.
WithForeignKeys = schema.WithForeignKeys
)
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv dialect.Driver
}
// NewSchema creates a new schema client.
func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
// Create creates all schema resources.
func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
migrate, err := schema.NewMigrate(s.drv, opts...)
if err != nil {
return fmt.Errorf("ent/migrate: %w", err)
}
return migrate.Create(ctx, Tables...)
}
// WriteTo writes the schema changes to w instead of running them against the database.
//
// if err := client.Schema.WriteTo(context.Background(), os.Stdout); err != nil {
// log.Fatal(err)
// }
//
func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error {
drv := &schema.WriteDriver{
Writer: w,
Driver: s.drv,
}
migrate, err := schema.NewMigrate(drv, opts...)
if err != nil {
return fmt.Errorf("ent/migrate: %w", err)
}
return migrate.Create(ctx, Tables...)
}
// Code generated by entc, DO NOT EDIT.
package migrate
import (
"entgo.io/ent/dialect/sql/schema"
"entgo.io/ent/schema/field"
)
var (
// ObClustersColumns holds the columns for the "ob_clusters" table.
ObClustersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "create_time", Type: field.TypeTime},
{Name: "update_time", Type: field.TypeTime},
{Name: "name", Type: field.TypeString},
{Name: "ob_cluster_id", Type: field.TypeInt64},
{Name: "type", Type: field.TypeString},
{Name: "rootservice_json", Type: field.TypeString, Size: 65536},
}
// ObClustersTable holds the schema information for the "ob_clusters" table.
ObClustersTable = &schema.Table{
Name: "ob_clusters",
Columns: ObClustersColumns,
PrimaryKey: []*schema.Column{ObClustersColumns[0]},
Indexes: []*schema.Index{
{
Name: "obcluster_update_time",
Unique: false,
Columns: []*schema.Column{ObClustersColumns[2]},
},
{
Name: "obcluster_name_ob_cluster_id",
Unique: true,
Columns: []*schema.Column{ObClustersColumns[3], ObClustersColumns[4]},
},
},
}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
ObClustersTable,
}
)
func init() {
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"sync"
"time"
"github.com/oceanbase/configserver/ent/obcluster"
"github.com/oceanbase/configserver/ent/predicate"
"entgo.io/ent"
)
const (
// Operation types.
OpCreate = ent.OpCreate
OpDelete = ent.OpDelete
OpDeleteOne = ent.OpDeleteOne
OpUpdate = ent.OpUpdate
OpUpdateOne = ent.OpUpdateOne
// Node types.
TypeObCluster = "ObCluster"
)
// ObClusterMutation represents an operation that mutates the ObCluster nodes in the graph.
type ObClusterMutation struct {
config
op Op
typ string
id *int
create_time *time.Time
update_time *time.Time
name *string
ob_cluster_id *int64
addob_cluster_id *int64
_type *string
rootservice_json *string
clearedFields map[string]struct{}
done bool
oldValue func(context.Context) (*ObCluster, error)
predicates []predicate.ObCluster
}
var _ ent.Mutation = (*ObClusterMutation)(nil)
// obclusterOption allows management of the mutation configuration using functional options.
type obclusterOption func(*ObClusterMutation)
// newObClusterMutation creates new mutation for the ObCluster entity.
func newObClusterMutation(c config, op Op, opts ...obclusterOption) *ObClusterMutation {
m := &ObClusterMutation{
config: c,
op: op,
typ: TypeObCluster,
clearedFields: make(map[string]struct{}),
}
for _, opt := range opts {
opt(m)
}
return m
}
// withObClusterID sets the ID field of the mutation.
func withObClusterID(id int) obclusterOption {
return func(m *ObClusterMutation) {
var (
err error
once sync.Once
value *ObCluster
)
m.oldValue = func(ctx context.Context) (*ObCluster, error) {
once.Do(func() {
if m.done {
err = errors.New("querying old values post mutation is not allowed")
} else {
value, err = m.Client().ObCluster.Get(ctx, id)
}
})
return value, err
}
m.id = &id
}
}
// withObCluster sets the old ObCluster of the mutation.
func withObCluster(node *ObCluster) obclusterOption {
return func(m *ObClusterMutation) {
m.oldValue = func(context.Context) (*ObCluster, error) {
return node, nil
}
m.id = &node.ID
}
}
// Client returns a new `ent.Client` from the mutation. If the mutation was
// executed in a transaction (ent.Tx), a transactional client is returned.
func (m ObClusterMutation) Client() *Client {
client := &Client{config: m.config}
client.init()
return client
}
// Tx returns an `ent.Tx` for mutations that were executed in transactions;
// it returns an error otherwise.
func (m ObClusterMutation) Tx() (*Tx, error) {
if _, ok := m.driver.(*txDriver); !ok {
return nil, errors.New("ent: mutation is not running in a transaction")
}
tx := &Tx{config: m.config}
tx.init()
return tx, nil
}
// ID returns the ID value in the mutation. Note that the ID is only available
// if it was provided to the builder or after it was returned from the database.
func (m *ObClusterMutation) ID() (id int, exists bool) {
if m.id == nil {
return
}
return *m.id, true
}
// IDs queries the database and returns the entity ids that match the mutation's predicate.
// That means, if the mutation is applied within a transaction with an isolation level such
// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
// or updated by the mutation.
func (m *ObClusterMutation) IDs(ctx context.Context) ([]int, error) {
switch {
case m.op.Is(OpUpdateOne | OpDeleteOne):
id, exists := m.ID()
if exists {
return []int{id}, nil
}
fallthrough
case m.op.Is(OpUpdate | OpDelete):
return m.Client().ObCluster.Query().Where(m.predicates...).IDs(ctx)
default:
return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
}
}
// SetCreateTime sets the "create_time" field.
func (m *ObClusterMutation) SetCreateTime(t time.Time) {
m.create_time = &t
}
// CreateTime returns the value of the "create_time" field in the mutation.
func (m *ObClusterMutation) CreateTime() (r time.Time, exists bool) {
v := m.create_time
if v == nil {
return
}
return *v, true
}
// OldCreateTime returns the old "create_time" field's value of the ObCluster entity.
// If the ObCluster object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ObClusterMutation) OldCreateTime(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCreateTime is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldCreateTime requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldCreateTime: %w", err)
}
return oldValue.CreateTime, nil
}
// ResetCreateTime resets all changes to the "create_time" field.
func (m *ObClusterMutation) ResetCreateTime() {
m.create_time = nil
}
// SetUpdateTime sets the "update_time" field.
func (m *ObClusterMutation) SetUpdateTime(t time.Time) {
m.update_time = &t
}
// UpdateTime returns the value of the "update_time" field in the mutation.
func (m *ObClusterMutation) UpdateTime() (r time.Time, exists bool) {
v := m.update_time
if v == nil {
return
}
return *v, true
}
// OldUpdateTime returns the old "update_time" field's value of the ObCluster entity.
// If the ObCluster object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ObClusterMutation) OldUpdateTime(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldUpdateTime is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldUpdateTime requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldUpdateTime: %w", err)
}
return oldValue.UpdateTime, nil
}
// ResetUpdateTime resets all changes to the "update_time" field.
func (m *ObClusterMutation) ResetUpdateTime() {
m.update_time = nil
}
// SetName sets the "name" field.
func (m *ObClusterMutation) SetName(s string) {
m.name = &s
}
// Name returns the value of the "name" field in the mutation.
func (m *ObClusterMutation) Name() (r string, exists bool) {
v := m.name
if v == nil {
return
}
return *v, true
}
// OldName returns the old "name" field's value of the ObCluster entity.
// If the ObCluster object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ObClusterMutation) OldName(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldName is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldName requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldName: %w", err)
}
return oldValue.Name, nil
}
// ResetName resets all changes to the "name" field.
func (m *ObClusterMutation) ResetName() {
m.name = nil
}
// SetObClusterID sets the "ob_cluster_id" field.
func (m *ObClusterMutation) SetObClusterID(i int64) {
m.ob_cluster_id = &i
m.addob_cluster_id = nil
}
// ObClusterID returns the value of the "ob_cluster_id" field in the mutation.
func (m *ObClusterMutation) ObClusterID() (r int64, exists bool) {
v := m.ob_cluster_id
if v == nil {
return
}
return *v, true
}
// OldObClusterID returns the old "ob_cluster_id" field's value of the ObCluster entity.
// If the ObCluster object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ObClusterMutation) OldObClusterID(ctx context.Context) (v int64, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldObClusterID is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldObClusterID requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldObClusterID: %w", err)
}
return oldValue.ObClusterID, nil
}
// AddObClusterID adds i to the "ob_cluster_id" field.
func (m *ObClusterMutation) AddObClusterID(i int64) {
if m.addob_cluster_id != nil {
*m.addob_cluster_id += i
} else {
m.addob_cluster_id = &i
}
}
// AddedObClusterID returns the value that was added to the "ob_cluster_id" field in this mutation.
func (m *ObClusterMutation) AddedObClusterID() (r int64, exists bool) {
v := m.addob_cluster_id
if v == nil {
return
}
return *v, true
}
// ResetObClusterID resets all changes to the "ob_cluster_id" field.
func (m *ObClusterMutation) ResetObClusterID() {
m.ob_cluster_id = nil
m.addob_cluster_id = nil
}
// SetType sets the "type" field.
func (m *ObClusterMutation) SetType(s string) {
m._type = &s
}
// GetType returns the value of the "type" field in the mutation.
func (m *ObClusterMutation) GetType() (r string, exists bool) {
v := m._type
if v == nil {
return
}
return *v, true
}
// OldType returns the old "type" field's value of the ObCluster entity.
// If the ObCluster object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ObClusterMutation) OldType(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldType is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldType requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldType: %w", err)
}
return oldValue.Type, nil
}
// ResetType resets all changes to the "type" field.
func (m *ObClusterMutation) ResetType() {
m._type = nil
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (m *ObClusterMutation) SetRootserviceJSON(s string) {
m.rootservice_json = &s
}
// RootserviceJSON returns the value of the "rootservice_json" field in the mutation.
func (m *ObClusterMutation) RootserviceJSON() (r string, exists bool) {
v := m.rootservice_json
if v == nil {
return
}
return *v, true
}
// OldRootserviceJSON returns the old "rootservice_json" field's value of the ObCluster entity.
// If the ObCluster object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ObClusterMutation) OldRootserviceJSON(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldRootserviceJSON is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldRootserviceJSON requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldRootserviceJSON: %w", err)
}
return oldValue.RootserviceJSON, nil
}
// ResetRootserviceJSON resets all changes to the "rootservice_json" field.
func (m *ObClusterMutation) ResetRootserviceJSON() {
m.rootservice_json = nil
}
// Where appends a list predicates to the ObClusterMutation builder.
func (m *ObClusterMutation) Where(ps ...predicate.ObCluster) {
m.predicates = append(m.predicates, ps...)
}
// Op returns the operation name.
func (m *ObClusterMutation) Op() Op {
return m.op
}
// Type returns the node type of this mutation (ObCluster).
func (m *ObClusterMutation) Type() string {
return m.typ
}
// Fields returns all fields that were changed during this mutation. Note that in
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *ObClusterMutation) Fields() []string {
fields := make([]string, 0, 6)
if m.create_time != nil {
fields = append(fields, obcluster.FieldCreateTime)
}
if m.update_time != nil {
fields = append(fields, obcluster.FieldUpdateTime)
}
if m.name != nil {
fields = append(fields, obcluster.FieldName)
}
if m.ob_cluster_id != nil {
fields = append(fields, obcluster.FieldObClusterID)
}
if m._type != nil {
fields = append(fields, obcluster.FieldType)
}
if m.rootservice_json != nil {
fields = append(fields, obcluster.FieldRootserviceJSON)
}
return fields
}
// Field returns the value of a field with the given name. The second boolean
// return value indicates that this field was not set, or was not defined in the
// schema.
func (m *ObClusterMutation) Field(name string) (ent.Value, bool) {
switch name {
case obcluster.FieldCreateTime:
return m.CreateTime()
case obcluster.FieldUpdateTime:
return m.UpdateTime()
case obcluster.FieldName:
return m.Name()
case obcluster.FieldObClusterID:
return m.ObClusterID()
case obcluster.FieldType:
return m.GetType()
case obcluster.FieldRootserviceJSON:
return m.RootserviceJSON()
}
return nil, false
}
// OldField returns the old value of the field from the database. An error is
// returned if the mutation operation is not UpdateOne, or the query to the
// database failed.
func (m *ObClusterMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
switch name {
case obcluster.FieldCreateTime:
return m.OldCreateTime(ctx)
case obcluster.FieldUpdateTime:
return m.OldUpdateTime(ctx)
case obcluster.FieldName:
return m.OldName(ctx)
case obcluster.FieldObClusterID:
return m.OldObClusterID(ctx)
case obcluster.FieldType:
return m.OldType(ctx)
case obcluster.FieldRootserviceJSON:
return m.OldRootserviceJSON(ctx)
}
return nil, fmt.Errorf("unknown ObCluster field %s", name)
}
// SetField sets the value of a field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *ObClusterMutation) SetField(name string, value ent.Value) error {
switch name {
case obcluster.FieldCreateTime:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetCreateTime(v)
return nil
case obcluster.FieldUpdateTime:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetUpdateTime(v)
return nil
case obcluster.FieldName:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetName(v)
return nil
case obcluster.FieldObClusterID:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetObClusterID(v)
return nil
case obcluster.FieldType:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetType(v)
return nil
case obcluster.FieldRootserviceJSON:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetRootserviceJSON(v)
return nil
}
return fmt.Errorf("unknown ObCluster field %s", name)
}
// AddedFields returns all numeric fields that were incremented/decremented during
// this mutation.
func (m *ObClusterMutation) AddedFields() []string {
var fields []string
if m.addob_cluster_id != nil {
fields = append(fields, obcluster.FieldObClusterID)
}
return fields
}
// AddedField returns the numeric value that was incremented/decremented on a field
// with the given name. The second boolean return value indicates that this field
// was not set, or was not defined in the schema.
func (m *ObClusterMutation) AddedField(name string) (ent.Value, bool) {
switch name {
case obcluster.FieldObClusterID:
return m.AddedObClusterID()
}
return nil, false
}
// AddField adds the value to the field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *ObClusterMutation) AddField(name string, value ent.Value) error {
switch name {
case obcluster.FieldObClusterID:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddObClusterID(v)
return nil
}
return fmt.Errorf("unknown ObCluster numeric field %s", name)
}
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *ObClusterMutation) ClearedFields() []string {
return nil
}
// FieldCleared returns a boolean indicating if a field with the given name was
// cleared in this mutation.
func (m *ObClusterMutation) FieldCleared(name string) bool {
_, ok := m.clearedFields[name]
return ok
}
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *ObClusterMutation) ClearField(name string) error {
return fmt.Errorf("unknown ObCluster nullable field %s", name)
}
// ResetField resets all changes in the mutation for the field with the given name.
// It returns an error if the field is not defined in the schema.
func (m *ObClusterMutation) ResetField(name string) error {
switch name {
case obcluster.FieldCreateTime:
m.ResetCreateTime()
return nil
case obcluster.FieldUpdateTime:
m.ResetUpdateTime()
return nil
case obcluster.FieldName:
m.ResetName()
return nil
case obcluster.FieldObClusterID:
m.ResetObClusterID()
return nil
case obcluster.FieldType:
m.ResetType()
return nil
case obcluster.FieldRootserviceJSON:
m.ResetRootserviceJSON()
return nil
}
return fmt.Errorf("unknown ObCluster field %s", name)
}
// AddedEdges returns all edge names that were set/added in this mutation.
func (m *ObClusterMutation) AddedEdges() []string {
edges := make([]string, 0, 0)
return edges
}
// AddedIDs returns all IDs (to other nodes) that were added for the given edge
// name in this mutation.
func (m *ObClusterMutation) AddedIDs(name string) []ent.Value {
return nil
}
// RemovedEdges returns all edge names that were removed in this mutation.
func (m *ObClusterMutation) RemovedEdges() []string {
edges := make([]string, 0, 0)
return edges
}
// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
// the given name in this mutation.
func (m *ObClusterMutation) RemovedIDs(name string) []ent.Value {
return nil
}
// ClearedEdges returns all edge names that were cleared in this mutation.
func (m *ObClusterMutation) ClearedEdges() []string {
edges := make([]string, 0, 0)
return edges
}
// EdgeCleared returns a boolean which indicates if the edge with the given name
// was cleared in this mutation.
func (m *ObClusterMutation) EdgeCleared(name string) bool {
return false
}
// ClearEdge clears the value of the edge with the given name. It returns an error
// if that edge is not defined in the schema.
func (m *ObClusterMutation) ClearEdge(name string) error {
return fmt.Errorf("unknown ObCluster unique edge %s", name)
}
// ResetEdge resets all changes to the edge with the given name in this mutation.
// It returns an error if the edge is not defined in the schema.
func (m *ObClusterMutation) ResetEdge(name string) error {
return fmt.Errorf("unknown ObCluster edge %s", name)
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent/dialect/sql"
"github.com/oceanbase/configserver/ent/obcluster"
)
// ObCluster is the model entity for the ObCluster schema.
type ObCluster struct {
config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
// CreateTime holds the value of the "create_time" field.
CreateTime time.Time `json:"create_time,omitempty"`
// UpdateTime holds the value of the "update_time" field.
UpdateTime time.Time `json:"update_time,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// ObClusterID holds the value of the "ob_cluster_id" field.
ObClusterID int64 `json:"ob_cluster_id,omitempty"`
// Type holds the value of the "type" field.
Type string `json:"type,omitempty"`
// RootserviceJSON holds the value of the "rootservice_json" field.
RootserviceJSON string `json:"rootservice_json,omitempty"`
}
// scanValues returns the types for scanning values from sql.Rows.
func (*ObCluster) scanValues(columns []string) ([]interface{}, error) {
values := make([]interface{}, len(columns))
for i := range columns {
switch columns[i] {
case obcluster.FieldID, obcluster.FieldObClusterID:
values[i] = new(sql.NullInt64)
case obcluster.FieldName, obcluster.FieldType, obcluster.FieldRootserviceJSON:
values[i] = new(sql.NullString)
case obcluster.FieldCreateTime, obcluster.FieldUpdateTime:
values[i] = new(sql.NullTime)
default:
return nil, fmt.Errorf("unexpected column %q for type ObCluster", columns[i])
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the ObCluster fields.
func (oc *ObCluster) assignValues(columns []string, values []interface{}) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case obcluster.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
oc.ID = int(value.Int64)
case obcluster.FieldCreateTime:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field create_time", values[i])
} else if value.Valid {
oc.CreateTime = value.Time
}
case obcluster.FieldUpdateTime:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field update_time", values[i])
} else if value.Valid {
oc.UpdateTime = value.Time
}
case obcluster.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
oc.Name = value.String
}
case obcluster.FieldObClusterID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field ob_cluster_id", values[i])
} else if value.Valid {
oc.ObClusterID = value.Int64
}
case obcluster.FieldType:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field type", values[i])
} else if value.Valid {
oc.Type = value.String
}
case obcluster.FieldRootserviceJSON:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field rootservice_json", values[i])
} else if value.Valid {
oc.RootserviceJSON = value.String
}
}
}
return nil
}
// Update returns a builder for updating this ObCluster.
// Note that you need to call ObCluster.Unwrap() before calling this method if this ObCluster
// was returned from a transaction, and the transaction was committed or rolled back.
func (oc *ObCluster) Update() *ObClusterUpdateOne {
return (&ObClusterClient{config: oc.config}).UpdateOne(oc)
}
// Unwrap unwraps the ObCluster entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (oc *ObCluster) Unwrap() *ObCluster {
tx, ok := oc.config.driver.(*txDriver)
if !ok {
panic("ent: ObCluster is not a transactional entity")
}
oc.config.driver = tx.drv
return oc
}
// String implements the fmt.Stringer.
func (oc *ObCluster) String() string {
var builder strings.Builder
builder.WriteString("ObCluster(")
builder.WriteString(fmt.Sprintf("id=%v", oc.ID))
builder.WriteString(", create_time=")
builder.WriteString(oc.CreateTime.Format(time.ANSIC))
builder.WriteString(", update_time=")
builder.WriteString(oc.UpdateTime.Format(time.ANSIC))
builder.WriteString(", name=")
builder.WriteString(oc.Name)
builder.WriteString(", ob_cluster_id=")
builder.WriteString(fmt.Sprintf("%v", oc.ObClusterID))
builder.WriteString(", type=")
builder.WriteString(oc.Type)
builder.WriteString(", rootservice_json=")
builder.WriteString(oc.RootserviceJSON)
builder.WriteByte(')')
return builder.String()
}
// ObClusters is a parsable slice of ObCluster.
type ObClusters []*ObCluster
func (oc ObClusters) config(cfg config) {
for _i := range oc {
oc[_i].config = cfg
}
}
// Code generated by entc, DO NOT EDIT.
package obcluster
import (
"time"
)
const (
// Label holds the string label denoting the obcluster type in the database.
Label = "ob_cluster"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreateTime holds the string denoting the create_time field in the database.
FieldCreateTime = "create_time"
// FieldUpdateTime holds the string denoting the update_time field in the database.
FieldUpdateTime = "update_time"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldObClusterID holds the string denoting the ob_cluster_id field in the database.
FieldObClusterID = "ob_cluster_id"
// FieldType holds the string denoting the type field in the database.
FieldType = "type"
// FieldRootserviceJSON holds the string denoting the rootservice_json field in the database.
FieldRootserviceJSON = "rootservice_json"
// Table holds the table name of the obcluster in the database.
Table = "ob_clusters"
)
// Columns holds all SQL columns for obcluster fields.
var Columns = []string{
FieldID,
FieldCreateTime,
FieldUpdateTime,
FieldName,
FieldObClusterID,
FieldType,
FieldRootserviceJSON,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// DefaultCreateTime holds the default value on creation for the "create_time" field.
DefaultCreateTime func() time.Time
// DefaultUpdateTime holds the default value on creation for the "update_time" field.
DefaultUpdateTime func() time.Time
// UpdateDefaultUpdateTime holds the default value on update for the "update_time" field.
UpdateDefaultUpdateTime func() time.Time
// ObClusterIDValidator is a validator for the "ob_cluster_id" field. It is called by the builders before save.
ObClusterIDValidator func(int64) error
)
// Code generated by entc, DO NOT EDIT.
package obcluster
import (
"time"
"entgo.io/ent/dialect/sql"
"github.com/oceanbase/configserver/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldID), id))
})
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldID), id))
})
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldID), id))
})
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
s.Where(sql.In(s.C(FieldID), v...))
})
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
s.Where(sql.NotIn(s.C(FieldID), v...))
})
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldID), id))
})
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldID), id))
})
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldID), id))
})
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldID), id))
})
}
// CreateTime applies equality check predicate on the "create_time" field. It's identical to CreateTimeEQ.
func CreateTime(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldCreateTime), v))
})
}
// UpdateTime applies equality check predicate on the "update_time" field. It's identical to UpdateTimeEQ.
func UpdateTime(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdateTime), v))
})
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldName), v))
})
}
// ObClusterID applies equality check predicate on the "ob_cluster_id" field. It's identical to ObClusterIDEQ.
func ObClusterID(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldObClusterID), v))
})
}
// Type applies equality check predicate on the "type" field. It's identical to TypeEQ.
func Type(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldType), v))
})
}
// RootserviceJSON applies equality check predicate on the "rootservice_json" field. It's identical to RootserviceJSONEQ.
func RootserviceJSON(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldRootserviceJSON), v))
})
}
// CreateTimeEQ applies the EQ predicate on the "create_time" field.
func CreateTimeEQ(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldCreateTime), v))
})
}
// CreateTimeNEQ applies the NEQ predicate on the "create_time" field.
func CreateTimeNEQ(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldCreateTime), v))
})
}
// CreateTimeIn applies the In predicate on the "create_time" field.
func CreateTimeIn(vs ...time.Time) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldCreateTime), v...))
})
}
// CreateTimeNotIn applies the NotIn predicate on the "create_time" field.
func CreateTimeNotIn(vs ...time.Time) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldCreateTime), v...))
})
}
// CreateTimeGT applies the GT predicate on the "create_time" field.
func CreateTimeGT(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldCreateTime), v))
})
}
// CreateTimeGTE applies the GTE predicate on the "create_time" field.
func CreateTimeGTE(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldCreateTime), v))
})
}
// CreateTimeLT applies the LT predicate on the "create_time" field.
func CreateTimeLT(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldCreateTime), v))
})
}
// CreateTimeLTE applies the LTE predicate on the "create_time" field.
func CreateTimeLTE(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldCreateTime), v))
})
}
// UpdateTimeEQ applies the EQ predicate on the "update_time" field.
func UpdateTimeEQ(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeNEQ applies the NEQ predicate on the "update_time" field.
func UpdateTimeNEQ(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeIn applies the In predicate on the "update_time" field.
func UpdateTimeIn(vs ...time.Time) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldUpdateTime), v...))
})
}
// UpdateTimeNotIn applies the NotIn predicate on the "update_time" field.
func UpdateTimeNotIn(vs ...time.Time) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldUpdateTime), v...))
})
}
// UpdateTimeGT applies the GT predicate on the "update_time" field.
func UpdateTimeGT(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeGTE applies the GTE predicate on the "update_time" field.
func UpdateTimeGTE(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeLT applies the LT predicate on the "update_time" field.
func UpdateTimeLT(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeLTE applies the LTE predicate on the "update_time" field.
func UpdateTimeLTE(v time.Time) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldUpdateTime), v))
})
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldName), v))
})
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldName), v))
})
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldName), v...))
})
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldName), v...))
})
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldName), v))
})
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldName), v))
})
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldName), v))
})
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldName), v))
})
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldName), v))
})
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldName), v))
})
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldName), v))
})
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldName), v))
})
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldName), v))
})
}
// ObClusterIDEQ applies the EQ predicate on the "ob_cluster_id" field.
func ObClusterIDEQ(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldObClusterID), v))
})
}
// ObClusterIDNEQ applies the NEQ predicate on the "ob_cluster_id" field.
func ObClusterIDNEQ(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldObClusterID), v))
})
}
// ObClusterIDIn applies the In predicate on the "ob_cluster_id" field.
func ObClusterIDIn(vs ...int64) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldObClusterID), v...))
})
}
// ObClusterIDNotIn applies the NotIn predicate on the "ob_cluster_id" field.
func ObClusterIDNotIn(vs ...int64) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldObClusterID), v...))
})
}
// ObClusterIDGT applies the GT predicate on the "ob_cluster_id" field.
func ObClusterIDGT(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldObClusterID), v))
})
}
// ObClusterIDGTE applies the GTE predicate on the "ob_cluster_id" field.
func ObClusterIDGTE(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldObClusterID), v))
})
}
// ObClusterIDLT applies the LT predicate on the "ob_cluster_id" field.
func ObClusterIDLT(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldObClusterID), v))
})
}
// ObClusterIDLTE applies the LTE predicate on the "ob_cluster_id" field.
func ObClusterIDLTE(v int64) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldObClusterID), v))
})
}
// TypeEQ applies the EQ predicate on the "type" field.
func TypeEQ(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldType), v))
})
}
// TypeNEQ applies the NEQ predicate on the "type" field.
func TypeNEQ(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldType), v))
})
}
// TypeIn applies the In predicate on the "type" field.
func TypeIn(vs ...string) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldType), v...))
})
}
// TypeNotIn applies the NotIn predicate on the "type" field.
func TypeNotIn(vs ...string) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldType), v...))
})
}
// TypeGT applies the GT predicate on the "type" field.
func TypeGT(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldType), v))
})
}
// TypeGTE applies the GTE predicate on the "type" field.
func TypeGTE(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldType), v))
})
}
// TypeLT applies the LT predicate on the "type" field.
func TypeLT(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldType), v))
})
}
// TypeLTE applies the LTE predicate on the "type" field.
func TypeLTE(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldType), v))
})
}
// TypeContains applies the Contains predicate on the "type" field.
func TypeContains(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldType), v))
})
}
// TypeHasPrefix applies the HasPrefix predicate on the "type" field.
func TypeHasPrefix(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldType), v))
})
}
// TypeHasSuffix applies the HasSuffix predicate on the "type" field.
func TypeHasSuffix(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldType), v))
})
}
// TypeEqualFold applies the EqualFold predicate on the "type" field.
func TypeEqualFold(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldType), v))
})
}
// TypeContainsFold applies the ContainsFold predicate on the "type" field.
func TypeContainsFold(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldType), v))
})
}
// RootserviceJSONEQ applies the EQ predicate on the "rootservice_json" field.
func RootserviceJSONEQ(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONNEQ applies the NEQ predicate on the "rootservice_json" field.
func RootserviceJSONNEQ(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONIn applies the In predicate on the "rootservice_json" field.
func RootserviceJSONIn(vs ...string) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldRootserviceJSON), v...))
})
}
// RootserviceJSONNotIn applies the NotIn predicate on the "rootservice_json" field.
func RootserviceJSONNotIn(vs ...string) predicate.ObCluster {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.ObCluster(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldRootserviceJSON), v...))
})
}
// RootserviceJSONGT applies the GT predicate on the "rootservice_json" field.
func RootserviceJSONGT(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONGTE applies the GTE predicate on the "rootservice_json" field.
func RootserviceJSONGTE(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONLT applies the LT predicate on the "rootservice_json" field.
func RootserviceJSONLT(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONLTE applies the LTE predicate on the "rootservice_json" field.
func RootserviceJSONLTE(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONContains applies the Contains predicate on the "rootservice_json" field.
func RootserviceJSONContains(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONHasPrefix applies the HasPrefix predicate on the "rootservice_json" field.
func RootserviceJSONHasPrefix(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONHasSuffix applies the HasSuffix predicate on the "rootservice_json" field.
func RootserviceJSONHasSuffix(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONEqualFold applies the EqualFold predicate on the "rootservice_json" field.
func RootserviceJSONEqualFold(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldRootserviceJSON), v))
})
}
// RootserviceJSONContainsFold applies the ContainsFold predicate on the "rootservice_json" field.
func RootserviceJSONContainsFold(v string) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldRootserviceJSON), v))
})
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.ObCluster) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s1 := s.Clone().SetP(nil)
for _, p := range predicates {
p(s1)
}
s.Where(s1.P())
})
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.ObCluster) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
s1 := s.Clone().SetP(nil)
for i, p := range predicates {
if i > 0 {
s1.Or()
}
p(s1)
}
s.Where(s1.P())
})
}
// Not applies the not operator on the given predicate.
func Not(p predicate.ObCluster) predicate.ObCluster {
return predicate.ObCluster(func(s *sql.Selector) {
p(s.Not())
})
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/oceanbase/configserver/ent/obcluster"
)
// ObClusterCreate is the builder for creating a ObCluster entity.
type ObClusterCreate struct {
config
mutation *ObClusterMutation
hooks []Hook
conflict []sql.ConflictOption
}
// SetCreateTime sets the "create_time" field.
func (occ *ObClusterCreate) SetCreateTime(t time.Time) *ObClusterCreate {
occ.mutation.SetCreateTime(t)
return occ
}
// SetNillableCreateTime sets the "create_time" field if the given value is not nil.
func (occ *ObClusterCreate) SetNillableCreateTime(t *time.Time) *ObClusterCreate {
if t != nil {
occ.SetCreateTime(*t)
}
return occ
}
// SetUpdateTime sets the "update_time" field.
func (occ *ObClusterCreate) SetUpdateTime(t time.Time) *ObClusterCreate {
occ.mutation.SetUpdateTime(t)
return occ
}
// SetNillableUpdateTime sets the "update_time" field if the given value is not nil.
func (occ *ObClusterCreate) SetNillableUpdateTime(t *time.Time) *ObClusterCreate {
if t != nil {
occ.SetUpdateTime(*t)
}
return occ
}
// SetName sets the "name" field.
func (occ *ObClusterCreate) SetName(s string) *ObClusterCreate {
occ.mutation.SetName(s)
return occ
}
// SetObClusterID sets the "ob_cluster_id" field.
func (occ *ObClusterCreate) SetObClusterID(i int64) *ObClusterCreate {
occ.mutation.SetObClusterID(i)
return occ
}
// SetType sets the "type" field.
func (occ *ObClusterCreate) SetType(s string) *ObClusterCreate {
occ.mutation.SetType(s)
return occ
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (occ *ObClusterCreate) SetRootserviceJSON(s string) *ObClusterCreate {
occ.mutation.SetRootserviceJSON(s)
return occ
}
// Mutation returns the ObClusterMutation object of the builder.
func (occ *ObClusterCreate) Mutation() *ObClusterMutation {
return occ.mutation
}
// Save creates the ObCluster in the database.
func (occ *ObClusterCreate) Save(ctx context.Context) (*ObCluster, error) {
var (
err error
node *ObCluster
)
occ.defaults()
if len(occ.hooks) == 0 {
if err = occ.check(); err != nil {
return nil, err
}
node, err = occ.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ObClusterMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err = occ.check(); err != nil {
return nil, err
}
occ.mutation = mutation
if node, err = occ.sqlSave(ctx); err != nil {
return nil, err
}
mutation.id = &node.ID
mutation.done = true
return node, err
})
for i := len(occ.hooks) - 1; i >= 0; i-- {
if occ.hooks[i] == nil {
return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
}
mut = occ.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, occ.mutation); err != nil {
return nil, err
}
}
return node, err
}
// SaveX calls Save and panics if Save returns an error.
func (occ *ObClusterCreate) SaveX(ctx context.Context) *ObCluster {
v, err := occ.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (occ *ObClusterCreate) Exec(ctx context.Context) error {
_, err := occ.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (occ *ObClusterCreate) ExecX(ctx context.Context) {
if err := occ.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (occ *ObClusterCreate) defaults() {
if _, ok := occ.mutation.CreateTime(); !ok {
v := obcluster.DefaultCreateTime()
occ.mutation.SetCreateTime(v)
}
if _, ok := occ.mutation.UpdateTime(); !ok {
v := obcluster.DefaultUpdateTime()
occ.mutation.SetUpdateTime(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (occ *ObClusterCreate) check() error {
if _, ok := occ.mutation.CreateTime(); !ok {
return &ValidationError{Name: "create_time", err: errors.New(`ent: missing required field "ObCluster.create_time"`)}
}
if _, ok := occ.mutation.UpdateTime(); !ok {
return &ValidationError{Name: "update_time", err: errors.New(`ent: missing required field "ObCluster.update_time"`)}
}
if _, ok := occ.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ObCluster.name"`)}
}
if _, ok := occ.mutation.ObClusterID(); !ok {
return &ValidationError{Name: "ob_cluster_id", err: errors.New(`ent: missing required field "ObCluster.ob_cluster_id"`)}
}
if v, ok := occ.mutation.ObClusterID(); ok {
if err := obcluster.ObClusterIDValidator(v); err != nil {
return &ValidationError{Name: "ob_cluster_id", err: fmt.Errorf(`ent: validator failed for field "ObCluster.ob_cluster_id": %w`, err)}
}
}
if _, ok := occ.mutation.GetType(); !ok {
return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "ObCluster.type"`)}
}
if _, ok := occ.mutation.RootserviceJSON(); !ok {
return &ValidationError{Name: "rootservice_json", err: errors.New(`ent: missing required field "ObCluster.rootservice_json"`)}
}
return nil
}
func (occ *ObClusterCreate) sqlSave(ctx context.Context) (*ObCluster, error) {
_node, _spec := occ.createSpec()
if err := sqlgraph.CreateNode(ctx, occ.driver, _spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{err.Error(), err}
}
return nil, err
}
id := _spec.ID.Value.(int64)
_node.ID = int(id)
return _node, nil
}
func (occ *ObClusterCreate) createSpec() (*ObCluster, *sqlgraph.CreateSpec) {
var (
_node = &ObCluster{config: occ.config}
_spec = &sqlgraph.CreateSpec{
Table: obcluster.Table,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: obcluster.FieldID,
},
}
)
_spec.OnConflict = occ.conflict
if value, ok := occ.mutation.CreateTime(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: obcluster.FieldCreateTime,
})
_node.CreateTime = value
}
if value, ok := occ.mutation.UpdateTime(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: obcluster.FieldUpdateTime,
})
_node.UpdateTime = value
}
if value, ok := occ.mutation.Name(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldName,
})
_node.Name = value
}
if value, ok := occ.mutation.ObClusterID(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeInt64,
Value: value,
Column: obcluster.FieldObClusterID,
})
_node.ObClusterID = value
}
if value, ok := occ.mutation.GetType(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldType,
})
_node.Type = value
}
if value, ok := occ.mutation.RootserviceJSON(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldRootserviceJSON,
})
_node.RootserviceJSON = value
}
return _node, _spec
}
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.ObCluster.Create().
// SetCreateTime(v).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
// sql.ResolveWithNewValues(),
// ).
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.ObClusterUpsert) {
// SetCreateTime(v+v).
// }).
// Exec(ctx)
//
func (occ *ObClusterCreate) OnConflict(opts ...sql.ConflictOption) *ObClusterUpsertOne {
occ.conflict = opts
return &ObClusterUpsertOne{
create: occ,
}
}
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.ObCluster.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
//
func (occ *ObClusterCreate) OnConflictColumns(columns ...string) *ObClusterUpsertOne {
occ.conflict = append(occ.conflict, sql.ConflictColumns(columns...))
return &ObClusterUpsertOne{
create: occ,
}
}
type (
// ObClusterUpsertOne is the builder for "upsert"-ing
// one ObCluster node.
ObClusterUpsertOne struct {
create *ObClusterCreate
}
// ObClusterUpsert is the "OnConflict" setter.
ObClusterUpsert struct {
*sql.UpdateSet
}
)
// SetCreateTime sets the "create_time" field.
func (u *ObClusterUpsert) SetCreateTime(v time.Time) *ObClusterUpsert {
u.Set(obcluster.FieldCreateTime, v)
return u
}
// UpdateCreateTime sets the "create_time" field to the value that was provided on create.
func (u *ObClusterUpsert) UpdateCreateTime() *ObClusterUpsert {
u.SetExcluded(obcluster.FieldCreateTime)
return u
}
// SetUpdateTime sets the "update_time" field.
func (u *ObClusterUpsert) SetUpdateTime(v time.Time) *ObClusterUpsert {
u.Set(obcluster.FieldUpdateTime, v)
return u
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *ObClusterUpsert) UpdateUpdateTime() *ObClusterUpsert {
u.SetExcluded(obcluster.FieldUpdateTime)
return u
}
// SetName sets the "name" field.
func (u *ObClusterUpsert) SetName(v string) *ObClusterUpsert {
u.Set(obcluster.FieldName, v)
return u
}
// UpdateName sets the "name" field to the value that was provided on create.
func (u *ObClusterUpsert) UpdateName() *ObClusterUpsert {
u.SetExcluded(obcluster.FieldName)
return u
}
// SetObClusterID sets the "ob_cluster_id" field.
func (u *ObClusterUpsert) SetObClusterID(v int64) *ObClusterUpsert {
u.Set(obcluster.FieldObClusterID, v)
return u
}
// UpdateObClusterID sets the "ob_cluster_id" field to the value that was provided on create.
func (u *ObClusterUpsert) UpdateObClusterID() *ObClusterUpsert {
u.SetExcluded(obcluster.FieldObClusterID)
return u
}
// AddObClusterID adds v to the "ob_cluster_id" field.
func (u *ObClusterUpsert) AddObClusterID(v int64) *ObClusterUpsert {
u.Add(obcluster.FieldObClusterID, v)
return u
}
// SetType sets the "type" field.
func (u *ObClusterUpsert) SetType(v string) *ObClusterUpsert {
u.Set(obcluster.FieldType, v)
return u
}
// UpdateType sets the "type" field to the value that was provided on create.
func (u *ObClusterUpsert) UpdateType() *ObClusterUpsert {
u.SetExcluded(obcluster.FieldType)
return u
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (u *ObClusterUpsert) SetRootserviceJSON(v string) *ObClusterUpsert {
u.Set(obcluster.FieldRootserviceJSON, v)
return u
}
// UpdateRootserviceJSON sets the "rootservice_json" field to the value that was provided on create.
func (u *ObClusterUpsert) UpdateRootserviceJSON() *ObClusterUpsert {
u.SetExcluded(obcluster.FieldRootserviceJSON)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
// client.ObCluster.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
//
func (u *ObClusterUpsertOne) UpdateNewValues() *ObClusterUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
return u
}
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.ObCluster.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
//
func (u *ObClusterUpsertOne) Ignore() *ObClusterUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
return u
}
// DoNothing configures the conflict_action to `DO NOTHING`.
// Supported only by SQLite and PostgreSQL.
func (u *ObClusterUpsertOne) DoNothing() *ObClusterUpsertOne {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the ObClusterCreate.OnConflict
// documentation for more info.
func (u *ObClusterUpsertOne) Update(set func(*ObClusterUpsert)) *ObClusterUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&ObClusterUpsert{UpdateSet: update})
}))
return u
}
// SetCreateTime sets the "create_time" field.
func (u *ObClusterUpsertOne) SetCreateTime(v time.Time) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.SetCreateTime(v)
})
}
// UpdateCreateTime sets the "create_time" field to the value that was provided on create.
func (u *ObClusterUpsertOne) UpdateCreateTime() *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateCreateTime()
})
}
// SetUpdateTime sets the "update_time" field.
func (u *ObClusterUpsertOne) SetUpdateTime(v time.Time) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.SetUpdateTime(v)
})
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *ObClusterUpsertOne) UpdateUpdateTime() *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateUpdateTime()
})
}
// SetName sets the "name" field.
func (u *ObClusterUpsertOne) SetName(v string) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.SetName(v)
})
}
// UpdateName sets the "name" field to the value that was provided on create.
func (u *ObClusterUpsertOne) UpdateName() *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateName()
})
}
// SetObClusterID sets the "ob_cluster_id" field.
func (u *ObClusterUpsertOne) SetObClusterID(v int64) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.SetObClusterID(v)
})
}
// AddObClusterID adds v to the "ob_cluster_id" field.
func (u *ObClusterUpsertOne) AddObClusterID(v int64) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.AddObClusterID(v)
})
}
// UpdateObClusterID sets the "ob_cluster_id" field to the value that was provided on create.
func (u *ObClusterUpsertOne) UpdateObClusterID() *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateObClusterID()
})
}
// SetType sets the "type" field.
func (u *ObClusterUpsertOne) SetType(v string) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.SetType(v)
})
}
// UpdateType sets the "type" field to the value that was provided on create.
func (u *ObClusterUpsertOne) UpdateType() *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateType()
})
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (u *ObClusterUpsertOne) SetRootserviceJSON(v string) *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.SetRootserviceJSON(v)
})
}
// UpdateRootserviceJSON sets the "rootservice_json" field to the value that was provided on create.
func (u *ObClusterUpsertOne) UpdateRootserviceJSON() *ObClusterUpsertOne {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateRootserviceJSON()
})
}
// Exec executes the query.
func (u *ObClusterUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for ObClusterCreate.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *ObClusterUpsertOne) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}
}
// Exec executes the UPSERT query and returns the inserted/updated ID.
func (u *ObClusterUpsertOne) ID(ctx context.Context) (id int, err error) {
node, err := u.create.Save(ctx)
if err != nil {
return id, err
}
return node.ID, nil
}
// IDX is like ID, but panics if an error occurs.
func (u *ObClusterUpsertOne) IDX(ctx context.Context) int {
id, err := u.ID(ctx)
if err != nil {
panic(err)
}
return id
}
// ObClusterCreateBulk is the builder for creating many ObCluster entities in bulk.
type ObClusterCreateBulk struct {
config
builders []*ObClusterCreate
conflict []sql.ConflictOption
}
// Save creates the ObCluster entities in the database.
func (occb *ObClusterCreateBulk) Save(ctx context.Context) ([]*ObCluster, error) {
specs := make([]*sqlgraph.CreateSpec, len(occb.builders))
nodes := make([]*ObCluster, len(occb.builders))
mutators := make([]Mutator, len(occb.builders))
for i := range occb.builders {
func(i int, root context.Context) {
builder := occb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ObClusterMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
nodes[i], specs[i] = builder.createSpec()
var err error
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, occb.builders[i+1].mutation)
} else {
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
spec.OnConflict = occb.conflict
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, occb.driver, spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{err.Error(), err}
}
}
}
if err != nil {
return nil, err
}
mutation.id = &nodes[i].ID
mutation.done = true
if specs[i].ID.Value != nil {
id := specs[i].ID.Value.(int64)
nodes[i].ID = int(id)
}
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, occb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (occb *ObClusterCreateBulk) SaveX(ctx context.Context) []*ObCluster {
v, err := occb.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (occb *ObClusterCreateBulk) Exec(ctx context.Context) error {
_, err := occb.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (occb *ObClusterCreateBulk) ExecX(ctx context.Context) {
if err := occb.Exec(ctx); err != nil {
panic(err)
}
}
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.ObCluster.CreateBulk(builders...).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
// sql.ResolveWithNewValues(),
// ).
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.ObClusterUpsert) {
// SetCreateTime(v+v).
// }).
// Exec(ctx)
//
func (occb *ObClusterCreateBulk) OnConflict(opts ...sql.ConflictOption) *ObClusterUpsertBulk {
occb.conflict = opts
return &ObClusterUpsertBulk{
create: occb,
}
}
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.ObCluster.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
//
func (occb *ObClusterCreateBulk) OnConflictColumns(columns ...string) *ObClusterUpsertBulk {
occb.conflict = append(occb.conflict, sql.ConflictColumns(columns...))
return &ObClusterUpsertBulk{
create: occb,
}
}
// ObClusterUpsertBulk is the builder for "upsert"-ing
// a bulk of ObCluster nodes.
type ObClusterUpsertBulk struct {
create *ObClusterCreateBulk
}
// UpdateNewValues updates the mutable fields using the new values that
// were set on create. Using this option is equivalent to using:
//
// client.ObCluster.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
//
func (u *ObClusterUpsertBulk) UpdateNewValues() *ObClusterUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
return u
}
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.ObCluster.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
//
func (u *ObClusterUpsertBulk) Ignore() *ObClusterUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
return u
}
// DoNothing configures the conflict_action to `DO NOTHING`.
// Supported only by SQLite and PostgreSQL.
func (u *ObClusterUpsertBulk) DoNothing() *ObClusterUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the ObClusterCreateBulk.OnConflict
// documentation for more info.
func (u *ObClusterUpsertBulk) Update(set func(*ObClusterUpsert)) *ObClusterUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&ObClusterUpsert{UpdateSet: update})
}))
return u
}
// SetCreateTime sets the "create_time" field.
func (u *ObClusterUpsertBulk) SetCreateTime(v time.Time) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.SetCreateTime(v)
})
}
// UpdateCreateTime sets the "create_time" field to the value that was provided on create.
func (u *ObClusterUpsertBulk) UpdateCreateTime() *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateCreateTime()
})
}
// SetUpdateTime sets the "update_time" field.
func (u *ObClusterUpsertBulk) SetUpdateTime(v time.Time) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.SetUpdateTime(v)
})
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *ObClusterUpsertBulk) UpdateUpdateTime() *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateUpdateTime()
})
}
// SetName sets the "name" field.
func (u *ObClusterUpsertBulk) SetName(v string) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.SetName(v)
})
}
// UpdateName sets the "name" field to the value that was provided on create.
func (u *ObClusterUpsertBulk) UpdateName() *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateName()
})
}
// SetObClusterID sets the "ob_cluster_id" field.
func (u *ObClusterUpsertBulk) SetObClusterID(v int64) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.SetObClusterID(v)
})
}
// AddObClusterID adds v to the "ob_cluster_id" field.
func (u *ObClusterUpsertBulk) AddObClusterID(v int64) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.AddObClusterID(v)
})
}
// UpdateObClusterID sets the "ob_cluster_id" field to the value that was provided on create.
func (u *ObClusterUpsertBulk) UpdateObClusterID() *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateObClusterID()
})
}
// SetType sets the "type" field.
func (u *ObClusterUpsertBulk) SetType(v string) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.SetType(v)
})
}
// UpdateType sets the "type" field to the value that was provided on create.
func (u *ObClusterUpsertBulk) UpdateType() *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateType()
})
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (u *ObClusterUpsertBulk) SetRootserviceJSON(v string) *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.SetRootserviceJSON(v)
})
}
// UpdateRootserviceJSON sets the "rootservice_json" field to the value that was provided on create.
func (u *ObClusterUpsertBulk) UpdateRootserviceJSON() *ObClusterUpsertBulk {
return u.Update(func(s *ObClusterUpsert) {
s.UpdateRootserviceJSON()
})
}
// Exec executes the query.
func (u *ObClusterUpsertBulk) Exec(ctx context.Context) error {
for i, b := range u.create.builders {
if len(b.conflict) != 0 {
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ObClusterCreateBulk instead", i)
}
}
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for ObClusterCreateBulk.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *ObClusterUpsertBulk) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/oceanbase/configserver/ent/obcluster"
"github.com/oceanbase/configserver/ent/predicate"
)
// ObClusterDelete is the builder for deleting a ObCluster entity.
type ObClusterDelete struct {
config
hooks []Hook
mutation *ObClusterMutation
}
// Where appends a list predicates to the ObClusterDelete builder.
func (ocd *ObClusterDelete) Where(ps ...predicate.ObCluster) *ObClusterDelete {
ocd.mutation.Where(ps...)
return ocd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (ocd *ObClusterDelete) Exec(ctx context.Context) (int, error) {
var (
err error
affected int
)
if len(ocd.hooks) == 0 {
affected, err = ocd.sqlExec(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ObClusterMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
ocd.mutation = mutation
affected, err = ocd.sqlExec(ctx)
mutation.done = true
return affected, err
})
for i := len(ocd.hooks) - 1; i >= 0; i-- {
if ocd.hooks[i] == nil {
return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
}
mut = ocd.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, ocd.mutation); err != nil {
return 0, err
}
}
return affected, err
}
// ExecX is like Exec, but panics if an error occurs.
func (ocd *ObClusterDelete) ExecX(ctx context.Context) int {
n, err := ocd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (ocd *ObClusterDelete) sqlExec(ctx context.Context) (int, error) {
_spec := &sqlgraph.DeleteSpec{
Node: &sqlgraph.NodeSpec{
Table: obcluster.Table,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: obcluster.FieldID,
},
},
}
if ps := ocd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return sqlgraph.DeleteNodes(ctx, ocd.driver, _spec)
}
// ObClusterDeleteOne is the builder for deleting a single ObCluster entity.
type ObClusterDeleteOne struct {
ocd *ObClusterDelete
}
// Exec executes the deletion query.
func (ocdo *ObClusterDeleteOne) Exec(ctx context.Context) error {
n, err := ocdo.ocd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{obcluster.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (ocdo *ObClusterDeleteOne) ExecX(ctx context.Context) {
ocdo.ocd.ExecX(ctx)
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"math"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/oceanbase/configserver/ent/obcluster"
"github.com/oceanbase/configserver/ent/predicate"
)
// ObClusterQuery is the builder for querying ObCluster entities.
type ObClusterQuery struct {
config
limit *int
offset *int
unique *bool
order []OrderFunc
fields []string
predicates []predicate.ObCluster
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the ObClusterQuery builder.
func (ocq *ObClusterQuery) Where(ps ...predicate.ObCluster) *ObClusterQuery {
ocq.predicates = append(ocq.predicates, ps...)
return ocq
}
// Limit adds a limit step to the query.
func (ocq *ObClusterQuery) Limit(limit int) *ObClusterQuery {
ocq.limit = &limit
return ocq
}
// Offset adds an offset step to the query.
func (ocq *ObClusterQuery) Offset(offset int) *ObClusterQuery {
ocq.offset = &offset
return ocq
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (ocq *ObClusterQuery) Unique(unique bool) *ObClusterQuery {
ocq.unique = &unique
return ocq
}
// Order adds an order step to the query.
func (ocq *ObClusterQuery) Order(o ...OrderFunc) *ObClusterQuery {
ocq.order = append(ocq.order, o...)
return ocq
}
// First returns the first ObCluster entity from the query.
// Returns a *NotFoundError when no ObCluster was found.
func (ocq *ObClusterQuery) First(ctx context.Context) (*ObCluster, error) {
nodes, err := ocq.Limit(1).All(ctx)
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{obcluster.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (ocq *ObClusterQuery) FirstX(ctx context.Context) *ObCluster {
node, err := ocq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first ObCluster ID from the query.
// Returns a *NotFoundError when no ObCluster ID was found.
func (ocq *ObClusterQuery) FirstID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = ocq.Limit(1).IDs(ctx); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{obcluster.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (ocq *ObClusterQuery) FirstIDX(ctx context.Context) int {
id, err := ocq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single ObCluster entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one ObCluster entity is found.
// Returns a *NotFoundError when no ObCluster entities are found.
func (ocq *ObClusterQuery) Only(ctx context.Context) (*ObCluster, error) {
nodes, err := ocq.Limit(2).All(ctx)
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{obcluster.Label}
default:
return nil, &NotSingularError{obcluster.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (ocq *ObClusterQuery) OnlyX(ctx context.Context) *ObCluster {
node, err := ocq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only ObCluster ID in the query.
// Returns a *NotSingularError when more than one ObCluster ID is found.
// Returns a *NotFoundError when no entities are found.
func (ocq *ObClusterQuery) OnlyID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = ocq.Limit(2).IDs(ctx); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = &NotSingularError{obcluster.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (ocq *ObClusterQuery) OnlyIDX(ctx context.Context) int {
id, err := ocq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of ObClusters.
func (ocq *ObClusterQuery) All(ctx context.Context) ([]*ObCluster, error) {
if err := ocq.prepareQuery(ctx); err != nil {
return nil, err
}
return ocq.sqlAll(ctx)
}
// AllX is like All, but panics if an error occurs.
func (ocq *ObClusterQuery) AllX(ctx context.Context) []*ObCluster {
nodes, err := ocq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of ObCluster IDs.
func (ocq *ObClusterQuery) IDs(ctx context.Context) ([]int, error) {
var ids []int
if err := ocq.Select(obcluster.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (ocq *ObClusterQuery) IDsX(ctx context.Context) []int {
ids, err := ocq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (ocq *ObClusterQuery) Count(ctx context.Context) (int, error) {
if err := ocq.prepareQuery(ctx); err != nil {
return 0, err
}
return ocq.sqlCount(ctx)
}
// CountX is like Count, but panics if an error occurs.
func (ocq *ObClusterQuery) CountX(ctx context.Context) int {
count, err := ocq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (ocq *ObClusterQuery) Exist(ctx context.Context) (bool, error) {
if err := ocq.prepareQuery(ctx); err != nil {
return false, err
}
return ocq.sqlExist(ctx)
}
// ExistX is like Exist, but panics if an error occurs.
func (ocq *ObClusterQuery) ExistX(ctx context.Context) bool {
exist, err := ocq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the ObClusterQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (ocq *ObClusterQuery) Clone() *ObClusterQuery {
if ocq == nil {
return nil
}
return &ObClusterQuery{
config: ocq.config,
limit: ocq.limit,
offset: ocq.offset,
order: append([]OrderFunc{}, ocq.order...),
predicates: append([]predicate.ObCluster{}, ocq.predicates...),
// clone intermediate query.
sql: ocq.sql.Clone(),
path: ocq.path,
unique: ocq.unique,
}
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// CreateTime time.Time `json:"create_time,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.ObCluster.Query().
// GroupBy(obcluster.FieldCreateTime).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
//
func (ocq *ObClusterQuery) GroupBy(field string, fields ...string) *ObClusterGroupBy {
group := &ObClusterGroupBy{config: ocq.config}
group.fields = append([]string{field}, fields...)
group.path = func(ctx context.Context) (prev *sql.Selector, err error) {
if err := ocq.prepareQuery(ctx); err != nil {
return nil, err
}
return ocq.sqlQuery(ctx), nil
}
return group
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// CreateTime time.Time `json:"create_time,omitempty"`
// }
//
// client.ObCluster.Query().
// Select(obcluster.FieldCreateTime).
// Scan(ctx, &v)
//
func (ocq *ObClusterQuery) Select(fields ...string) *ObClusterSelect {
ocq.fields = append(ocq.fields, fields...)
return &ObClusterSelect{ObClusterQuery: ocq}
}
func (ocq *ObClusterQuery) prepareQuery(ctx context.Context) error {
for _, f := range ocq.fields {
if !obcluster.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if ocq.path != nil {
prev, err := ocq.path(ctx)
if err != nil {
return err
}
ocq.sql = prev
}
return nil
}
func (ocq *ObClusterQuery) sqlAll(ctx context.Context) ([]*ObCluster, error) {
var (
nodes = []*ObCluster{}
_spec = ocq.querySpec()
)
_spec.ScanValues = func(columns []string) ([]interface{}, error) {
node := &ObCluster{config: ocq.config}
nodes = append(nodes, node)
return node.scanValues(columns)
}
_spec.Assign = func(columns []string, values []interface{}) error {
if len(nodes) == 0 {
return fmt.Errorf("ent: Assign called without calling ScanValues")
}
node := nodes[len(nodes)-1]
return node.assignValues(columns, values)
}
if err := sqlgraph.QueryNodes(ctx, ocq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
return nodes, nil
}
func (ocq *ObClusterQuery) sqlCount(ctx context.Context) (int, error) {
_spec := ocq.querySpec()
_spec.Node.Columns = ocq.fields
if len(ocq.fields) > 0 {
_spec.Unique = ocq.unique != nil && *ocq.unique
}
return sqlgraph.CountNodes(ctx, ocq.driver, _spec)
}
func (ocq *ObClusterQuery) sqlExist(ctx context.Context) (bool, error) {
n, err := ocq.sqlCount(ctx)
if err != nil {
return false, fmt.Errorf("ent: check existence: %w", err)
}
return n > 0, nil
}
func (ocq *ObClusterQuery) querySpec() *sqlgraph.QuerySpec {
_spec := &sqlgraph.QuerySpec{
Node: &sqlgraph.NodeSpec{
Table: obcluster.Table,
Columns: obcluster.Columns,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: obcluster.FieldID,
},
},
From: ocq.sql,
Unique: true,
}
if unique := ocq.unique; unique != nil {
_spec.Unique = *unique
}
if fields := ocq.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, obcluster.FieldID)
for i := range fields {
if fields[i] != obcluster.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := ocq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := ocq.limit; limit != nil {
_spec.Limit = *limit
}
if offset := ocq.offset; offset != nil {
_spec.Offset = *offset
}
if ps := ocq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (ocq *ObClusterQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(ocq.driver.Dialect())
t1 := builder.Table(obcluster.Table)
columns := ocq.fields
if len(columns) == 0 {
columns = obcluster.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if ocq.sql != nil {
selector = ocq.sql
selector.Select(selector.Columns(columns...)...)
}
if ocq.unique != nil && *ocq.unique {
selector.Distinct()
}
for _, p := range ocq.predicates {
p(selector)
}
for _, p := range ocq.order {
p(selector)
}
if offset := ocq.offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := ocq.limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ObClusterGroupBy is the group-by builder for ObCluster entities.
type ObClusterGroupBy struct {
config
fields []string
fns []AggregateFunc
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Aggregate adds the given aggregation functions to the group-by query.
func (ocgb *ObClusterGroupBy) Aggregate(fns ...AggregateFunc) *ObClusterGroupBy {
ocgb.fns = append(ocgb.fns, fns...)
return ocgb
}
// Scan applies the group-by query and scans the result into the given value.
func (ocgb *ObClusterGroupBy) Scan(ctx context.Context, v interface{}) error {
query, err := ocgb.path(ctx)
if err != nil {
return err
}
ocgb.sql = query
return ocgb.sqlScan(ctx, v)
}
// ScanX is like Scan, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) ScanX(ctx context.Context, v interface{}) {
if err := ocgb.Scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from group-by.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Strings(ctx context.Context) ([]string, error) {
if len(ocgb.fields) > 1 {
return nil, errors.New("ent: ObClusterGroupBy.Strings is not achievable when grouping more than 1 field")
}
var v []string
if err := ocgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) StringsX(ctx context.Context) []string {
v, err := ocgb.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// String returns a single string from a group-by query.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) String(ctx context.Context) (_ string, err error) {
var v []string
if v, err = ocgb.Strings(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterGroupBy.Strings returned %d results when one was expected", len(v))
}
return
}
// StringX is like String, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) StringX(ctx context.Context) string {
v, err := ocgb.String(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from group-by.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Ints(ctx context.Context) ([]int, error) {
if len(ocgb.fields) > 1 {
return nil, errors.New("ent: ObClusterGroupBy.Ints is not achievable when grouping more than 1 field")
}
var v []int
if err := ocgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) IntsX(ctx context.Context) []int {
v, err := ocgb.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Int returns a single int from a group-by query.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Int(ctx context.Context) (_ int, err error) {
var v []int
if v, err = ocgb.Ints(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterGroupBy.Ints returned %d results when one was expected", len(v))
}
return
}
// IntX is like Int, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) IntX(ctx context.Context) int {
v, err := ocgb.Int(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from group-by.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Float64s(ctx context.Context) ([]float64, error) {
if len(ocgb.fields) > 1 {
return nil, errors.New("ent: ObClusterGroupBy.Float64s is not achievable when grouping more than 1 field")
}
var v []float64
if err := ocgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) Float64sX(ctx context.Context) []float64 {
v, err := ocgb.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64 returns a single float64 from a group-by query.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Float64(ctx context.Context) (_ float64, err error) {
var v []float64
if v, err = ocgb.Float64s(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterGroupBy.Float64s returned %d results when one was expected", len(v))
}
return
}
// Float64X is like Float64, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) Float64X(ctx context.Context) float64 {
v, err := ocgb.Float64(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from group-by.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Bools(ctx context.Context) ([]bool, error) {
if len(ocgb.fields) > 1 {
return nil, errors.New("ent: ObClusterGroupBy.Bools is not achievable when grouping more than 1 field")
}
var v []bool
if err := ocgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) BoolsX(ctx context.Context) []bool {
v, err := ocgb.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
// Bool returns a single bool from a group-by query.
// It is only allowed when executing a group-by query with one field.
func (ocgb *ObClusterGroupBy) Bool(ctx context.Context) (_ bool, err error) {
var v []bool
if v, err = ocgb.Bools(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterGroupBy.Bools returned %d results when one was expected", len(v))
}
return
}
// BoolX is like Bool, but panics if an error occurs.
func (ocgb *ObClusterGroupBy) BoolX(ctx context.Context) bool {
v, err := ocgb.Bool(ctx)
if err != nil {
panic(err)
}
return v
}
func (ocgb *ObClusterGroupBy) sqlScan(ctx context.Context, v interface{}) error {
for _, f := range ocgb.fields {
if !obcluster.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)}
}
}
selector := ocgb.sqlQuery()
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ocgb.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
func (ocgb *ObClusterGroupBy) sqlQuery() *sql.Selector {
selector := ocgb.sql.Select()
aggregation := make([]string, 0, len(ocgb.fns))
for _, fn := range ocgb.fns {
aggregation = append(aggregation, fn(selector))
}
// If no columns were selected in a custom aggregation function, the default
// selection is the fields used for "group-by", and the aggregation functions.
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(ocgb.fields)+len(ocgb.fns))
for _, f := range ocgb.fields {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(ocgb.fields...)...)
}
// ObClusterSelect is the builder for selecting fields of ObCluster entities.
type ObClusterSelect struct {
*ObClusterQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
}
// Scan applies the selector query and scans the result into the given value.
func (ocs *ObClusterSelect) Scan(ctx context.Context, v interface{}) error {
if err := ocs.prepareQuery(ctx); err != nil {
return err
}
ocs.sql = ocs.ObClusterQuery.sqlQuery(ctx)
return ocs.sqlScan(ctx, v)
}
// ScanX is like Scan, but panics if an error occurs.
func (ocs *ObClusterSelect) ScanX(ctx context.Context, v interface{}) {
if err := ocs.Scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Strings(ctx context.Context) ([]string, error) {
if len(ocs.fields) > 1 {
return nil, errors.New("ent: ObClusterSelect.Strings is not achievable when selecting more than 1 field")
}
var v []string
if err := ocs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (ocs *ObClusterSelect) StringsX(ctx context.Context) []string {
v, err := ocs.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// String returns a single string from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) String(ctx context.Context) (_ string, err error) {
var v []string
if v, err = ocs.Strings(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterSelect.Strings returned %d results when one was expected", len(v))
}
return
}
// StringX is like String, but panics if an error occurs.
func (ocs *ObClusterSelect) StringX(ctx context.Context) string {
v, err := ocs.String(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Ints(ctx context.Context) ([]int, error) {
if len(ocs.fields) > 1 {
return nil, errors.New("ent: ObClusterSelect.Ints is not achievable when selecting more than 1 field")
}
var v []int
if err := ocs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (ocs *ObClusterSelect) IntsX(ctx context.Context) []int {
v, err := ocs.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Int returns a single int from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Int(ctx context.Context) (_ int, err error) {
var v []int
if v, err = ocs.Ints(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterSelect.Ints returned %d results when one was expected", len(v))
}
return
}
// IntX is like Int, but panics if an error occurs.
func (ocs *ObClusterSelect) IntX(ctx context.Context) int {
v, err := ocs.Int(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Float64s(ctx context.Context) ([]float64, error) {
if len(ocs.fields) > 1 {
return nil, errors.New("ent: ObClusterSelect.Float64s is not achievable when selecting more than 1 field")
}
var v []float64
if err := ocs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (ocs *ObClusterSelect) Float64sX(ctx context.Context) []float64 {
v, err := ocs.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64 returns a single float64 from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Float64(ctx context.Context) (_ float64, err error) {
var v []float64
if v, err = ocs.Float64s(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterSelect.Float64s returned %d results when one was expected", len(v))
}
return
}
// Float64X is like Float64, but panics if an error occurs.
func (ocs *ObClusterSelect) Float64X(ctx context.Context) float64 {
v, err := ocs.Float64(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Bools(ctx context.Context) ([]bool, error) {
if len(ocs.fields) > 1 {
return nil, errors.New("ent: ObClusterSelect.Bools is not achievable when selecting more than 1 field")
}
var v []bool
if err := ocs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (ocs *ObClusterSelect) BoolsX(ctx context.Context) []bool {
v, err := ocs.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
// Bool returns a single bool from a selector. It is only allowed when selecting one field.
func (ocs *ObClusterSelect) Bool(ctx context.Context) (_ bool, err error) {
var v []bool
if v, err = ocs.Bools(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{obcluster.Label}
default:
err = fmt.Errorf("ent: ObClusterSelect.Bools returned %d results when one was expected", len(v))
}
return
}
// BoolX is like Bool, but panics if an error occurs.
func (ocs *ObClusterSelect) BoolX(ctx context.Context) bool {
v, err := ocs.Bool(ctx)
if err != nil {
panic(err)
}
return v
}
func (ocs *ObClusterSelect) sqlScan(ctx context.Context, v interface{}) error {
rows := &sql.Rows{}
query, args := ocs.sql.Query()
if err := ocs.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/oceanbase/configserver/ent/obcluster"
"github.com/oceanbase/configserver/ent/predicate"
)
// ObClusterUpdate is the builder for updating ObCluster entities.
type ObClusterUpdate struct {
config
hooks []Hook
mutation *ObClusterMutation
}
// Where appends a list predicates to the ObClusterUpdate builder.
func (ocu *ObClusterUpdate) Where(ps ...predicate.ObCluster) *ObClusterUpdate {
ocu.mutation.Where(ps...)
return ocu
}
// SetCreateTime sets the "create_time" field.
func (ocu *ObClusterUpdate) SetCreateTime(t time.Time) *ObClusterUpdate {
ocu.mutation.SetCreateTime(t)
return ocu
}
// SetNillableCreateTime sets the "create_time" field if the given value is not nil.
func (ocu *ObClusterUpdate) SetNillableCreateTime(t *time.Time) *ObClusterUpdate {
if t != nil {
ocu.SetCreateTime(*t)
}
return ocu
}
// SetUpdateTime sets the "update_time" field.
func (ocu *ObClusterUpdate) SetUpdateTime(t time.Time) *ObClusterUpdate {
ocu.mutation.SetUpdateTime(t)
return ocu
}
// SetName sets the "name" field.
func (ocu *ObClusterUpdate) SetName(s string) *ObClusterUpdate {
ocu.mutation.SetName(s)
return ocu
}
// SetObClusterID sets the "ob_cluster_id" field.
func (ocu *ObClusterUpdate) SetObClusterID(i int64) *ObClusterUpdate {
ocu.mutation.ResetObClusterID()
ocu.mutation.SetObClusterID(i)
return ocu
}
// AddObClusterID adds i to the "ob_cluster_id" field.
func (ocu *ObClusterUpdate) AddObClusterID(i int64) *ObClusterUpdate {
ocu.mutation.AddObClusterID(i)
return ocu
}
// SetType sets the "type" field.
func (ocu *ObClusterUpdate) SetType(s string) *ObClusterUpdate {
ocu.mutation.SetType(s)
return ocu
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (ocu *ObClusterUpdate) SetRootserviceJSON(s string) *ObClusterUpdate {
ocu.mutation.SetRootserviceJSON(s)
return ocu
}
// Mutation returns the ObClusterMutation object of the builder.
func (ocu *ObClusterUpdate) Mutation() *ObClusterMutation {
return ocu.mutation
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (ocu *ObClusterUpdate) Save(ctx context.Context) (int, error) {
var (
err error
affected int
)
ocu.defaults()
if len(ocu.hooks) == 0 {
if err = ocu.check(); err != nil {
return 0, err
}
affected, err = ocu.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ObClusterMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err = ocu.check(); err != nil {
return 0, err
}
ocu.mutation = mutation
affected, err = ocu.sqlSave(ctx)
mutation.done = true
return affected, err
})
for i := len(ocu.hooks) - 1; i >= 0; i-- {
if ocu.hooks[i] == nil {
return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
}
mut = ocu.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, ocu.mutation); err != nil {
return 0, err
}
}
return affected, err
}
// SaveX is like Save, but panics if an error occurs.
func (ocu *ObClusterUpdate) SaveX(ctx context.Context) int {
affected, err := ocu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (ocu *ObClusterUpdate) Exec(ctx context.Context) error {
_, err := ocu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ocu *ObClusterUpdate) ExecX(ctx context.Context) {
if err := ocu.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (ocu *ObClusterUpdate) defaults() {
if _, ok := ocu.mutation.UpdateTime(); !ok {
v := obcluster.UpdateDefaultUpdateTime()
ocu.mutation.SetUpdateTime(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (ocu *ObClusterUpdate) check() error {
if v, ok := ocu.mutation.ObClusterID(); ok {
if err := obcluster.ObClusterIDValidator(v); err != nil {
return &ValidationError{Name: "ob_cluster_id", err: fmt.Errorf(`ent: validator failed for field "ObCluster.ob_cluster_id": %w`, err)}
}
}
return nil
}
func (ocu *ObClusterUpdate) sqlSave(ctx context.Context) (n int, err error) {
_spec := &sqlgraph.UpdateSpec{
Node: &sqlgraph.NodeSpec{
Table: obcluster.Table,
Columns: obcluster.Columns,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: obcluster.FieldID,
},
},
}
if ps := ocu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := ocu.mutation.CreateTime(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: obcluster.FieldCreateTime,
})
}
if value, ok := ocu.mutation.UpdateTime(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: obcluster.FieldUpdateTime,
})
}
if value, ok := ocu.mutation.Name(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldName,
})
}
if value, ok := ocu.mutation.ObClusterID(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeInt64,
Value: value,
Column: obcluster.FieldObClusterID,
})
}
if value, ok := ocu.mutation.AddedObClusterID(); ok {
_spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{
Type: field.TypeInt64,
Value: value,
Column: obcluster.FieldObClusterID,
})
}
if value, ok := ocu.mutation.GetType(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldType,
})
}
if value, ok := ocu.mutation.RootserviceJSON(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldRootserviceJSON,
})
}
if n, err = sqlgraph.UpdateNodes(ctx, ocu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{obcluster.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{err.Error(), err}
}
return 0, err
}
return n, nil
}
// ObClusterUpdateOne is the builder for updating a single ObCluster entity.
type ObClusterUpdateOne struct {
config
fields []string
hooks []Hook
mutation *ObClusterMutation
}
// SetCreateTime sets the "create_time" field.
func (ocuo *ObClusterUpdateOne) SetCreateTime(t time.Time) *ObClusterUpdateOne {
ocuo.mutation.SetCreateTime(t)
return ocuo
}
// SetNillableCreateTime sets the "create_time" field if the given value is not nil.
func (ocuo *ObClusterUpdateOne) SetNillableCreateTime(t *time.Time) *ObClusterUpdateOne {
if t != nil {
ocuo.SetCreateTime(*t)
}
return ocuo
}
// SetUpdateTime sets the "update_time" field.
func (ocuo *ObClusterUpdateOne) SetUpdateTime(t time.Time) *ObClusterUpdateOne {
ocuo.mutation.SetUpdateTime(t)
return ocuo
}
// SetName sets the "name" field.
func (ocuo *ObClusterUpdateOne) SetName(s string) *ObClusterUpdateOne {
ocuo.mutation.SetName(s)
return ocuo
}
// SetObClusterID sets the "ob_cluster_id" field.
func (ocuo *ObClusterUpdateOne) SetObClusterID(i int64) *ObClusterUpdateOne {
ocuo.mutation.ResetObClusterID()
ocuo.mutation.SetObClusterID(i)
return ocuo
}
// AddObClusterID adds i to the "ob_cluster_id" field.
func (ocuo *ObClusterUpdateOne) AddObClusterID(i int64) *ObClusterUpdateOne {
ocuo.mutation.AddObClusterID(i)
return ocuo
}
// SetType sets the "type" field.
func (ocuo *ObClusterUpdateOne) SetType(s string) *ObClusterUpdateOne {
ocuo.mutation.SetType(s)
return ocuo
}
// SetRootserviceJSON sets the "rootservice_json" field.
func (ocuo *ObClusterUpdateOne) SetRootserviceJSON(s string) *ObClusterUpdateOne {
ocuo.mutation.SetRootserviceJSON(s)
return ocuo
}
// Mutation returns the ObClusterMutation object of the builder.
func (ocuo *ObClusterUpdateOne) Mutation() *ObClusterMutation {
return ocuo.mutation
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (ocuo *ObClusterUpdateOne) Select(field string, fields ...string) *ObClusterUpdateOne {
ocuo.fields = append([]string{field}, fields...)
return ocuo
}
// Save executes the query and returns the updated ObCluster entity.
func (ocuo *ObClusterUpdateOne) Save(ctx context.Context) (*ObCluster, error) {
var (
err error
node *ObCluster
)
ocuo.defaults()
if len(ocuo.hooks) == 0 {
if err = ocuo.check(); err != nil {
return nil, err
}
node, err = ocuo.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ObClusterMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err = ocuo.check(); err != nil {
return nil, err
}
ocuo.mutation = mutation
node, err = ocuo.sqlSave(ctx)
mutation.done = true
return node, err
})
for i := len(ocuo.hooks) - 1; i >= 0; i-- {
if ocuo.hooks[i] == nil {
return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
}
mut = ocuo.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, ocuo.mutation); err != nil {
return nil, err
}
}
return node, err
}
// SaveX is like Save, but panics if an error occurs.
func (ocuo *ObClusterUpdateOne) SaveX(ctx context.Context) *ObCluster {
node, err := ocuo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (ocuo *ObClusterUpdateOne) Exec(ctx context.Context) error {
_, err := ocuo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ocuo *ObClusterUpdateOne) ExecX(ctx context.Context) {
if err := ocuo.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (ocuo *ObClusterUpdateOne) defaults() {
if _, ok := ocuo.mutation.UpdateTime(); !ok {
v := obcluster.UpdateDefaultUpdateTime()
ocuo.mutation.SetUpdateTime(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (ocuo *ObClusterUpdateOne) check() error {
if v, ok := ocuo.mutation.ObClusterID(); ok {
if err := obcluster.ObClusterIDValidator(v); err != nil {
return &ValidationError{Name: "ob_cluster_id", err: fmt.Errorf(`ent: validator failed for field "ObCluster.ob_cluster_id": %w`, err)}
}
}
return nil
}
func (ocuo *ObClusterUpdateOne) sqlSave(ctx context.Context) (_node *ObCluster, err error) {
_spec := &sqlgraph.UpdateSpec{
Node: &sqlgraph.NodeSpec{
Table: obcluster.Table,
Columns: obcluster.Columns,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: obcluster.FieldID,
},
},
}
id, ok := ocuo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ObCluster.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := ocuo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, obcluster.FieldID)
for _, f := range fields {
if !obcluster.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != obcluster.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := ocuo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := ocuo.mutation.CreateTime(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: obcluster.FieldCreateTime,
})
}
if value, ok := ocuo.mutation.UpdateTime(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: obcluster.FieldUpdateTime,
})
}
if value, ok := ocuo.mutation.Name(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldName,
})
}
if value, ok := ocuo.mutation.ObClusterID(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeInt64,
Value: value,
Column: obcluster.FieldObClusterID,
})
}
if value, ok := ocuo.mutation.AddedObClusterID(); ok {
_spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{
Type: field.TypeInt64,
Value: value,
Column: obcluster.FieldObClusterID,
})
}
if value, ok := ocuo.mutation.GetType(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldType,
})
}
if value, ok := ocuo.mutation.RootserviceJSON(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: obcluster.FieldRootserviceJSON,
})
}
_node = &ObCluster{config: ocuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, ocuo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{obcluster.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{err.Error(), err}
}
return nil, err
}
return _node, nil
}
// Code generated by entc, DO NOT EDIT.
package predicate
import (
"entgo.io/ent/dialect/sql"
)
// ObCluster is the predicate function for obcluster builders.
type ObCluster func(*sql.Selector)
// Code generated by entc, DO NOT EDIT.
package ent
import (
"time"
"github.com/oceanbase/configserver/ent/obcluster"
"github.com/oceanbase/configserver/ent/schema"
)
// The init function reads all schema descriptors with runtime code
// (default values, validators, hooks and policies) and stitches it
// to their package variables.
func init() {
obclusterFields := schema.ObCluster{}.Fields()
_ = obclusterFields
// obclusterDescCreateTime is the schema descriptor for create_time field.
obclusterDescCreateTime := obclusterFields[0].Descriptor()
// obcluster.DefaultCreateTime holds the default value on creation for the create_time field.
obcluster.DefaultCreateTime = obclusterDescCreateTime.Default.(func() time.Time)
// obclusterDescUpdateTime is the schema descriptor for update_time field.
obclusterDescUpdateTime := obclusterFields[1].Descriptor()
// obcluster.DefaultUpdateTime holds the default value on creation for the update_time field.
obcluster.DefaultUpdateTime = obclusterDescUpdateTime.Default.(func() time.Time)
// obcluster.UpdateDefaultUpdateTime holds the default value on update for the update_time field.
obcluster.UpdateDefaultUpdateTime = obclusterDescUpdateTime.UpdateDefault.(func() time.Time)
// obclusterDescObClusterID is the schema descriptor for ob_cluster_id field.
obclusterDescObClusterID := obclusterFields[3].Descriptor()
// obcluster.ObClusterIDValidator is a validator for the "ob_cluster_id" field. It is called by the builders before save.
obcluster.ObClusterIDValidator = obclusterDescObClusterID.Validators[0].(func(int64) error)
}
// Code generated by entc, DO NOT EDIT.
package runtime
// The schema-stitching logic is generated in github.com/oceanbase/configserver/ent/runtime.go
const (
Version = "v0.10.1" // Version of ent codegen.
Sum = "h1:dM5h4Zk6yHGIgw4dCqVzGw3nWgpGYJiV4/kyHEF6PFo=" // Sum of ent codegen.
)
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// ObCluster holds the schema definition for the ObCluster entity.
type ObCluster struct {
ent.Schema
}
// Fields of the ObCluster.
func (ObCluster) Fields() []ent.Field {
return []ent.Field{
field.Time("create_time").Default(time.Now),
field.Time("update_time").Default(time.Now).UpdateDefault(time.Now),
field.String("name"),
field.Int64("ob_cluster_id").Positive(),
field.String("type"),
field.String("rootservice_json").
Annotations(entsql.Annotation{
Size: 65536,
}),
}
}
func (ObCluster) Edges() []ent.Edge {
return nil
}
func (ObCluster) Indexes() []ent.Index {
return []ent.Index{
index.Fields("update_time"),
index.Fields("name", "ob_cluster_id").Unique(),
}
}
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"sync"
"entgo.io/ent/dialect"
)
// Tx is a transactional client that is created by calling Client.Tx().
type Tx struct {
config
// ObCluster is the client for interacting with the ObCluster builders.
ObCluster *ObClusterClient
// lazily loaded.
client *Client
clientOnce sync.Once
// completion callbacks.
mu sync.Mutex
onCommit []CommitHook
onRollback []RollbackHook
// ctx lives for the life of the transaction. It is
// the same context used by the underlying connection.
ctx context.Context
}
type (
// Committer is the interface that wraps the Commit method.
Committer interface {
Commit(context.Context, *Tx) error
}
// The CommitFunc type is an adapter to allow the use of ordinary
// function as a Committer. If f is a function with the appropriate
// signature, CommitFunc(f) is a Committer that calls f.
CommitFunc func(context.Context, *Tx) error
// CommitHook defines the "commit middleware". A function that gets a Committer
// and returns a Committer. For example:
//
// hook := func(next ent.Committer) ent.Committer {
// return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error {
// // Do some stuff before.
// if err := next.Commit(ctx, tx); err != nil {
// return err
// }
// // Do some stuff after.
// return nil
// })
// }
//
CommitHook func(Committer) Committer
)
// Commit calls f(ctx, m).
func (f CommitFunc) Commit(ctx context.Context, tx *Tx) error {
return f(ctx, tx)
}
// Commit commits the transaction.
func (tx *Tx) Commit() error {
txDriver := tx.config.driver.(*txDriver)
var fn Committer = CommitFunc(func(context.Context, *Tx) error {
return txDriver.tx.Commit()
})
tx.mu.Lock()
hooks := append([]CommitHook(nil), tx.onCommit...)
tx.mu.Unlock()
for i := len(hooks) - 1; i >= 0; i-- {
fn = hooks[i](fn)
}
return fn.Commit(tx.ctx, tx)
}
// OnCommit adds a hook to call on commit.
func (tx *Tx) OnCommit(f CommitHook) {
tx.mu.Lock()
defer tx.mu.Unlock()
tx.onCommit = append(tx.onCommit, f)
}
type (
// Rollbacker is the interface that wraps the Rollback method.
Rollbacker interface {
Rollback(context.Context, *Tx) error
}
// The RollbackFunc type is an adapter to allow the use of ordinary
// function as a Rollbacker. If f is a function with the appropriate
// signature, RollbackFunc(f) is a Rollbacker that calls f.
RollbackFunc func(context.Context, *Tx) error
// RollbackHook defines the "rollback middleware". A function that gets a Rollbacker
// and returns a Rollbacker. For example:
//
// hook := func(next ent.Rollbacker) ent.Rollbacker {
// return ent.RollbackFunc(func(ctx context.Context, tx *ent.Tx) error {
// // Do some stuff before.
// if err := next.Rollback(ctx, tx); err != nil {
// return err
// }
// // Do some stuff after.
// return nil
// })
// }
//
RollbackHook func(Rollbacker) Rollbacker
)
// Rollback calls f(ctx, m).
func (f RollbackFunc) Rollback(ctx context.Context, tx *Tx) error {
return f(ctx, tx)
}
// Rollback rollbacks the transaction.
func (tx *Tx) Rollback() error {
txDriver := tx.config.driver.(*txDriver)
var fn Rollbacker = RollbackFunc(func(context.Context, *Tx) error {
return txDriver.tx.Rollback()
})
tx.mu.Lock()
hooks := append([]RollbackHook(nil), tx.onRollback...)
tx.mu.Unlock()
for i := len(hooks) - 1; i >= 0; i-- {
fn = hooks[i](fn)
}
return fn.Rollback(tx.ctx, tx)
}
// OnRollback adds a hook to call on rollback.
func (tx *Tx) OnRollback(f RollbackHook) {
tx.mu.Lock()
defer tx.mu.Unlock()
tx.onRollback = append(tx.onRollback, f)
}
// Client returns a Client that binds to current transaction.
func (tx *Tx) Client() *Client {
tx.clientOnce.Do(func() {
tx.client = &Client{config: tx.config}
tx.client.init()
})
return tx.client
}
func (tx *Tx) init() {
tx.ObCluster = NewObClusterClient(tx.config)
}
// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation.
// The idea is to support transactions without adding any extra code to the builders.
// When a builder calls to driver.Tx(), it gets the same dialect.Tx instance.
// Commit and Rollback are nop for the internal builders and the user must call one
// of them in order to commit or rollback the transaction.
//
// If a closed transaction is embedded in one of the generated entities, and the entity
// applies a query, for example: ObCluster.QueryXXX(), the query will be executed
// through the driver which created this transaction.
//
// Note that txDriver is not goroutine safe.
type txDriver struct {
// the driver we started the transaction from.
drv dialect.Driver
// tx is the underlying transaction.
tx dialect.Tx
}
// newTx creates a new transactional driver.
func newTx(ctx context.Context, drv dialect.Driver) (*txDriver, error) {
tx, err := drv.Tx(ctx)
if err != nil {
return nil, err
}
return &txDriver{tx: tx, drv: drv}, nil
}
// Tx returns the transaction wrapper (txDriver) to avoid Commit or Rollback calls
// from the internal builders. Should be called only by the internal builders.
func (tx *txDriver) Tx(context.Context) (dialect.Tx, error) { return tx, nil }
// Dialect returns the dialect of the driver we started the transaction from.
func (tx *txDriver) Dialect() string { return tx.drv.Dialect() }
// Close is a nop close.
func (*txDriver) Close() error { return nil }
// Commit is a nop commit for the internal builders.
// User must call `Tx.Commit` in order to commit the transaction.
func (*txDriver) Commit() error { return nil }
// Rollback is a nop rollback for the internal builders.
// User must call `Tx.Rollback` in order to rollback the transaction.
func (*txDriver) Rollback() error { return nil }
// Exec calls tx.Exec.
func (tx *txDriver) Exec(ctx context.Context, query string, args, v interface{}) error {
return tx.tx.Exec(ctx, query, args, v)
}
// Query calls tx.Query.
func (tx *txDriver) Query(ctx context.Context, query string, args, v interface{}) error {
return tx.tx.Query(ctx, query, args, v)
}
var _ dialect.Driver = (*txDriver)(nil)
## log config
log:
level: info
filename: ./log/ob-configserver.log
maxsize: 30
maxage: 7
maxbackups: 10
localtime: true
compress: true
## server config
server:
address: "0.0.0.0:8080"
run_dir: run
## vip config, configserver will generate url with vip address and port and return it to the client
## if you don't hava a vip, use the server address and port is ok, but do not use some random value that can't be connected
vip:
address: "127.0.0.1"
port: 8080
## storage config
storage:
## database type, support sqlite3 or mysql
database_type: mysql
# database_type: sqlite3
## database connection config, should match database_type above
connection_url: "user:password@tcp(127.0.0.1:3306)/oceanbase?parseTime=true"
# connection_url: "/tmp/data.db?cache=shared&_fk=1"
# connection_url: "file:ent?mode=memory&cache=shared&_fk=1"
module github.com/oceanbase/configserver
go 1.17
require (
entgo.io/ent v0.10.1
github.com/gin-contrib/pprof v1.3.0
github.com/gin-gonic/gin v1.7.7
github.com/go-sql-driver/mysql v1.6.0
github.com/gwatts/gin-adapter v0.0.0-20170508204228-c44433c485ad
github.com/mattn/go-isatty v0.0.14
github.com/mattn/go-sqlite3 v1.14.10
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/goconvey v1.7.2
github.com/spf13/cobra v1.4.0
github.com/spf13/viper v1.10.1
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
require (
ariga.io/atlas v0.3.7-0.20220303204946-787354f533c3 // indirect
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/hcl/v2 v2.10.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
ariga.io/atlas v0.3.7-0.20220303204946-787354f533c3 h1:fjG4oFCQEfGrRi0QoxWcH2OO28CE6VYa6DkIr3yDySU=
ariga.io/atlas v0.3.7-0.20220303204946-787354f533c3/go.mod h1:yWGf4VPiD4SW83+kAqzD624txN9VKoJC+bpVXr2pKJA=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
entgo.io/ent v0.10.1 h1:dM5h4Zk6yHGIgw4dCqVzGw3nWgpGYJiV4/kyHEF6PFo=
entgo.io/ent v0.10.1/go.mod h1:YPgxeLnoQ/YdpVORRtqjBF+wCy9NX9IR7veTv3Bffus=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/gwatts/gin-adapter v0.0.0-20170508204228-c44433c485ad h1:eGCbPkMnsg02jXBIxxXn1Fxep9dAuTUvEi6UdJsbOhg=
github.com/gwatts/gin-adapter v0.0.0-20170508204228-c44433c485ad/go.mod h1:XywyZk8euPjg6CVt44eMyHjv0sZUiHbHtBnFKgmvj8I=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.10.0 h1:1S1UnuhDGlv3gRFV4+0EdwB+znNP5HmcGbIqwnSCByg=
github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942 h1:t0lM6y/M5IiUZyvbBTcngso8SZEZICH7is9B6g/obVU=
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9-0.20211216111533-8d383106f7e7/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package codec
import (
"bytes"
"encoding/json"
)
func MarshalToJsonString(t interface{}) (string, error) {
bf := bytes.NewBufferString("")
jsonEncoder := json.NewEncoder(bf)
jsonEncoder.SetEscapeHTML(false)
err := jsonEncoder.Encode(t)
return bf.String(), err
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package codec
import (
"github.com/stretchr/testify/require"
"testing"
)
type Service struct {
Address string `json:"address"`
}
func TestMarshalToJsonString(t *testing.T) {
service := &Service{
Address: "http://helloworld.com/services?a=1&b=2",
}
jsonStr, _ := MarshalToJsonString(service)
require.Equal(t, "{\"address\":\"http://helloworld.com/services?a=1&b=2\"}\n", jsonStr)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package http
import (
"context"
"net"
"net/http"
log "github.com/sirupsen/logrus"
)
type Listener struct {
tcpListener *net.TCPListener
unixListener *net.UnixListener
mux *http.ServeMux
srv *http.Server
}
func NewListener() *Listener {
mux := http.NewServeMux()
return &Listener{
mux: mux,
srv: &http.Server{Handler: mux},
}
}
func (l *Listener) StartTCP(addr string) error {
tcpListener, err := NewTcpListener(addr)
if err != nil {
return err
}
go func() {
_ = l.srv.Serve(tcpListener)
log.Info("http tcp server exited")
}()
l.tcpListener = tcpListener
return nil
}
func NewTcpListener(addr string) (*net.TCPListener, error) {
cfg := net.ListenConfig{}
listener, err := cfg.Listen(context.Background(), "tcp", addr)
if err != nil {
return nil, err
}
return listener.(*net.TCPListener), nil
}
func (l *Listener) StartSocket(path string) error {
listener, err := NewSocketListener(path)
if err != nil {
return err
}
go func() {
_ = l.srv.Serve(listener)
log.Info("http socket server exited")
}()
l.unixListener = listener
return nil
}
func NewSocketListener(path string) (*net.UnixListener, error) {
addr, err := net.ResolveUnixAddr("unix", path)
if err != nil {
return nil, err
}
return net.ListenUnix("unix", addr)
}
func (l *Listener) AddHandler(path string, h http.Handler) {
l.mux.Handle(path, http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.Header().Set("Connection", "close")
h.ServeHTTP(writer, request)
}))
}
func (l *Listener) Close() {
//var err error
_ = l.srv.Close()
if l.tcpListener != nil {
_ = l.tcpListener.Close()
//if err != nil {
// log.WithError(err).Warn("close tcpListener got error")
//}
}
if l.unixListener != nil {
_ = l.unixListener.Close()
//if err != nil {
// log.WithError(err).Warn("close unixListener got error")
//}
}
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package http
import (
"fmt"
"testing"
"time"
)
func TestNewTcpListener(t *testing.T) {
listener1, err := NewTcpListener("127.0.0.1:9998")
if err != nil {
t.Error("run tcp listener failed", err)
}
defer listener1.Close()
listener2, err := NewTcpListener("127.0.0.1:9998")
if err == nil {
t.Error("run tcp listener on same port")
}
defer listener2.Close()
}
func TestStartTcp(t *testing.T) {
defer time.Sleep(time.Millisecond)
listener1 := NewListener()
err := listener1.StartTCP("127.0.0.1:9998")
if err != nil {
t.Error("run StartTCP failed", err)
}
defer listener1.Close()
listener2 := NewListener()
err = listener2.StartTCP("127.0.0.1:9998")
if err == nil {
t.Error("run StartTCP on same port")
}
defer listener2.Close()
}
func TestStartErr(t *testing.T) {
defer time.Sleep(time.Millisecond)
listener1 := NewListener()
err := listener1.StartTCP("127.0.0.11:9998")
if err == nil {
fmt.Println("run StartTCP on bad address should failed")
//t.Error("run StartTCP on bad address should failed")
defer listener1.Close()
}
fmt.Println(err)
err = listener1.StartSocket("/not/exist_file")
if err == nil {
t.Error("run StartTCP on bad address should failed")
defer listener1.Close()
}
fmt.Println(err)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package net
import (
"net"
"github.com/pkg/errors"
)
func GetLocalIpAddress() (string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return "", errors.Errorf("failed to get local ip address, cannot get network interfaces: %s", err)
}
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String(), nil
}
}
}
return "", errors.New("failed to get local ip address, no ip address found")
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package trace
import (
"context"
"crypto/rand"
"fmt"
"github.com/oceanbase/configserver/logger"
)
func RandomTraceId() string {
n := 8
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
return ""
}
return fmt.Sprintf("%x", b)
}
func ContextWithRandomTraceId() context.Context {
return context.WithValue(context.Background(), logger.TraceIdKey{}, RandomTraceId())
}
func ContextWithTraceId(traceId string) context.Context {
return context.WithValue(context.Background(), logger.TraceIdKey{}, traceId)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package logger
import (
"fmt"
"io"
"runtime"
"strings"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
)
const defaultTimestampFormat = "2006-01-02T15:04:05.99999-07:00"
const INIT_TRACEID = "0000000000000000"
var textFormatter = &TextFormatter{
TimestampFormat: "2006-01-02T15:04:05.99999-07:00", // log timestamp format
FullTimestamp: true,
DisableLevelTruncation: true,
FieldMap: map[string]string{
"WARNING": "WARN", // log level string, use WARN
},
// log caller, filename:line callFunction
CallerPrettyfier: func(frame *runtime.Frame) (string, string) {
n := 0
filename := frame.File
// 获取包名
for i := len(filename) - 1; i > 0; i-- {
if filename[i] == '/' {
n++
if n >= 2 {
filename = filename[i+1:]
break
}
}
}
name := frame.Function
idx := strings.LastIndex(name, ".")
return name[idx+1:], fmt.Sprintf("%s:%d", filename, frame.Line)
},
}
type LoggerConfig struct {
Output io.Writer
Level string `yaml:"level"`
Filename string `yaml:"filename"`
MaxSize int `yaml:"maxsize"`
MaxAge int `yaml:"maxage"`
MaxBackups int `yaml:"maxbackups"`
LocalTime bool `yaml:"localtime"`
Compress bool `yaml:"compress"`
}
func InitLogger(config LoggerConfig) *logrus.Logger {
logger := logrus.StandardLogger()
// log output
if config.Output == nil {
logger.SetOutput(&lumberjack.Logger{
Filename: config.Filename,
MaxSize: config.MaxSize,
MaxBackups: config.MaxBackups,
MaxAge: config.MaxAge,
Compress: config.Compress,
})
} else {
logger.SetOutput(config.Output)
}
// log level
level, err := logrus.ParseLevel(config.Level)
if err != nil {
panic(fmt.Sprintf("parse log level: %+v", err))
}
logger.SetLevel(level)
// log format
logger.SetFormatter(textFormatter)
logger.SetReportCaller(true)
return logger
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package logger
import (
"bytes"
"context"
"fmt"
"os"
"testing"
"github.com/sirupsen/logrus"
)
func TestLogExample(t *testing.T) {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
_ = buf
logger := InitLogger(LoggerConfig{
Output: os.Stdout,
Level: "debug",
})
// use logger
logger.Debugf("debug-log-%d", 1)
logger.WithField("field-key-1", "field-val-1").Infof("info-log-%d", 1)
// with context, set traceId
ctx := context.WithValue(context.Background(), TraceIdKey{}, "TRACE-ID")
ctxlog := logger.WithContext(ctx)
ctxlog.Debugf("debug-log-%d", 2)
fieldlog := ctxlog.WithFields(map[string]interface{}{
"field-key-2": "field-val-2",
"field-key-3": "field-val-3",
})
// use the same field logger to avoid allocte new Entry
fieldlog.Infof("info-log-%d", 2)
fieldlog.Infof("info-log-%s", "2.1")
// use logrus
logrus.Debugf("debug-log-%d", 3)
logrus.WithField("field-key-3", "field-val-3").Infof("info-log-%d", 3)
fmt.Printf("%s", buf.Bytes())
}
func TestLogFile(t *testing.T) {
InitLogger(LoggerConfig{
Output: nil,
Level: "debug",
Filename: "../tests/test.log",
MaxSize: 10, // 10M
MaxAge: 3, // 3days
MaxBackups: 3,
LocalTime: false,
Compress: false,
})
// use logrus
logrus.Debugf("debug-log-%d", 1)
logrus.WithField("field-key-1", "field-val-1").Infof("info-log-%d", 1)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package logger
import (
"bytes"
"fmt"
"os"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"time"
"unicode/utf8"
"github.com/mattn/go-isatty"
"github.com/sirupsen/logrus"
)
const (
red = 31
yellow = 33
blue = 36
gray = 37
)
var (
// procid
pid = os.Getpid()
// proc start timestamp
startTimestamp time.Time
)
func init() {
startTimestamp = time.Now()
}
type TraceIdKey struct{}
// field alias
type FieldMap map[string]string
func (f FieldMap) resolve(key string) string {
if k, ok := f[key]; ok {
return k
}
return string(key)
}
// TextFormatter formats logs into text
type TextFormatter struct {
// Set to true to bypass checking for a TTY before outputting colors.
ForceColors bool
// Force disabling colors.
DisableColors bool
// Force quoting of all values
ForceQuote bool
// DisableQuote disables quoting for all values.
// DisableQuote will have a lower priority than ForceQuote.
// If both of them are set to true, quote will be forced on all values.
DisableQuote bool
// Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/
EnvironmentOverrideColors bool
// Disable timestamp logging. useful when output is redirected to logging
// system that already adds timestamps.
DisableTimestamp bool
// Enable logging the full timestamp when a TTY is attached instead of just
// the time passed since beginning of execution.
FullTimestamp bool
// TimestampFormat to use for display when a full timestamp is printed
TimestampFormat string
// The fields are sorted by default for a consistent output. For applications
// that log extremely frequently and don't use the JSON formatter this may not
// be desired.
DisableSorting bool
// The keys sorting function, when uninitialized it uses sort.Strings.
SortingFunc func([]string)
// Disables the truncation of the level text to 4 characters.
DisableLevelTruncation bool
// PadLevelText Adds padding the level text so that all the levels output at the same length
// PadLevelText is a superset of the DisableLevelTruncation option
PadLevelText bool
// QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool
// Whether the logger's out is to a terminal
isTerminal bool
// FieldMap allows users to customize the names of keys for default fields.
// As an example:
// formatter := &TextFormatter{
// FieldMap: FieldMap{
// FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
// FieldKeyMsg: "@message"}}
FieldMap FieldMap
// CallerPrettyfier can be set by the user to modify the content
// of the function and file keys in the data when ReportCaller is
// activated. If any of the returned value is the empty string the
// corresponding key will be removed from fields.
CallerPrettyfier func(*runtime.Frame) (function string, file string)
terminalInitOnce sync.Once
// The max length of the level text, generated dynamically on init
levelTextMaxLength int
}
func (f *TextFormatter) init(entry *logrus.Entry) {
if entry.Logger != nil {
file, ok := (entry.Logger.Out).(*os.File)
f.isTerminal = ok && isatty.IsTerminal(file.Fd())
}
// Get the max length of the level text
for _, level := range logrus.AllLevels {
levelTextLength := utf8.RuneCount([]byte(level.String()))
if levelTextLength > f.levelTextMaxLength {
f.levelTextMaxLength = levelTextLength
}
}
}
func (f *TextFormatter) isColored() bool {
isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows"))
if f.EnvironmentOverrideColors {
switch force, ok := os.LookupEnv("CLICOLOR_FORCE"); {
case ok && force != "0":
isColored = true
case ok && force == "0", os.Getenv("CLICOLOR") == "0":
isColored = false
}
}
return isColored && !f.DisableColors
}
func prefixFieldClashes(data logrus.Fields, fieldMap FieldMap, reportCaller bool) {
timeKey := fieldMap.resolve(logrus.FieldKeyTime)
if t, ok := data[timeKey]; ok {
data["fields."+timeKey] = t
delete(data, timeKey)
}
msgKey := fieldMap.resolve(logrus.FieldKeyMsg)
if m, ok := data[msgKey]; ok {
data["fields."+msgKey] = m
delete(data, msgKey)
}
levelKey := fieldMap.resolve(logrus.FieldKeyLevel)
if l, ok := data[levelKey]; ok {
data["fields."+levelKey] = l
delete(data, levelKey)
}
logrusErrKey := fieldMap.resolve(logrus.FieldKeyLogrusError)
if l, ok := data[logrusErrKey]; ok {
data["fields."+logrusErrKey] = l
delete(data, logrusErrKey)
}
// If reportCaller is not set, 'func' will not conflict.
if reportCaller {
funcKey := fieldMap.resolve(logrus.FieldKeyFunc)
if l, ok := data[funcKey]; ok {
data["fields."+funcKey] = l
}
fileKey := fieldMap.resolve(logrus.FieldKeyFile)
if l, ok := data[fileKey]; ok {
data["fields."+fileKey] = l
}
}
}
// Format renders a single log entry
func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) {
data := make(logrus.Fields)
for k, v := range entry.Data {
data[k] = v
}
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
keys := make([]string, 0, len(data))
for k := range data {
keys = append(keys, k)
}
var funcVal, fileVal string
fixedKeys := make([]string, 0, 4+len(data))
if !f.DisableTimestamp {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(logrus.FieldKeyTime))
}
fixedKeys = append(fixedKeys, f.FieldMap.resolve(logrus.FieldKeyLevel))
if entry.Message != "" {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(logrus.FieldKeyMsg))
}
// if entry.err != "" {
// fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError))
// }
if entry.HasCaller() {
if f.CallerPrettyfier != nil {
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
} else {
funcVal = entry.Caller.Function
fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
}
if funcVal != "" {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(logrus.FieldKeyFunc))
}
if fileVal != "" {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(logrus.FieldKeyFile))
}
}
if !f.DisableSorting {
if f.SortingFunc == nil {
sort.Strings(keys)
fixedKeys = append(fixedKeys, keys...)
} else {
if !f.isColored() {
fixedKeys = append(fixedKeys, keys...)
f.SortingFunc(fixedKeys)
} else {
f.SortingFunc(keys)
}
}
} else {
fixedKeys = append(fixedKeys, keys...)
}
var b *bytes.Buffer
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
f.terminalInitOnce.Do(func() { f.init(entry) })
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
timestampFormat = defaultTimestampFormat
}
f.printMessage(b, entry, keys, data, timestampFormat)
b.WriteByte('\n')
return b.Bytes(), nil
}
func (f *TextFormatter) printMessage(b *bytes.Buffer, entry *logrus.Entry, keys []string, data logrus.Fields, timestampFormat string) {
levelText := strings.ToUpper(entry.Level.String())
levelText = f.FieldMap.resolve(levelText)
if !f.DisableLevelTruncation && !f.PadLevelText {
levelText = levelText[0:4]
}
if f.PadLevelText {
// Generates the format string used in the next line, for example "%-6s" or "%-7s".
// Based on the max level text length.
formatString := "%-" + strconv.Itoa(f.levelTextMaxLength) + "s"
// Formats the level text by appending spaces up to the max length, for example:
// - "INFO "
// - "WARNING"
levelText = fmt.Sprintf(formatString, levelText)
}
var traceId string
if entry.Context != nil {
traceIdVal := entry.Context.Value(TraceIdKey{})
traceId, _ = traceIdVal.(string)
}
// Remove a single newline if it already exists in the message to keep
// the behavior of logrus text_formatter the same as the stdlib log package
entry.Message = strings.TrimSuffix(entry.Message, "\n")
caller := ""
if entry.HasCaller() {
funcVal := fmt.Sprintf("%s", entry.Caller.Function)
fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
if f.CallerPrettyfier != nil {
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
}
if fileVal == "" {
caller = funcVal
} else if funcVal == "" {
caller = fileVal
} else {
caller = fileVal + ":" + funcVal
}
}
if f.isColored() {
f.printColored(b, entry, keys, data, timestampFormat, levelText, caller, traceId)
} else {
f.printNoColored(b, entry, keys, data, timestampFormat, levelText, caller, traceId)
}
}
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry,
keys []string, data logrus.Fields, timestampFormat string,
levelText string, caller string, traceId string) {
var levelColor int
switch entry.Level {
case logrus.DebugLevel, logrus.TraceLevel:
levelColor = gray
case logrus.WarnLevel:
levelColor = yellow
case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
levelColor = red
case logrus.InfoLevel:
levelColor = blue
default:
levelColor = blue
}
switch {
case f.DisableTimestamp:
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m [%d,%s] %s %s",
levelColor,
levelText,
pid,
traceId,
caller,
entry.Message)
case !f.FullTimestamp:
fmt.Fprintf(b, "%04d \x1b[%dm%s\x1b[0m [%d,%s] %s %s",
int(entry.Time.Sub(startTimestamp)/time.Second),
levelColor,
levelText,
pid,
traceId,
caller,
entry.Message)
default:
fmt.Fprintf(b, "%s \x1b[%dm%s\x1b[0m [%d,%s] (%s) %s",
entry.Time.Format(timestampFormat),
levelColor,
levelText,
pid,
traceId,
caller,
entry.Message)
}
if len(keys) > 0 {
b.WriteString(" ")
}
for i, k := range keys {
v := data[k]
if i == 0 {
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
} else {
fmt.Fprintf(b, ", \x1b[%dm%s\x1b[0m=", levelColor, k)
}
f.appendValue(b, v)
}
}
func (f *TextFormatter) printNoColored(b *bytes.Buffer, entry *logrus.Entry,
keys []string, data logrus.Fields, timestampFormat string,
levelText string, caller string, traceId string) {
switch {
case f.DisableTimestamp:
fmt.Fprintf(b, "%s [%d,%s] caller=%s %s",
levelText,
pid,
traceId,
caller,
entry.Message)
case !f.FullTimestamp:
fmt.Fprintf(b, "%04d %s [%d,%s] caller=%s %s",
int(entry.Time.Sub(startTimestamp)/time.Second),
levelText,
pid,
traceId,
caller,
entry.Message)
default:
fmt.Fprintf(b, "%s %s [%d,%s] caller=%s: %s",
entry.Time.Format(timestampFormat),
levelText,
pid,
traceId,
caller,
entry.Message)
}
if len(keys) > 0 {
b.WriteString(" fields:")
}
for i, k := range keys {
v := data[k]
if i == 0 {
fmt.Fprintf(b, " %s=", k)
} else {
fmt.Fprintf(b, ", %s=", k)
}
f.appendValue(b, v)
}
}
func (f *TextFormatter) needsQuoting(text string) bool {
if f.ForceQuote {
return true
}
if f.QuoteEmptyFields && len(text) == 0 {
return true
}
if f.DisableQuote {
return false
}
for _, ch := range text {
if !((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
return true
}
}
return false
}
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
if b.Len() > 0 {
b.WriteByte(' ')
}
b.WriteString(key)
b.WriteByte('=')
f.appendValue(b, value)
}
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
stringVal, ok := value.(string)
if !ok {
stringVal = fmt.Sprint(value)
}
if !f.needsQuoting(stringVal) {
b.WriteString(stringVal)
} else {
b.WriteString(fmt.Sprintf("%q", stringVal))
}
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package model
type ObClusterIdcRegionInfo struct {
Cluster string `json:"ObRegion"`
ClusterId int64 `json:"ObRegionId"`
IdcList []*IdcRegionInfo `json:"IDCList"`
ReadonlyRsList string `json:"ReadonlyRsList"`
}
type IdcRegionInfo struct {
Idc string `json:"idc"`
Region string `json:"region"`
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package model
type ObRootServiceInfo struct {
ObClusterId int64 `json:"ObClusterId"`
ObRegionId int64 `json:"ObRegionId"`
ObCluster string `json:"ObCluster"`
ObRegion string `json:"ObRegion"`
ReadonlyRsList []*ObServerInfo `json:"ReadonlyRsList"`
RsList []*ObServerInfo `json:"RsList"`
Type string `json:"Type"`
TimeStamp int64 `json:"timestamp"`
}
type ObServerInfo struct {
Address string `json:"address"`
Role string `json:"role"`
SqlPort int `json:"sql_port"`
}
func (r *ObRootServiceInfo) Fill() {
// fill ob cluster and ob region with real
if len(r.ObCluster) > 0 {
r.ObRegion = r.ObCluster
} else if len(r.ObRegion) > 0 {
r.ObCluster = r.ObRegion
}
// fill ob cluster id and ob region id with real
if r.ObClusterId > 0 {
r.ObRegionId = r.ObClusterId
} else if r.ObRegionId > 0 {
r.ObClusterId = r.ObRegionId
}
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package model
import (
"github.com/stretchr/testify/require"
"testing"
)
type Service struct {
Address string `json:"address"`
}
func TestFillObRegion(t *testing.T) {
info := &ObRootServiceInfo{
ObCluster: "helloworld",
ObClusterId: 1,
}
info.Fill()
require.Equal(t, int64(1), info.ObRegionId)
require.Equal(t, "helloworld", info.ObRegion)
}
func TestFillObCluster(t *testing.T) {
info := &ObRootServiceInfo{
ObRegion: "helloworld",
ObRegionId: 1,
}
info.Fill()
require.Equal(t, int64(1), info.ObClusterId)
require.Equal(t, "helloworld", info.ObCluster)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package model
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
)
const (
OBPROXY_BIN_URL_FORMAT = "%s/client?Action=GetObProxy"
CONFIG_URL_FORMAT_TEMPLATE_V1 = "%s/services?Action=ObRootServiceInfo&ObRegion=${ObRegion}"
CONFIG_URL_FORMAT_TEMPLATE_V2 = "%s/services?Action=ObRootServiceInfo&version=2&ObCluster=${ObCluster}&ObClusterId=${OBClusterId}"
)
type ObProxyConfig struct {
ObProxyBinUrl string `json:"ObProxyBinUrl"`
MetaDatabase *MetaDatabaseInfo `json:"ObProxyDatabaseInfo"`
ConfigUrlList []*RootServiceInfoUrl `json:"ObRootServiceInfoUrlList"`
Version string `json:"Version"`
}
type ObProxyConfigWithTemplate struct {
ObProxyBinUrl string `json:"ObProxyBinUrl"`
MetaDatabase *MetaDatabaseInfo `json:"ObProxyDatabaseInfo"`
Version string `json:"Version"`
ObClusters []string `json:"ObClusterList"`
TemplateV1 string `json:"ObRootServiceInfoUrlTemplate"`
TemplateV2 string `json:"ObRootServiceInfoUrlTemplateV2"`
}
type ObProxyConfigVersionOnly struct {
Version string `json:"Version"`
}
type MetaDatabaseInfo struct {
Database string `json:"DataBase"`
ConfigUrl string `json:"MetaDataBase"`
Password string `json:"Password"`
User string `json:"User"`
}
type RootServiceInfoUrl struct {
ObCluster string `json:"ObRegion"`
Url string `json:"ObRootServiceInfoUrl"`
}
func NewDefaultMetaDatabaseInfo(serviceAddress string) *MetaDatabaseInfo {
return &MetaDatabaseInfo{
Database: "***",
User: "***",
Password: "***",
ConfigUrl: fmt.Sprintf("%s/services?Action=ObRootServiceInfo&User_ID=alibaba&UID=admin&ObRegion=obdv1", serviceAddress),
}
}
func NewObProxyConfigVersionOnly(version string) *ObProxyConfigVersionOnly {
return &ObProxyConfigVersionOnly{
Version: version,
}
}
func NewObProxyConfig(serviceAddress string, configUrlList []*RootServiceInfoUrl) (*ObProxyConfig, error) {
obProxyBinUrl := fmt.Sprintf(OBPROXY_BIN_URL_FORMAT, serviceAddress)
metaDatabaseInfo := NewDefaultMetaDatabaseInfo(serviceAddress)
metaJson, err := json.Marshal(metaDatabaseInfo)
if err != nil {
return nil, errors.Wrap(err, "encode obproxy metadb")
}
configUrlJson, err := json.Marshal(configUrlList)
if err != nil {
return nil, errors.Wrap(err, "encode config urls")
}
strForMd5 := string(configUrlJson) + string(metaJson) + obProxyBinUrl
h := md5.New()
h.Write([]byte(strForMd5))
version := hex.EncodeToString(h.Sum(nil))
return &ObProxyConfig{
ObProxyBinUrl: obProxyBinUrl,
MetaDatabase: NewDefaultMetaDatabaseInfo(serviceAddress),
ConfigUrlList: configUrlList,
Version: version,
}, nil
}
func NewObProxyConfigWithTemplate(serviceAddress string, clusterNames []string) (*ObProxyConfigWithTemplate, error) {
obProxyBinUrl := fmt.Sprintf(OBPROXY_BIN_URL_FORMAT, serviceAddress)
metaDatabaseInfo := NewDefaultMetaDatabaseInfo(serviceAddress)
metaJson, err := json.Marshal(metaDatabaseInfo)
if err != nil {
return nil, errors.Wrap(err, "encode obproxy metadb")
}
clusterNamesJson, err := json.Marshal(clusterNames)
if err != nil {
return nil, errors.Wrap(err, "encode cluster names")
}
templateStrV1 := fmt.Sprintf(CONFIG_URL_FORMAT_TEMPLATE_V1, serviceAddress)
templateV1Json, err := json.Marshal(templateStrV1)
if err != nil {
return nil, errors.Wrap(err, "encode config url template v1")
}
templateStrV2 := fmt.Sprintf(CONFIG_URL_FORMAT_TEMPLATE_V2, serviceAddress)
templateV2Json, err := json.Marshal(templateStrV2)
if err != nil {
return nil, errors.Wrap(err, "encode config url template v2")
}
strForMd5 := string(clusterNamesJson) + string(templateV1Json) + string(templateV2Json) + string(metaJson) + obProxyBinUrl
h := md5.New()
h.Write([]byte(strForMd5))
version := hex.EncodeToString(h.Sum(nil))
return &ObProxyConfigWithTemplate{
ObProxyBinUrl: obProxyBinUrl,
MetaDatabase: NewDefaultMetaDatabaseInfo(serviceAddress),
ObClusters: clusterNames,
TemplateV1: templateStrV1,
TemplateV2: templateStrV2,
Version: version,
}, nil
}
#!/bin/bash
PROJECT_DIR=$1
PROJECT_NAME=$2
RELEASE=$3
CUR_DIR=$(dirname $(readlink -f "$0"))
TOP_DIR=$CUR_DIR/.rpm_build
echo "[BUILD] args: CURDIR=${CUR_DIR} PROJECT_NAME=${PROJECT_NAME} RELEASE=${RELEASE}"
# prepare rpm build dirs
rm -rf $TOP_DIR
mkdir -p $TOP_DIR/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
# build rpm
cd $CUR_DIR
export PROJECT_NAME=${PROJECT_NAME}
export RELEASE=${RELEASE}
rpmbuild --define "_topdir $TOP_DIR" -bb $PROJECT_NAME.spec
find $TOP_DIR/ -name "*.rpm" -exec mv {} . 2>/dev/null \;
Name: ob-configserver
Summary: configserver for oceanbase database
Group: alipay/oceanbase
Version: 1.0.0
Release: %(echo $RELEASE)%{?dist}
URL: https://github.com/oceanbase/oceanbase
License: MulanPSL - 2.0
BuildArch: x86_64 aarch64
%description
configserver for oceanbase database
%define _prefix /home/admin
%build
cd $OLDPWD/../
make build-release
%install
cd $OLDPWD/../
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/bin
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/conf
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/log
mkdir -p $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/run
cp bin/* $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/bin
cp -r etc/* $RPM_BUILD_ROOT/%{_prefix}/ob-configserver/conf
%files
%defattr(755,admin,admin)
%dir %{_prefix}/ob-configserver/
%dir %{_prefix}/ob-configserver/bin
%dir %{_prefix}/ob-configserver/conf
%dir %{_prefix}/ob-configserver/log
%dir %{_prefix}/ob-configserver/run
%{_prefix}/ob-configserver/bin/ob-configserver
%{_prefix}/ob-configserver/conf/*.yaml
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
"github.com/oceanbase/configserver/config"
"github.com/oceanbase/configserver/ent"
"github.com/oceanbase/configserver/lib/trace"
"github.com/oceanbase/configserver/logger"
)
var configServer *ConfigServer
func GetConfigServer() *ConfigServer {
return configServer
}
type ConfigServer struct {
Config *config.ConfigServerConfig
Server *HttpServer
Client *ent.Client
}
func NewConfigServer(conf *config.ConfigServerConfig) *ConfigServer {
server := &ConfigServer{
Config: conf,
Server: &HttpServer{
Counter: new(Counter),
Router: gin.Default(),
Server: &http.Server{},
Address: conf.Server.Address,
},
Client: nil,
}
configServer = server
return configServer
}
func (server *ConfigServer) Run() error {
client, err := ent.Open(server.Config.Storage.DatabaseType, server.Config.Storage.ConnectionUrl)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("initialize storage client with config %v", server.Config.Storage))
}
server.Client = client
defer server.Client.Close()
if err := server.Client.Schema.Create(context.Background()); err != nil {
return errors.Wrap(err, "create configserver schema")
}
// start http server
ctx, cancel := context.WithCancel(trace.ContextWithTraceId(logger.INIT_TRACEID))
server.Server.Cancel = cancel
// register route
InitConfigServerRoutes(server.Server.Router)
// run http server
server.Server.Run(ctx)
return nil
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"net/http"
"sync"
"time"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/oceanbase/configserver/lib/codec"
"github.com/oceanbase/configserver/lib/net"
"github.com/oceanbase/configserver/lib/trace"
)
var invalidActionOnce sync.Once
var invalidActionFunc func(*gin.Context)
func getInvalidActionFunc() func(*gin.Context) {
invalidActionOnce.Do(func() {
invalidActionFunc = handlerFunctionWrapper(invalidAction)
})
return invalidActionFunc
}
func getServerIdentity() string {
ip, _ := net.GetLocalIpAddress()
return ip
}
func handlerFunctionWrapper(f func(context.Context, *gin.Context) *ApiResponse) func(*gin.Context) {
fn := func(c *gin.Context) {
tStart := time.Now()
traceId := trace.RandomTraceId()
ctxlog := trace.ContextWithTraceId(traceId)
log.WithContext(ctxlog).Infof("handle request: %s %s", c.Request.Method, c.Request.RequestURI)
response := f(ctxlog, c)
cost := time.Now().Sub(tStart).Milliseconds()
response.TraceId = traceId
response.Cost = cost
response.Server = getServerIdentity()
responseJson, err := codec.MarshalToJsonString(response)
if err != nil {
log.WithContext(ctxlog).Errorf("response: %s", "response serialization error")
c.JSON(http.StatusInternalServerError, NewErrorResponse(errors.Wrap(err, "serialize response")))
} else {
log.WithContext(ctxlog).Infof("response: %s", responseJson)
c.String(response.Code, string(responseJson))
}
}
return fn
}
func invalidAction(ctxlog context.Context, c *gin.Context) *ApiResponse {
log.WithContext(ctxlog).Error("invalid action")
return NewIllegalArgumentResponse(errors.New("invalid action"))
}
func getHandler() gin.HandlerFunc {
fn := func(c *gin.Context) {
action := c.Query("Action")
switch action {
case "ObRootServiceInfo":
getObRootServiceGetFunc()(c)
case "GetObProxyConfig":
getObProxyConfigFunc()(c)
case "GetObRootServiceInfoUrlTemplate":
getObProxyConfigWithTemplateFunc()(c)
case "ObIDCRegionInfo":
getObIdcRegionInfoFunc()(c)
default:
getInvalidActionFunc()(c)
}
}
return gin.HandlerFunc(fn)
}
func postHandler() gin.HandlerFunc {
fn := func(c *gin.Context) {
action, _ := c.GetQuery("Action")
switch action {
case "ObRootServiceInfo":
getObRootServicePostFunc()(c)
case "GetObProxyConfig":
getObProxyConfigFunc()(c)
case "GetObRootServiceInfoUrlTemplate":
getObProxyConfigWithTemplateFunc()(c)
default:
getInvalidActionFunc()(c)
}
}
return gin.HandlerFunc(fn)
}
func deleteHandler() gin.HandlerFunc {
fn := func(c *gin.Context) {
action, _ := c.GetQuery("Action")
switch action {
case "ObRootServiceInfo":
getObRootServiceDeleteFunc()(c)
default:
getInvalidActionFunc()(c)
}
}
return gin.HandlerFunc(fn)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"net/http"
"sync"
"sync/atomic"
"time"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
libhttp "github.com/oceanbase/configserver/lib/http"
)
type HttpServer struct {
// server will be stopped, new request will be rejected
Stopping int32
// current session count, concurrent safely
Counter *Counter
// http routers
Router *gin.Engine
// address
Address string
// http server, call its Run, Shutdown methods
Server *http.Server
// stop the http.Server by calling cancel method
Cancel context.CancelFunc
}
// UseCounter use counter middleware
func (server *HttpServer) UseCounter() {
server.Router.Use(
server.counterPreHandlerFunc,
server.counterPostHandlerFunc,
)
}
// Run start a httpServer
// when ctx is cancelled, call shutdown to stop the httpServer
func (server *HttpServer) Run(ctx context.Context) {
server.Server.Handler = server.Router
if server.Address != "" {
log.WithContext(ctx).Infof("listen on address: %s", server.Address)
tcpListener, err := libhttp.NewTcpListener(server.Address)
if err != nil {
log.WithError(err).
Errorf("create tcp listener on address '%s' failed %v", server.Address, err)
return
}
go func() {
if err := server.Server.Serve(tcpListener); err != nil {
log.WithError(err).
Info("tcp server exited")
}
}()
}
for {
select {
case <-ctx.Done():
if err := server.Shutdown(ctx); err != nil {
log.WithContext(ctx).
WithError(err).
Error("server shutdown failed!")
// in a for loop, sleep 100ms
time.Sleep(time.Millisecond * 100)
} else {
log.WithContext(ctx).Info("server shutdown successfully.")
return
}
}
}
}
// shutdown httpServer can shutdown if sessionCount is 0,
// otherwise, return an error
func (server *HttpServer) Shutdown(ctx context.Context) error {
atomic.StoreInt32(&(server.Stopping), 1)
sessionCount := atomic.LoadInt32(&server.Counter.sessionCount)
if sessionCount > 0 {
return errors.Errorf("server shutdown failed, cur-session count:%d, shutdown will be success when wait session-count is 0.", sessionCount)
}
return server.Server.Close()
}
// counterPreHandlerFunc middleware for httpServer session count, before process a request
func (server *HttpServer) counterPreHandlerFunc(c *gin.Context) {
if atomic.LoadInt32(&(server.Stopping)) == 1 {
c.Abort()
c.JSON(http.StatusServiceUnavailable, "server is shutdowning now.")
return
}
server.Counter.incr()
c.Next()
}
// counterPostHandlerFunc middleware for httpServer session count, after process a request
func (server *HttpServer) counterPostHandlerFunc(c *gin.Context) {
c.Next()
server.Counter.decr()
}
// counter session counter
// when server receive a request, sessionCount +1,
// when the request returns a response, sessionCount -1.
type Counter struct {
sessionCount int32
sync.Mutex
}
// incr sessionCount +1 concurrent safely
func (c *Counter) incr() {
c.Lock()
c.sessionCount++
defer c.Unlock()
}
// decr sessionCount -1 concurrent safely
func (c *Counter) decr() {
c.Lock()
c.sessionCount--
defer c.Unlock()
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gin-gonic/gin"
. "github.com/smartystreets/goconvey/convey"
)
func TestCounter(t *testing.T) {
count := new(Counter)
Convey("counter after init", t, func() {
So(count.sessionCount, ShouldEqual, 0)
})
count.incr()
Convey("counter after incr", t, func() {
So(count.sessionCount, ShouldEqual, 1)
})
count.decr()
Convey("counter after decr", t, func() {
So(count.sessionCount, ShouldEqual, 0)
})
}
func TestHttpServer(t *testing.T) {
server := &HttpServer{
Counter: new(Counter),
Router: gin.Default(),
Server: &http.Server{
Addr: ":0",
},
}
w := httptest.NewRecorder()
server.UseCounter()
server.Router.GET("/foo", fooHandler)
end := make(chan bool, 1)
handler := func(w http.ResponseWriter, r *http.Request) {
server.Router.ServeHTTP(w, r)
time.Sleep(time.Second)
}
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
go func() {
handler(w, req)
end <- true
}()
time.Sleep(10 * time.Millisecond)
t.Run("handle a 1 second request", func(t *testing.T) {
Convey("session count should be 1", t, func() {
So(server.Counter.sessionCount, ShouldEqual, 1)
})
err := server.Shutdown(context.Background())
Convey("server shutdown should fail", t, func() {
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "server shutdown failed")
})
})
<-end
t.Run("handle request end", func(t *testing.T) {
Convey("session count should be 0", t, func() {
So(server.Counter.sessionCount, ShouldEqual, 0)
})
err := server.Shutdown(context.Background())
Convey("server shutdown should success", t, func() {
So(err, ShouldBeNil)
})
})
}
func fooHandler(c *gin.Context) {
time.Sleep(time.Second)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"fmt"
"strconv"
"sync"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
// log "github.com/sirupsen/logrus"
"github.com/oceanbase/configserver/model"
)
const (
CONFIG_URL_FORMAT = "%s/services?Action=ObRootServiceInfo&ObCluster=%s"
)
var obProxyConfigOnce sync.Once
var obProxyConfigFunc func(*gin.Context)
var obProxyConfigWithTemplateOnce sync.Once
var obProxyConfigWithTemplateFunc func(*gin.Context)
func getObProxyConfigFunc() func(*gin.Context) {
obProxyConfigOnce.Do(func() {
obProxyConfigFunc = handlerFunctionWrapper(getObProxyConfig)
})
return obProxyConfigFunc
}
func getObProxyConfigWithTemplateFunc() func(*gin.Context) {
obProxyConfigWithTemplateOnce.Do(func() {
obProxyConfigWithTemplateFunc = handlerFunctionWrapper(getObProxyConfigWithTemplate)
})
return obProxyConfigWithTemplateFunc
}
func getServiceAddress() string {
return fmt.Sprintf("http://%s:%d", GetConfigServer().Config.Vip.Address, GetConfigServer().Config.Vip.Port)
}
func isVersionOnly(c *gin.Context) (bool, error) {
ret := false
var err error
versionOnly, ok := c.GetQuery("VersionOnly")
if ok {
ret, err = strconv.ParseBool(versionOnly)
}
return ret, err
}
func getObProxyConfig(ctxlog context.Context, c *gin.Context) *ApiResponse {
var response *ApiResponse
client := GetConfigServer().Client
versionOnly, err := isVersionOnly(c)
if err != nil {
return NewIllegalArgumentResponse(errors.Wrap(err, "invalid parameter, failed to parse versiononly"))
}
rootServiceInfoUrlMap := make(map[string]*model.RootServiceInfoUrl)
clusters, err := client.ObCluster.Query().All(context.Background())
if err != nil {
return NewErrorResponse(errors.Wrap(err, "query ob clusters"))
}
for _, cluster := range clusters {
rootServiceInfoUrlMap[cluster.Name] = &model.RootServiceInfoUrl{
ObCluster: cluster.Name,
Url: fmt.Sprintf(CONFIG_URL_FORMAT, getServiceAddress(), cluster.Name),
}
}
rootServiceInfoUrls := make([]*model.RootServiceInfoUrl, 0, len(rootServiceInfoUrlMap))
for _, info := range rootServiceInfoUrlMap {
rootServiceInfoUrls = append(rootServiceInfoUrls, info)
}
obProxyConfig, err := model.NewObProxyConfig(getServiceAddress(), rootServiceInfoUrls)
if err != nil {
response = NewErrorResponse(errors.Wrap(err, "generate obproxy config"))
} else {
if versionOnly {
response = NewSuccessResponse(model.NewObProxyConfigVersionOnly(obProxyConfig.Version))
} else {
response = NewSuccessResponse(obProxyConfig)
}
}
return response
}
func getObProxyConfigWithTemplate(ctxlog context.Context, c *gin.Context) *ApiResponse {
var response *ApiResponse
client := GetConfigServer().Client
versionOnly, err := isVersionOnly(c)
if err != nil {
return NewIllegalArgumentResponse(errors.Wrap(err, "invalid parameter, failed to parse versiononly"))
}
clusterMap := make(map[string]interface{})
clusters, err := client.ObCluster.Query().All(context.Background())
if err != nil {
return NewErrorResponse(errors.Wrap(err, "query ob clusters"))
}
for _, cluster := range clusters {
clusterMap[cluster.Name] = nil
}
clusterNames := make([]string, 0, len(clusterMap))
for clusterName := range clusterMap {
clusterNames = append(clusterNames, clusterName)
}
obProxyConfigWithTemplate, err := model.NewObProxyConfigWithTemplate(getServiceAddress(), clusterNames)
if err != nil {
response = NewErrorResponse(errors.Wrap(err, "generate obproxy config with template"))
} else {
if versionOnly {
response = NewSuccessResponse(model.NewObProxyConfigVersionOnly(obProxyConfigWithTemplate.Version))
} else {
response = NewSuccessResponse(obProxyConfigWithTemplate)
}
}
return response
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
"github.com/oceanbase/configserver/config"
"github.com/oceanbase/configserver/ent"
)
func TestParseVersionOnlyNormal(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=GetObproxyConfig&VersionOnly=true", nil)
versionOnly, err := isVersionOnly(c)
require.True(t, versionOnly)
require.True(t, err == nil)
}
func TestParseVersionOnlyError(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=GetObproxyConfig&VersionOnly=abc", nil)
_, err := isVersionOnly(c)
require.True(t, err != nil)
}
func TestParseVersionOnlyNotExists(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=GetObproxyConfig", nil)
c.Params = []gin.Param{{Key: "Version", Value: "abc"}}
versionOnly, err := isVersionOnly(c)
require.False(t, versionOnly)
require.True(t, err == nil)
}
func TestGetObProxyConfig(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=GetObproxyConfig", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
response := getObProxyConfig(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
func TestGetObproxyConfigWithTemplate(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=GetObproxyConfig", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
response := getObProxyConfigWithTemplate(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"context"
"encoding/json"
"fmt"
"strconv"
"sync"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/oceanbase/configserver/ent"
"github.com/oceanbase/configserver/ent/obcluster"
"github.com/oceanbase/configserver/model"
)
var obRootServiceGetOnce sync.Once
var obRootServiceGetFunc func(*gin.Context)
var obRootServicePostOnce sync.Once
var obRootServicePostFunc func(*gin.Context)
var obRootServiceDeleteOnce sync.Once
var obRootServiceDeleteFunc func(*gin.Context)
var obIdcRegionInfoOnce sync.Once
var obIdcRegionInfoFunc func(*gin.Context)
func getObIdcRegionInfoFunc() func(c *gin.Context) {
obIdcRegionInfoOnce.Do(func() {
obIdcRegionInfoFunc = handlerFunctionWrapper(getObIdcRegionInfo)
})
return obIdcRegionInfoFunc
}
func getObRootServiceGetFunc() func(*gin.Context) {
obRootServiceGetOnce.Do(func() {
obRootServiceGetFunc = handlerFunctionWrapper(getObRootServiceInfo)
})
return obRootServiceGetFunc
}
func getObRootServicePostFunc() func(*gin.Context) {
obRootServicePostOnce.Do(func() {
obRootServicePostFunc = handlerFunctionWrapper(createOrUpdateObRootServiceInfo)
})
return obRootServicePostFunc
}
func getObRootServiceDeleteFunc() func(*gin.Context) {
obRootServiceDeleteOnce.Do(func() {
obRootServiceDeleteFunc = handlerFunctionWrapper(deleteObRootServiceInfo)
})
return obRootServiceDeleteFunc
}
type RootServiceInfoParam struct {
ObCluster string
ObClusterId int64
Version int
}
func getCommonParam(c *gin.Context) (*RootServiceInfoParam, error) {
var err error
name := ""
obCluster, obClusterOk := c.GetQuery("ObCluster")
obRegion, obRegionOk := c.GetQuery("ObRegion")
if obClusterOk {
name = obCluster
}
if obRegionOk {
name = obRegion
}
if len(name) == 0 {
return nil, errors.New("no obcluster or obregion")
}
obClusterId, obClusterIdOk := c.GetQuery("ObClusterId")
obRegionId, obRegionIdOk := c.GetQuery("ObRegionId")
var clusterId int64
var clusterIdStr string
if obClusterIdOk {
clusterIdStr = obClusterId
}
if obRegionIdOk {
clusterIdStr = obRegionId
}
if clusterIdStr != "" {
clusterId, err = strconv.ParseInt(clusterIdStr, 10, 64)
if err != nil {
return nil, errors.Wrap(err, "parse ob cluster id")
}
}
version := 0
versionStr, versionOk := c.GetQuery("version")
if versionOk {
version, err = strconv.Atoi(versionStr)
if err != nil {
return nil, errors.Wrap(err, "parse version")
}
}
return &RootServiceInfoParam{
ObCluster: name,
ObClusterId: clusterId,
Version: version,
}, nil
}
func selectPrimaryCluster(clusters []*model.ObRootServiceInfo) *model.ObRootServiceInfo {
var primaryCluster *model.ObRootServiceInfo
for _, cluster := range clusters {
if primaryCluster == nil {
primaryCluster = cluster
} else {
if primaryCluster.Type != "PRIMARY" {
if cluster.Type == "PRIMARY" || cluster.TimeStamp > primaryCluster.TimeStamp {
primaryCluster = cluster
}
} else {
if cluster.Type == "PRIMARY" && cluster.TimeStamp > primaryCluster.TimeStamp {
primaryCluster = cluster
}
}
}
}
return primaryCluster
}
func getObIdcRegionInfo(ctxlog context.Context, c *gin.Context) *ApiResponse {
// return empty idc list
param, err := getCommonParam(c)
if err != nil {
return NewErrorResponse(errors.Wrap(err, "parse ob idc region info query parameter"))
}
rootServiceInfoList, err := getRootServiceInfoList(ctxlog, param.ObCluster, param.ObClusterId)
if err != nil {
if rootServiceInfoList != nil && len(rootServiceInfoList) == 0 {
return NewNotFoundResponse(errors.New(fmt.Sprintf("no obcluster found with query param %v", param)))
} else {
return NewErrorResponse(errors.Wrap(err, fmt.Sprintf("get all rootservice info for cluster %s:%d", param.ObCluster, param.ObClusterId)))
}
}
idcList := make([]*model.IdcRegionInfo, 0, 0)
if param.Version < 2 || param.ObClusterId > 0 {
primaryCluster := selectPrimaryCluster(rootServiceInfoList)
obClusterIdcRegionInfo := &model.ObClusterIdcRegionInfo{
Cluster: primaryCluster.ObCluster,
ClusterId: primaryCluster.ObClusterId,
IdcList: idcList,
ReadonlyRsList: "",
}
return NewSuccessResponse(obClusterIdcRegionInfo)
} else {
obClusterIdcRegionInfoList := make([]*model.ObClusterIdcRegionInfo, 0, 4)
for _, cluster := range rootServiceInfoList {
obClusterIdcRegionInfo := &model.ObClusterIdcRegionInfo{
Cluster: cluster.ObCluster,
ClusterId: cluster.ObClusterId,
IdcList: idcList,
ReadonlyRsList: "",
}
obClusterIdcRegionInfoList = append(obClusterIdcRegionInfoList, obClusterIdcRegionInfo)
}
return NewSuccessResponse(obClusterIdcRegionInfoList)
}
}
func getRootServiceInfoList(ctxlog context.Context, obCluster string, obClusterId int64) ([]*model.ObRootServiceInfo, error) {
var clusters []*ent.ObCluster
var err error
rootServiceInfoList := make([]*model.ObRootServiceInfo, 0, 4)
client := GetConfigServer().Client
if obClusterId != 0 {
log.WithContext(ctxlog).Infof("query ob clusters with obcluster %s and obcluster_id %d", obCluster, obClusterId)
clusters, err = client.ObCluster.Query().Where(obcluster.Name(obCluster), obcluster.ObClusterID(obClusterId)).All(context.Background())
} else {
log.WithContext(ctxlog).Infof("query ob clusters with obcluster %s", obCluster)
clusters, err = client.ObCluster.Query().Where(obcluster.Name(obCluster)).All(context.Background())
}
if err != nil {
return nil, errors.Wrap(err, "query ob clusters from db")
}
if len(clusters) == 0 {
return rootServiceInfoList, errors.New(fmt.Sprintf("no root service info found with obcluster %s, obcluster id %d", obCluster, obClusterId))
}
for _, cluster := range clusters {
var rootServiceInfo model.ObRootServiceInfo
err = json.Unmarshal([]byte(cluster.RootserviceJSON), &rootServiceInfo)
if err != nil {
return nil, errors.Wrap(err, "deserialize root service info")
}
rootServiceInfo.Fill()
rootServiceInfoList = append(rootServiceInfoList, &rootServiceInfo)
}
return rootServiceInfoList, nil
}
func getObRootServiceInfo(ctxlog context.Context, c *gin.Context) *ApiResponse {
var response *ApiResponse
param, err := getCommonParam(c)
if err != nil {
return NewErrorResponse(errors.Wrap(err, "parse rootservice query parameter"))
}
rootServiceInfoList, err := getRootServiceInfoList(ctxlog, param.ObCluster, param.ObClusterId)
if err != nil {
if rootServiceInfoList != nil && len(rootServiceInfoList) == 0 {
return NewNotFoundResponse(errors.New(fmt.Sprintf("no obcluster found with query param %v", param)))
} else {
return NewErrorResponse(errors.Wrap(err, fmt.Sprintf("get all rootservice info for cluster %s:%d", param.ObCluster, param.ObClusterId)))
}
}
if param.Version < 2 || param.ObClusterId > 0 {
log.WithContext(ctxlog).Infof("return primary ob cluster")
response = NewSuccessResponse(selectPrimaryCluster(rootServiceInfoList))
} else {
log.WithContext(ctxlog).Infof("return all ob clusters")
response = NewSuccessResponse(rootServiceInfoList)
}
return response
}
func createOrUpdateObRootServiceInfo(ctxlog context.Context, c *gin.Context) *ApiResponse {
var response *ApiResponse
client := GetConfigServer().Client
obRootServiceInfo := new(model.ObRootServiceInfo)
err := c.ShouldBindJSON(obRootServiceInfo)
if err != nil {
return NewErrorResponse(errors.Wrap(err, "bind rootservice query parameter"))
}
obRootServiceInfo.Fill()
param, err := getCommonParam(c)
if err != nil {
return NewErrorResponse(errors.Wrap(err, "parse rootservice query parameter"))
}
if len(obRootServiceInfo.ObCluster) == 0 {
return NewIllegalArgumentResponse(errors.New("ob cluster name is required"))
}
if param.Version > 1 {
if len(obRootServiceInfo.Type) == 0 {
return NewIllegalArgumentResponse(errors.New("ob cluster type is required when version > 1"))
}
}
rsBytes, err := json.Marshal(obRootServiceInfo)
if err != nil {
response = NewErrorResponse(errors.Wrap(err, "serialize ob rootservice info"))
} else {
rootServiceInfoJson := string(rsBytes)
log.WithContext(ctxlog).Infof("store rootservice info %s", rootServiceInfoJson)
err := client.ObCluster.
Create().
SetName(obRootServiceInfo.ObCluster).
SetObClusterID(obRootServiceInfo.ObClusterId).
SetType(obRootServiceInfo.Type).
SetRootserviceJSON(rootServiceInfoJson).
OnConflict().
SetRootserviceJSON(rootServiceInfoJson).
Exec(context.Background())
if err != nil {
response = NewErrorResponse(errors.Wrap(err, "save ob rootservice info"))
} else {
response = NewSuccessResponse("successful")
}
}
return response
}
func deleteObRootServiceInfo(ctxlog context.Context, c *gin.Context) *ApiResponse {
var response *ApiResponse
client := GetConfigServer().Client
param, err := getCommonParam(c)
if err != nil {
return NewErrorResponse(errors.Wrap(err, "parse rootservice query parameter"))
}
if param.Version < 2 {
response = NewIllegalArgumentResponse(errors.New("delete obcluster rs info is only supported when version >= 2"))
} else if param.ObClusterId == 0 {
response = NewIllegalArgumentResponse(errors.New("delete obcluster rs info is only supported with obcluster id"))
} else {
affected, err := client.ObCluster.
Delete().
Where(obcluster.Name(param.ObCluster), obcluster.ObClusterID(param.ObClusterId)).
Exec(context.Background())
if err != nil {
response = NewErrorResponse(errors.Wrap(err, fmt.Sprintf("delete obcluster %s with ob cluster id %d in db", param.ObCluster, param.ObClusterId)))
} else {
log.WithContext(ctxlog).Infof("delete obcluster %s with ob cluster id %d in db, affected rows %d", param.ObCluster, param.ObClusterId, affected)
response = NewSuccessResponse("success")
}
}
return response
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
"github.com/oceanbase/configserver/config"
"github.com/oceanbase/configserver/ent"
)
const testRootServiceJson = "{\"Type\":\"PRIMARY\",\"ObClusterId\":1,\"ObRegionId\":1,\"ObCluster\":\"c1\",\"ObRegion\":\"c1\",\"ReadonlyRsList\":[],\"RsList\":[{\"address\":\"1.1.1.1:2882\",\"role\":\"LEADER\",\"sql_port\":2881}],\"timestamp\":1649435362283000}"
func TestGetRootServiceInfoParamOldVersion(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObRegion=c1&ObRegionId=1", nil)
obRootServiceInfoParam, err := getCommonParam(c)
require.Equal(t, "c1", obRootServiceInfoParam.ObCluster)
require.Equal(t, int64(1), obRootServiceInfoParam.ObClusterId)
require.Equal(t, 0, obRootServiceInfoParam.Version)
require.True(t, err == nil)
}
func TestGetRootServiceInfoParamVersion2(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&ObClusterId=1&version=2", nil)
obRootServiceInfoParam, err := getCommonParam(c)
require.Equal(t, "c1", obRootServiceInfoParam.ObCluster)
require.Equal(t, int64(1), obRootServiceInfoParam.ObClusterId)
require.Equal(t, 2, obRootServiceInfoParam.Version)
require.True(t, err == nil)
}
func TestGetObRootServiceInfo(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
client.ObCluster.
Create().
SetName("c1").
SetObClusterID(1).
SetType("PRIMARY").
SetRootserviceJSON(testRootServiceJson).
OnConflict().
SetRootserviceJSON(testRootServiceJson).
Exec(context.Background())
response := getObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
func TestGetObRootServiceInfoV2(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&version=2", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
client.ObCluster.
Create().
SetName("c1").
SetObClusterID(1).
SetType("PRIMARY").
SetRootserviceJSON(testRootServiceJson).
OnConflict().
SetRootserviceJSON(testRootServiceJson).
Exec(context.Background())
response := getObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
func TestGetObRootServiceInfoV2WithObClusterId(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&ObClusterId=1&version=2", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
client.ObCluster.
Create().
SetName("c1").
SetObClusterID(1).
SetType("PRIMARY").
SetRootserviceJSON(testRootServiceJson).
OnConflict().
SetRootserviceJSON(testRootServiceJson).
Exec(context.Background())
response := getObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
func TestGetObRootServiceInfoNoResult(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c2&ObClusterId=2&version=2", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
response := getObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusNotFound, response.Code)
}
func TestCreateOrUpdateObRootServiceInfo(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&ObClusterId=1&version=2", bytes.NewBuffer([]byte(testRootServiceJson)))
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
response := createOrUpdateObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
func TestDeleteObRootServiceInfo(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("DELETE", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&ObClusterId=1&version=2", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
client.ObCluster.
Create().
SetName("c1").
SetObClusterID(1).
SetType("PRIMARY").
SetRootserviceJSON(testRootServiceJson).
OnConflict().
SetRootserviceJSON(testRootServiceJson).
Exec(context.Background())
response := deleteObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusOK, response.Code)
}
func TestDeleteObRootServiceInfoVersion1(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("DELETE", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&ObClusterId=1", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
client.ObCluster.
Create().
SetName("c1").
SetObClusterID(1).
SetType("PRIMARY").
SetRootserviceJSON(testRootServiceJson).
OnConflict().
SetRootserviceJSON(testRootServiceJson).
Exec(context.Background())
response := deleteObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusBadRequest, response.Code)
}
func TestDeleteObRootServiceInfoWithoutClusterId(t *testing.T) {
// test gin
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("DELETE", "http://1.1.1.1:8080/services?Action=ObRootServiceInfo&ObCluster=c1&version=2", nil)
// mock db client
client, _ := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client.Schema.Create(context.Background())
configServerConfig, _ := config.ParseConfigServerConfig("../etc/config.yaml")
configServer = &ConfigServer{
Config: configServerConfig,
Client: client,
}
client.ObCluster.
Create().
SetName("c1").
SetObClusterID(1).
SetType("PRIMARY").
SetRootserviceJSON(testRootServiceJson).
OnConflict().
SetRootserviceJSON(testRootServiceJson).
Exec(context.Background())
response := deleteObRootServiceInfo(context.Background(), c)
require.Equal(t, http.StatusBadRequest, response.Code)
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"fmt"
"net/http"
)
type ApiResponse struct {
Code int `json:"Code"`
Message string `json:"Message"`
Successful bool `json:"Success"`
Data interface{} `json:"Data"`
TraceId string `json:"Trace"`
Server string `json:"Server"`
Cost int64 `json:"Cost"`
}
type IterableData struct {
Contents interface{} `json:"Contents"`
}
func NewSuccessResponse(data interface{}) *ApiResponse {
return &ApiResponse{
Code: http.StatusOK,
Message: "successful",
Successful: true,
Data: data,
}
}
func NewBadRequestResponse(err error) *ApiResponse {
return &ApiResponse{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("bad request: %v", err),
Successful: false,
}
}
func NewIllegalArgumentResponse(err error) *ApiResponse {
return &ApiResponse{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("illegal argument: %v", err),
Successful: false,
}
}
func NewNotFoundResponse(err error) *ApiResponse {
return &ApiResponse{
Code: http.StatusNotFound,
Message: fmt.Sprintf("resource not found: %v", err),
Successful: false,
}
}
func NewNotImplementedResponse(err error) *ApiResponse {
return &ApiResponse{
Code: http.StatusNotImplemented,
Message: fmt.Sprintf("request not implemented: %v", err),
Successful: false,
}
}
func NewErrorResponse(err error) *ApiResponse {
return &ApiResponse{
Code: http.StatusInternalServerError,
Message: fmt.Sprintf("got internal error: %v", err),
Successful: false,
}
}
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
package server
import (
"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
)
func InitConfigServerRoutes(r *gin.Engine) {
r.Use(
gin.Recovery(), // gin's crash-free middleware
)
// register pprof for debug
pprof.Register(r, "debug/pprof")
// register route
r.GET("/services", getHandler())
r.POST("/services", postHandler())
r.DELETE("/services", deleteHandler())
}
github.com/oceanbase/configserver/cmd
github.com/oceanbase/configserver/ent
github.com/oceanbase/configserver/config
github.com/oceanbase/configserver/lib/trace
github.com/oceanbase/configserver/lib/net
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册