From 08a8ae40bb3f68c0194892107f8cc3718240a213 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 5 Aug 2020 14:36:54 +0800 Subject: [PATCH 01/37] add dmclusters CRD --- docs/api-references/docs.md | 8576 ++++++++++------- pkg/apis/pingcap/v1alpha1/crd_kinds.go | 6 + pkg/apis/pingcap/v1alpha1/dm_config.go | 98 + .../pingcap/v1alpha1/openapi_generated.go | 833 +- pkg/apis/pingcap/v1alpha1/types.go | 273 + .../pingcap/v1alpha1/zz_generated.deepcopy.go | 461 + pkg/util/crdutil.go | 2 + 7 files changed, 6748 insertions(+), 3501 deletions(-) create mode 100644 pkg/apis/pingcap/v1alpha1/dm_config.go diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index f0e840e9a0..b7e145fc1b 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -3055,12 +3055,14 @@ and component-level overrides

ComponentSpec

(Appears on: +MasterSpec, PDSpec, PumpSpec, TiCDCSpec, TiDBSpec, TiFlashSpec, -TiKVSpec) +TiKVSpec, +WorkerSpec)

ComponentSpec is the base spec of each component, the fields should always accessed by the BasicSpec() method to respect the cluster-level properties

@@ -3372,6 +3374,7 @@ string

(Appears on: ComponentSpec, +DMClusterSpec, TidbClusterSpec)

@@ -3546,6 +3549,18 @@ CrdKind +DMCluster
+ + +CrdKind + + + + + + + + Backup
@@ -3713,13 +3728,9 @@ LeastRemainAvailableStoragePercent should between 5 and 90. If not set, the defa -

DashboardConfig

-

-(Appears on: -PDConfig) -

+

DMCluster

-

DashboardConfig is the configuration for tidb-dashboard.

+

DMCluster is the control script’s spec

@@ -3731,280 +3742,258 @@ LeastRemainAvailableStoragePercent should between 5 and 90. If not set, the defa - +

Spec defines the behavior of a dm cluster

+
+
+
-tidb-cacert-path
+metadata
-string + +Kubernetes meta/v1.ObjectMeta +
-(Optional) +Refer to the Kubernetes API documentation for the fields of the +metadata field.
-tidb-cert-path
+spec
-string + +DMClusterSpec +
-(Optional) -
- -
-tidb-key-path
+discovery
-string + +DMDiscoverySpec +
-(Optional) +

Discovery spec

-public-path-prefix
+dm_master
-string + +MasterSpec +
(Optional) +

dm-master cluster spec

-internal-proxy
+dm_worker
-bool + +WorkerSpec +
(Optional) +

dm-worker cluster spec

-disable-telemetry
+paused
bool
(Optional) -

When not disabled, usage data will be sent to PingCAP for improving user experience. -Optional: Defaults to false -Deprecated in PD v4.0.3, use EnableTelemetry instead

+

Indicates that the dm cluster is paused and will not be processed by +the controller.

-enable-telemetry
+version
-bool +string
(Optional) -

When enabled, usage data will be sent to PingCAP for improving user experience. -Optional: Defaults to true

+

TODO: remove optional after defaulting logic introduced +dm cluster version

-

DiscoverySpec

-

-(Appears on: -TidbClusterSpec) -

-

-

DiscoverySpec contains details of Discovery members

-

- - - - + + - - - -
FieldDescription +schedulerName
+ +string + +
+

SchedulerName of DM cluster Pods

+
-ResourceRequirements
+pvReclaimPolicy
- -Kubernetes core/v1.ResourceRequirements + +Kubernetes core/v1.PersistentVolumeReclaimPolicy
-

-(Members of ResourceRequirements are embedded into this type.) -

+

Persistent volume reclaim policy applied to the PVs that consumed by DM cluster

-

DumplingConfig

-

-(Appears on: -BackupSpec) -

-

-

DumplingConfig contains config for dumpling

-

- - - - - - - - - -
FieldDescription
-options
+imagePullPolicy
-[]string + +Kubernetes core/v1.PullPolicy +
-

Options means options for backup data to remote storage with dumpling.

+

ImagePullPolicy of DM cluster Pods

-tableFilter
+imagePullSecrets
-[]string + +[]Kubernetes core/v1.LocalObjectReference +
-

TableFilter means Table filter expression for ‘db.table’ matching

+(Optional) +

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-

Experimental

-

-(Appears on: -TiDBConfig) -

-

-

Experimental controls the features that are still experimental: their semantics, interfaces are subject to change. -Using these features in the production environment is not recommended.

-

- - - - + + - - - -
FieldDescription +configUpdateStrategy
+ + +ConfigUpdateStrategy + + +
+

ConfigUpdateStrategy determines how the configuration change is applied to the cluster. +UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the +cluster component is needed to reload the configuration change. +UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the +related components to use the new ConfigMap, that is, the new configuration will be applied automatically.

+
-allow-auto-random
+enablePVReclaim
bool
(Optional) -

Whether enable the syntax like auto_random(3) on the primary key column. -Imported from TiDB v3.1.0. -Deprecated in TiDB v4.0.3, please check detail in https://docs.pingcap.com/tidb/dev/release-4.0.3#improvements.

+

Whether enable PVC reclaim for orphan PVC left by statefulset scale-in +Optional: Defaults to false

-allow-expression-index
+tlsCluster
-bool + +TLSCluster +
(Optional) -

Whether enable creating expression index.

+

Whether enable the TLS connection between DM server components +Optional: Defaults to nil

-

ExternalEndpoint

-

-(Appears on: -BasicAutoScalerSpec) -

-

-

ExternalEndpoint describes the external service endpoint -which provides the ability to get the tikv/tidb auto-scaling recommended replicas

-

- - - - - - - - + +
FieldDescription
-host
+nodeSelector
-string +map[string]string
-

Host indicates the external service’s host

+(Optional) +

Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively

-port
+annotations
-int32 +map[string]string
-

Port indicates the external service’s port

+(Optional) +

Base annotations of DM cluster Pods, components may add or override selectors upon this respectively

-path
+tolerations
-string + +[]Kubernetes core/v1.Toleration +
-

Path indicates the external service’s path

+(Optional) +

Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively

+
-tlsSecret
+status
- -SecretRef + +DMClusterStatus -(Optional) -

TLSSecret indicates the Secret which stores the TLS configuration. If set, the operator will use https -to communicate to the external service

+

Most recently observed status of the dm cluster

-

FileLogConfig

+

DMClusterCondition

(Appears on: -Log, -PDLogConfig) +DMClusterStatus)

+

DMClusterCondition is dm cluster condition

@@ -4016,73 +4005,94 @@ to communicate to the external service

+ + + +
-filename
+type
-string + +TidbClusterConditionType +
-(Optional) -

Log filename, leave empty to disable file log.

+

Type of the condition.

-log-rotate
+status
-bool + +Kubernetes core/v1.ConditionStatus +
-(Optional) -

Is log rotate enabled.

+

Status of the condition, one of True, False, Unknown.

-max-size
+lastUpdateTime
-int + +Kubernetes meta/v1.Time +
-(Optional) -

Max size for a single file, in MB.

+

The last time this condition was updated.

-max-days
+lastTransitionTime
-int + +Kubernetes meta/v1.Time +
(Optional) -

Max log keep days, default is never deleting.

+

Last time the condition transitioned from one status to another.

-max-backups
+reason
-int +string
(Optional) -

Maximum number of old log files to retain.

+

The reason for the condition’s last transition.

+
+message
+ +string + +
+(Optional) +

A human readable message indicating details about the transition.

-

Flash

+

DMClusterConditionType

+

+

DMClusterConditionType represents a dm cluster condition value.

+

+

DMClusterSpec

(Appears on: -CommonConfig) +DMCluster)

-

Flash is the configuration of [flash] section.

+

DMClusterSpec describes the attributes that a user creates on a dm cluster

@@ -4094,223 +4104,214 @@ int - -
-overlap_threshold
+discovery
-float64 + +DMDiscoverySpec +
-(Optional) -

Optional: Defaults to 0.6

+

Discovery spec

-compact_log_min_period
+dm_master
-int32 + +MasterSpec +
(Optional) -

Optional: Defaults to 200

+

dm-master cluster spec

-flash_cluster
+dm_worker
- -FlashCluster + +WorkerSpec
(Optional) +

dm-worker cluster spec

-

FlashLogger

-

-(Appears on: -CommonConfig) -

-

-

FlashLogger is the configuration of [logger] section.

-

- - - - - - - - - -
FieldDescription
-size
+paused
-string +bool
(Optional) -

Optional: Defaults to 100M

+

Indicates that the dm cluster is paused and will not be processed by +the controller.

-level
+version
string
(Optional) -

Optional: Defaults to information

+

TODO: remove optional after defaulting logic introduced +dm cluster version

-count
+schedulerName
-int32 +string
-(Optional) -

Optional: Defaults to 10

+

SchedulerName of DM cluster Pods

-

GcsStorageProvider

-

-(Appears on: -StorageProvider) -

-

-

GcsStorageProvider represents the google cloud storage for storing backups.

-

- - - - - - - -
FieldDescription
-projectId
+pvReclaimPolicy
-string + +Kubernetes core/v1.PersistentVolumeReclaimPolicy +
-

ProjectId represents the project that organizes all your Google Cloud Platform resources

+

Persistent volume reclaim policy applied to the PVs that consumed by DM cluster

-location
+imagePullPolicy
-string + +Kubernetes core/v1.PullPolicy +
-

Location in which the gcs bucket is located.

+

ImagePullPolicy of DM cluster Pods

-path
+imagePullSecrets
-string + +[]Kubernetes core/v1.LocalObjectReference +
-

Path is the full path where the backup is saved. -The format of the path must be: “/

+(Optional) +

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-bucket
+configUpdateStrategy
-string + +ConfigUpdateStrategy +
-

Bucket in which to store the backup data.

+

ConfigUpdateStrategy determines how the configuration change is applied to the cluster. +UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the +cluster component is needed to reload the configuration change. +UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the +related components to use the new ConfigMap, that is, the new configuration will be applied automatically.

-storageClass
+enablePVReclaim
-string +bool
-

StorageClass represents the storage class

+(Optional) +

Whether enable PVC reclaim for orphan PVC left by statefulset scale-in +Optional: Defaults to false

-objectAcl
+tlsCluster
-string + +TLSCluster +
-

ObjectAcl represents the access control list for new objects

+(Optional) +

Whether enable the TLS connection between DM server components +Optional: Defaults to nil

-bucketAcl
+nodeSelector
-string +map[string]string
-

BucketAcl represents the access control list for new buckets

+(Optional) +

Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively

-secretName
+annotations
-string +map[string]string
-

SecretName is the name of secret which stores the -gcs service account credentials JSON.

+(Optional) +

Base annotations of DM cluster Pods, components may add or override selectors upon this respectively

-prefix
+tolerations
-string + +[]Kubernetes core/v1.Toleration +
-

Prefix of the data path.

+(Optional) +

Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively

-

GrafanaSpec

+

DMClusterStatus

(Appears on: -TidbMonitorSpec) +DMCluster)

-

GrafanaSpec is the desired state of grafana

+

DMClusterStatus represents the current status of a dm cluster.

@@ -4322,35 +4323,22 @@ string - - - - @@ -4359,56 +4347,39 @@ ServiceSpec - - - - - - - -
-MonitorContainer
+dm_master
- -MonitorContainer + +MasterStatus
-

-(Members of MonitorContainer are embedded into this type.) -

-
-logLevel
- -string - -
-service
+dm_worker
- -ServiceSpec + +WorkerStatus
-username
- -string - -
-
-password
- -string - -
-
-envs
+monitor
-map[string]string + +TidbMonitorRef +
-(Optional)
-ingress
+conditions
- -IngressSpec + +[]DMClusterCondition
(Optional) +

Represents the latest available observations of a dm cluster’s state.

-

GroupRef

+

DMDiscoverySpec

(Appears on: -TidbClusterStatus) +DMClusterSpec)

+

DMDiscoverySpec contains details of Discovery members for dm

@@ -4420,28 +4391,40 @@ IngressSpec + + + +
-Reference
+ResourceRequirements
- -Kubernetes core/v1.LocalObjectReference + +Kubernetes core/v1.ResourceRequirements

-(Members of Reference are embedded into this type.) +(Members of ResourceRequirements are embedded into this type.)

+host
+ +string + +
+

Host indicates the existed TiDB discovery host. If not specified, dm cluster will start a new one

+
-

HelperSpec

+

DMSecurityConfig

(Appears on: -TidbClusterSpec) +MasterConfig, +WorkerConfig)

-

HelperSpec contains details of helper component

+

DM common security config

@@ -4453,108 +4436,61 @@ Kubernetes core/v1.LocalObjectReference - - -
-image
+ssl-ca
string
(Optional) -

Image used to tail slow log and set kernel parameters if necessary, must have tail and sysctl installed -Optional: Defaults to busybox:1.26.2

+

SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn’t be empty

-imagePullPolicy
+ssl-cert
- -Kubernetes core/v1.PullPolicy - +string
(Optional) -

ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present -Optional: Defaults to the cluster-level setting

-
-

IngressSpec

-

-(Appears on: -GrafanaSpec, -PrometheusSpec) -

-

-

IngressSpec describe the ingress desired state for the target component

-

- - - - - - - - - - -
FieldDescription
-hosts
- -[]string - -
-

Hosts describe the hosts for the ingress

+

SSLCert is the path of file that contains X509 certificate in PEM format.

-annotations
+ssl-key
-map[string]string +string
(Optional) -

Annotations describe the desired annotations for the ingress

+

SSLKey is the path of file that contains X509 key in PEM format.

-tls
+cert-allowed-cn
- -[]Kubernetes extensions/v1beta1.IngressTLS - +[]string
(Optional) -

TLS configuration. Currently the Ingress only supports a single TLS -port, 443. If multiple members of this list specify different hosts, they -will be multiplexed on the same port according to the hostname specified -through the SNI TLS extension, if the ingress controller fulfilling the -ingress supports SNI.

+

CertAllowedCN is the Common Name that allowed

-

InitializePhase

-

-(Appears on: -TidbInitializerStatus) -

-

-

-

InitializerSpec

+

DashboardConfig

(Appears on: -TidbMonitorSpec) +PDConfig)

-

InitializerSpec is the desired state of initializer

+

DashboardConfig is the configuration for tidb-dashboard.

@@ -4566,129 +4502,95 @@ ingress supports SNI.

- - - - - -
-MonitorContainer
- - -MonitorContainer - - -
-

-(Members of MonitorContainer are embedded into this type.) -

-
-envs
+tidb-cacert-path
-map[string]string +string
(Optional)
-

Interval

-

-(Appears on: -Quota) -

-

-

Interval is the configuration of [quotas.default.interval] section.

-

- - - - - - - -
FieldDescription
-duration
+tidb-cert-path
-int32 +string
(Optional) -

Optional: Defaults to 3600

-queries
+tidb-key-path
-int32 +string
(Optional) -

Optional: Defaults to 0

-errors
+public-path-prefix
-int32 +string
(Optional) -

Optional: Defaults to 0

-result_rows
+internal-proxy
-int32 +bool
(Optional) -

Optional: Defaults to 0

-read_rows
+disable-telemetry
-int32 +bool
(Optional) -

Optional: Defaults to 0

+

When not disabled, usage data will be sent to PingCAP for improving user experience. +Optional: Defaults to false +Deprecated in PD v4.0.3, use EnableTelemetry instead

-execution_time
+enable-telemetry
-int32 +bool
(Optional) -

Optional: Defaults to 0

+

When enabled, usage data will be sent to PingCAP for improving user experience. +Optional: Defaults to true

-

IsolationRead

+

DiscoverySpec

(Appears on: -TiDBConfig) +TidbClusterSpec)

-

IsolationRead is the config for isolation read.

+

DiscoverySpec contains details of Discovery members

@@ -4700,26 +4602,28 @@ int32
-engines
+ResourceRequirements
-[]string + +Kubernetes core/v1.ResourceRequirements +
-(Optional) -

Engines filters tidb-server access paths by engine type. -imported from v3.1.0

+

+(Members of ResourceRequirements are embedded into this type.) +

-

Log

+

DumplingConfig

(Appears on: -TiDBConfig) +BackupSpec)

-

Log is the log section of config.

+

DumplingConfig contains config for dumpling

@@ -4731,160 +4635,225 @@ imported from v3.1.0

+ +
-level
+options
-string +[]string
-(Optional) -

Log level. -Optional: Defaults to info

+

Options means options for backup data to remote storage with dumpling.

-format
+tableFilter
-string +[]string
-(Optional) -

Log format. one of json, text, or console. -Optional: Defaults to text

+

TableFilter means Table filter expression for ‘db.table’ matching

+

Experimental

+

+(Appears on: +TiDBConfig) +

+

+

Experimental controls the features that are still experimental: their semantics, interfaces are subject to change. +Using these features in the production environment is not recommended.

+

+ + - - + + + + + +
-disable-timestamp
- -bool - -
-(Optional) -

Disable automatic timestamps in output.

-
FieldDescription
-enable-timestamp
+allow-auto-random
bool
(Optional) -

EnableTimestamp enables automatic timestamps in log output.

+

Whether enable the syntax like auto_random(3) on the primary key column. +Imported from TiDB v3.1.0. +Deprecated in TiDB v4.0.3, please check detail in https://docs.pingcap.com/tidb/dev/release-4.0.3#improvements.

-enable-error-stack
+allow-expression-index
bool
(Optional) -

EnableErrorStack enables annotating logs with the full stack error -message.

+

Whether enable creating expression index.

+

ExternalEndpoint

+

+(Appears on: +BasicAutoScalerSpec) +

+

+

ExternalEndpoint describes the external service endpoint +which provides the ability to get the tikv/tidb auto-scaling recommended replicas

+

+ + + + + + + + + +
FieldDescription
-file
+host
- -FileLogConfig - +string
-(Optional) -

File log config.

+

Host indicates the external service’s host

-enable-slow-log
+port
-bool +int32
-(Optional) +

Port indicates the external service’s port

-slow-query-file
+path
string
-(Optional) +

Path indicates the external service’s path

-slow-threshold
+tlsSecret
-uint64 + +SecretRef +
(Optional) -

Optional: Defaults to 300

+

TLSSecret indicates the Secret which stores the TLS configuration. If set, the operator will use https +to communicate to the external service

+

FileLogConfig

+

+(Appears on: +Log, +PDLogConfig) +

+

+

+ + + + + + + + + + + + + + + +
FieldDescription
-expensive-threshold
+filename
-uint +string
(Optional) -

Optional: Defaults to 10000

+

Log filename, leave empty to disable file log.

-query-log-max-len
+log-rotate
-uint64 +bool
(Optional) -

Optional: Defaults to 2048

+

Is log rotate enabled.

-record-plan-in-slow-log
+max-size
-uint32 +int
(Optional) -

Optional: Defaults to 1

+

Max size for a single file, in MB.

+
+max-days
+ +int + +
+(Optional) +

Max log keep days, default is never deleting.

+
+max-backups
+ +int + +
+(Optional) +

Maximum number of old log files to retain.

-

LogTailerSpec

+

Flash

(Appears on: -TiFlashSpec) +CommonConfig)

-

LogTailerSpec represents an optional log tailer sidecar container

+

Flash is the configuration of [flash] section.

@@ -4896,29 +4865,50 @@ uint32 + + + + + + + +
-ResourceRequirements
+overlap_threshold
- -Kubernetes core/v1.ResourceRequirements +float64 + +
+(Optional) +

Optional: Defaults to 0.6

+
+compact_log_min_period
+ +int32 + +
+(Optional) +

Optional: Defaults to 200

+
+flash_cluster
+ + +FlashCluster
-

-(Members of ResourceRequirements are embedded into this type.) -

+(Optional)
-

MasterKeyFileConfig

+

FlashLogger

(Appears on: -TiKVMasterKeyConfig, -TiKVSecurityConfigEncryptionMasterKey, -TiKVSecurityConfigEncryptionPreviousMasterKey) +CommonConfig)

+

FlashLogger is the configuration of [logger] section.

@@ -4930,39 +4920,49 @@ Kubernetes core/v1.ResourceRequirements + + + +
-method
+size
string
-

Encrypyion method, use master key encryption data key -Possible values: plaintext, aes128-ctr, aes192-ctr, aes256-ctr -Optional: Default to plaintext -optional

+(Optional) +

Optional: Defaults to 100M

-path
+level
string
-

Text file containing the key in hex form, end with ‘\n’

+(Optional) +

Optional: Defaults to information

+
+count
+ +int32 + +
+(Optional) +

Optional: Defaults to 10

-

MasterKeyKMSConfig

+

GcsStorageProvider

(Appears on: -TiKVMasterKeyConfig, -TiKVSecurityConfigEncryptionMasterKey, -TiKVSecurityConfigEncryptionPreviousMasterKey) +StorageProvider)

+

GcsStorageProvider represents the google cloud storage for storing backups.

@@ -4974,165 +4974,114 @@ string - -
-key-id
+projectId
string
-

AWS CMK key-id it can be find in AWS Console or use aws cli -This field is required

+

ProjectId represents the project that organizes all your Google Cloud Platform resources

-access-key
+location
string
-

AccessKey of AWS user, leave empty if using other authrization method -optional

+

Location in which the gcs bucket is located.

-secret-access-key
+path
string
-

SecretKey of AWS user, leave empty if using other authrization method -optional

+

Path is the full path where the backup is saved. +The format of the path must be: “/

-region
+bucket
string
-

Region of this KMS key -Optional: Default to us-east-1 -optional

+

Bucket in which to store the backup data.

-endpoint
+storageClass
string
-

Used for KMS compatible KMS, such as Ceph, minio, If use AWS, leave empty -optional

+

StorageClass represents the storage class

-

MemberPhase

-

-(Appears on: -PDStatus, -PumpStatus, -TiCDCStatus, -TiDBStatus, -TiKVStatus) -

-

-

MemberPhase is the current state of member

-

-

MemberType

-

-

MemberType represents member type

-

-

MetricsStatus

-

-(Appears on: -BasicAutoScalerStatus) -

-

-

MetricsStatus describe the basic metrics status in the last auto-scaling reconciliation

-

- - - - - - - -
FieldDescription
-name
+objectAcl
string
-

Name indicates the metrics name

+

ObjectAcl represents the access control list for new objects

-currentValue
+bucketAcl
string
-(Optional) -

CurrentValue indicates the value calculated in the last auto-scaling reconciliation

+

BucketAcl represents the access control list for new buckets

-thresholdValue
+secretName
string
-(Optional) -

TargetValue indicates the threshold value for this metrics in auto-scaling

+

SecretName is the name of secret which stores the +gcs service account credentials JSON.

-StorageMetricsStatus
+prefix
- -StorageMetricsStatus - +string
-

-(Members of StorageMetricsStatus are embedded into this type.) -

-(Optional) +

Prefix of the data path.

-

MonitorComponentAccessor

-

-

-

MonitorContainer

+

GrafanaSpec

(Appears on: -GrafanaSpec, -InitializerSpec, -PrometheusSpec, -ReloaderSpec) +TidbMonitorSpec)

-

MonitorContainer is the common attributes of the container of monitoring

+

GrafanaSpec is the desired state of grafana

@@ -5144,22 +5093,22 @@ StorageMetricsStatus - - - - - -
-ResourceRequirements
+MonitorContainer
- -Kubernetes core/v1.ResourceRequirements + +MonitorContainer

-(Members of ResourceRequirements are embedded into this type.) +(Members of MonitorContainer are embedded into this type.)

-baseImage
+logLevel
string @@ -5169,93 +5118,41 @@ string
-version
+service
-string - -
-
-imagePullPolicy
- - -Kubernetes core/v1.PullPolicy + +ServiceSpec
-(Optional)
-

Networks

-

-(Appears on: -User) -

-

-

Networks is the configuration of [users.readonly.networks] section.

-

- - - - - - - - - -
FieldDescription
-ip
+username
string
-(Optional)
-

OpenTracing

-

-(Appears on: -TiDBConfig) -

-

-

OpenTracing is the opentracing section of the config.

-

- - - - - - - - @@ -5275,27 +5172,14 @@ OpenTracingReporter (Optional) - - - -
FieldDescription
-enable
+password
-bool +string
-(Optional) -

Optional: Defaults to false

-sampler
+envs
- -OpenTracingSampler - +map[string]string
@@ -5264,10 +5161,10 @@ OpenTracingSampler
-reporter
+ingress
- -OpenTracingReporter + +IngressSpec
-rpc-metrics
- -bool - -
-(Optional) -
-

OpenTracingReporter

+

GroupRef

(Appears on: -OpenTracing) +TidbClusterStatus)

-

OpenTracingReporter is the config for opentracing reporter. -See https://godoc.org/github.com/uber/jaeger-client-go/config#ReporterConfig

@@ -5307,58 +5191,75 @@ See +Kubernetes core/v1.LocalObjectReference + + +
-(Optional) +

+(Members of Reference are embedded into this type.) +

+

HelperSpec

+

+(Appears on: +TidbClusterSpec) +

+

+

HelperSpec contains details of helper component

+

+ + - - + + + +
-buffer-flush-interval
- -time.Duration - -
-(Optional) -FieldDescription
-log-spans
+image
-bool +string
(Optional) +

Image used to tail slow log and set kernel parameters if necessary, must have tail and sysctl installed +Optional: Defaults to busybox:1.26.2

-local-agent-host-port
+imagePullPolicy
-string + +Kubernetes core/v1.PullPolicy +
(Optional) +

ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present +Optional: Defaults to the cluster-level setting

-

OpenTracingSampler

+

IngressSpec

(Appears on: -OpenTracing) +GrafanaSpec, +PrometheusSpec)

-

OpenTracingSampler is the config for opentracing sampler. -See https://godoc.org/github.com/uber/jaeger-client-go/config#SamplerConfig

+

IngressSpec describe the ingress desired state for the target component

@@ -5370,53 +5271,90 @@ See +[]Kubernetes extensions/v1beta1.IngressTLS + + +
(Optional) +

TLS configuration. Currently the Ingress only supports a single TLS +port, 443. If multiple members of this list specify different hosts, they +will be multiplexed on the same port according to the hostname specified +through the SNI TLS extension, if the ingress controller fulfilling the +ingress supports SNI.

+

InitializePhase

+

+(Appears on: +TidbInitializerStatus) +

+

+

+

InitializerSpec

+

+(Appears on: +TidbMonitorSpec) +

+

+

InitializerSpec is the desired state of initializer

+

+ + + + + + + +
FieldDescription
-max-operations
+MonitorContainer
-int + +MonitorContainer +
-(Optional) +

+(Members of MonitorContainer are embedded into this type.) +

-sampling-refresh-interval
+envs
-time.Duration +map[string]string
@@ -5425,13 +5363,13 @@ time.Duration
-

PDConfig

+

Interval

(Appears on: -PDSpec) +Quota)

-

PDConfig is the configuration of pd-server

+

Interval is the configuration of [quotas.default.interval] section.

@@ -5443,165 +5381,207 @@ time.Duration - - +
-force-new-cluster
+duration
-bool +int32
(Optional) +

Optional: Defaults to 3600

-enable-grpc-gateway
+queries
-bool +int32
(Optional) -

Optional: Defaults to true

+

Optional: Defaults to 0

-lease
+errors
-int64 +int32
(Optional) -

LeaderLease time, if leader doesn’t update its TTL -in etcd after lease time, etcd will expire the leader key -and other servers can campaign the leader again. -Etcd only supports seconds TTL, so here is second too. -Optional: Defaults to 3

+

Optional: Defaults to 0

-log
+result_rows
- -PDLogConfig - +int32
(Optional) -

Log related config.

+

Optional: Defaults to 0

-log-file
+read_rows
-string +int32
(Optional) -

Backward compatibility.

+

Optional: Defaults to 0

-log-level
+execution_time
-string +int32
(Optional) +

Optional: Defaults to 0

-tso-save-interval
- -string - +
+

IsolationRead

+

+(Appears on: +TiDBConfig) +

+

+

IsolationRead is the config for isolation read.

+

+ + + + + + + + + + + +
FieldDescription
+engines
+ +[]string +
(Optional) -

TsoSaveInterval is the interval to save timestamp. -Optional: Defaults to 3s

+

Engines filters tidb-server access paths by engine type. +imported from v3.1.0

+

Log

+

+(Appears on: +TiDBConfig) +

+

+

Log is the log section of config.

+

+ + + + + + + + + + + + + + + + + + + +
FieldDescription
-metric
+level
- -PDMetricConfig - +string
(Optional) +

Log level. +Optional: Defaults to info

-schedule
+format
- -PDScheduleConfig - +string
(Optional) -

Immutable, change should be made through pd-ctl after cluster creation

+

Log format. one of json, text, or console. +Optional: Defaults to text

-replication
+disable-timestamp
- -PDReplicationConfig - +bool
(Optional) -

Immutable, change should be made through pd-ctl after cluster creation

+

Disable automatic timestamps in output.

-namespace
+enable-timestamp
- -map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.PDNamespaceConfig - +bool
(Optional) +

EnableTimestamp enables automatic timestamps in log output.

-pd-server
+enable-error-stack
- -PDServerConfig +bool + +
+(Optional) +

EnableErrorStack enables annotating logs with the full stack error +message.

+
+file
+ + +FileLogConfig
(Optional) +

File log config.

-cluster-version
+enable-slow-log
-string +bool
@@ -5610,148 +5590,209 @@ string
-quota-backend-bytes
+slow-query-file
string
(Optional) -

QuotaBackendBytes Raise alarms when backend size exceeds the given quota. 0 means use the default quota. -the default size is 2GB, the maximum is 8GB.

-auto-compaction-mode
+slow-threshold
-string +uint64
(Optional) -

AutoCompactionMode is either ‘periodic’ or ‘revision’. The default value is ‘periodic’.

+

Optional: Defaults to 300

-auto-compaction-retention-v2
+expensive-threshold
-string +uint
(Optional) -

AutoCompactionRetention is either duration string with time unit -(e.g. ‘5m’ for 5-minute), or revision unit (e.g. ‘5000’). -If no time unit is provided and compaction mode is ‘periodic’, -the unit defaults to hour. For example, ‘5’ translates into 5-hour. -The default retention is 1 hour. -Before etcd v3.3.x, the type of retention is int. We add ‘v2’ suffix to make it backward compatible.

+

Optional: Defaults to 10000

-tikv-interval
+query-log-max-len
+ +uint64 + +
+(Optional) +

Optional: Defaults to 2048

+
+record-plan-in-slow-log
+ +uint32 + +
+(Optional) +

Optional: Defaults to 1

+
+

LogTailerSpec

+

+(Appears on: +TiFlashSpec) +

+

+

LogTailerSpec represents an optional log tailer sidecar container

+

+ + + + + + + + + + + + + +
FieldDescription
+ResourceRequirements
+ + +Kubernetes core/v1.ResourceRequirements + + +
+

+(Members of ResourceRequirements are embedded into this type.) +

+
+

MasterConfig

+

+(Appears on: +MasterSpec) +

+

+

MasterConfig is the configuration of dm-master-server

+

+ + + + + + + + + +
FieldDescription
+log-level
string
(Optional) -

TickInterval is the interval for etcd Raft tick.

+

Log level. +Optional: Defaults to info

-election-interval
+log-file
string
(Optional) -

ElectionInterval is the interval for etcd Raft election.

+

File log config.

-enable-prevote
+log-format
-bool +string
(Optional) -

Prevote is true to enable Raft Pre-Vote. -If enabled, Raft runs an additional election phase -to check whether it would get enough votes to win -an election, thus minimizing disruptions. -Optional: Defaults to true

+

Log format. one of json or text.

-security
+rpc-timeout
- -PDSecurityConfig - +string
(Optional) +

RPC timeout when dm-master request to dm-worker +Optional: Defaults to 30s

-label-property
+rpc-rate-limit
- -PDLabelPropertyConfig - +float64
(Optional) +

RPC agent rate limit when dm-master request to dm-worker +Optional: Defaults to 10

-namespace-classifier
+rpc-rate-burst
-string +int
(Optional) -

NamespaceClassifier is for classifying stores/regions into different -namespaces. -Optional: Defaults to true

+

RPC agent rate burst when dm-master request to dm-worker +Optional: Defaults to 40

-dashboard
+DMSecurityConfig
- -DashboardConfig + +DMSecurityConfig
(Optional) +

dm-master’s security config

-

PDFailureMember

-

-(Appears on: -PDStatus) -

+

MasterFailureMember

-

PDFailureMember is the pd failure member information

+

MasterFailureMember is the dm-master failure member information

@@ -5815,20 +5856,14 @@ Kubernetes meta/v1.Time
-

PDLabelPropertyConfig

-

-(Appears on: -PDConfig) -

-

-

-

PDLogConfig

+

MasterKeyFileConfig

(Appears on: -PDConfig) +TiKVMasterKeyConfig, +TiKVSecurityConfigEncryptionMasterKey, +TiKVSecurityConfigEncryptionPreviousMasterKey)

-

PDLogConfig serializes log related config in toml/json.

@@ -5840,117 +5875,118 @@ Kubernetes meta/v1.Time + +
-level
+method
string
-(Optional) -

Log level. -Optional: Defaults to info

+

Encrypyion method, use master key encryption data key +Possible values: plaintext, aes128-ctr, aes192-ctr, aes256-ctr +Optional: Default to plaintext +optional

-format
+path
string
-(Optional) -

Log format. one of json, text, or console.

+

Text file containing the key in hex form, end with ‘\n’

+

MasterKeyKMSConfig

+

+(Appears on: +TiKVMasterKeyConfig, +TiKVSecurityConfigEncryptionMasterKey, +TiKVSecurityConfigEncryptionPreviousMasterKey) +

+

+

+ + - - + + + +
-disable-timestamp
- -bool - -
-(Optional) -

Disable automatic timestamps in output.

-
FieldDescription
-file
+key-id
- -FileLogConfig - +string
-(Optional) -

File log config.

+

AWS CMK key-id it can be find in AWS Console or use aws cli +This field is required

-development
+access-key
-bool +string
-(Optional) -

Development puts the logger in development mode, which changes the -behavior of DPanicLevel and takes stacktraces more liberally.

+

AccessKey of AWS user, leave empty if using other authrization method +optional

-disable-caller
+secret-access-key
-bool +string
-(Optional) -

DisableCaller stops annotating logs with the calling function’s file -name and line number. By default, all logs are annotated.

+

SecretKey of AWS user, leave empty if using other authrization method +optional

-disable-stacktrace
+region
-bool +string
-(Optional) -

DisableStacktrace completely disables automatic stacktrace capturing. By -default, stacktraces are captured for WarnLevel and above logs in -development and ErrorLevel and above in production.

+

Region of this KMS key +Optional: Default to us-east-1 +optional

-disable-error-verbose
+endpoint
-bool +string
-(Optional) -

DisableErrorVerbose stops annotating logs with the full verbose error -message.

+

Used for KMS compatible KMS, such as Ceph, minio, If use AWS, leave empty +optional

-

PDMember

+

MasterMember

(Appears on: -PDStatus) +MasterStatus)

-

PDMember is PD member

+

MasterMember is dm-master member status

@@ -6017,12 +6053,13 @@ Kubernetes meta/v1.Time
-

PDMetricConfig

+

MasterSpec

(Appears on: -PDConfig) +DMClusterSpec)

+

MasterSpec contains details of dm-master members

@@ -6034,136 +6071,141 @@ Kubernetes meta/v1.Time - -
-job
+ComponentSpec
-string + +ComponentSpec +
-(Optional) +

+(Members of ComponentSpec are embedded into this type.) +

-address
+ResourceRequirements
-string + +Kubernetes core/v1.ResourceRequirements +
-(Optional) +

+(Members of ResourceRequirements are embedded into this type.) +

-interval
+replicas
-string +int32
-(Optional) +

The desired ready replicas

-

PDNamespaceConfig

-

-(Appears on: -PDConfig) -

-

-

PDNamespaceConfig is to overwrite the global setting for specific namespace

-

- - - - - - - -
FieldDescription
-leader-schedule-limit
+baseImage
-uint64 +string
(Optional) -

LeaderScheduleLimit is the max coexist leader schedules.

+

TODO: remove optional after defaulting introduced +Base image of the component, image tag is now allowed during validation

-region-schedule-limit
+service
-uint64 + +ServiceSpec +
(Optional) -

RegionScheduleLimit is the max coexist region schedules.

+

Service defines a Kubernetes service of Master cluster. +Optional: Defaults to .spec.services in favor of backward compatibility

-replica-schedule-limit
+maxFailoverCount
-uint64 +int32
(Optional) -

ReplicaScheduleLimit is the max coexist replica schedules.

+

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. +Optional: Defaults to 3

-merge-schedule-limit
+storageClassName
-uint64 +string
(Optional) -

MergeScheduleLimit is the max coexist merge schedules.

+

The storageClassName of the persistent volume for dm-master data storage. +Defaults to Kubernetes default storage class.

-hot-region-schedule-limit
+dataSubDir
-uint64 +string
(Optional) -

HotRegionScheduleLimit is the max coexist hot region schedules.

+

Subdirectory within the volume to store dm-master Data. By default, the data +is stored in the root directory of volume which is mounted at +/var/lib/dm-master. +Specifying this will change the data directory to a subdirectory, e.g. +/var/lib/dm-master/data if you set the value to “data”. +It’s dangerous to change this value for a running cluster as it will +upgrade your cluster to use a new storage directory. +Defaults to “” (volume’s root).

-max-replicas
+config
-uint64 + +MasterConfig +
(Optional) -

MaxReplicas is the number of replicas for each region.

+

Config is the Configuration of dm-master-servers

-

PDReplicationConfig

+

MasterStatus

(Appears on: -PDConfig) +DMClusterStatus)

-

PDReplicationConfig is the replication configuration.

+

MasterStatus is dm-master status

@@ -6175,112 +6217,1347 @@ uint64 - -
-max-replicas
+synced
-uint64 +bool
-(Optional) -

MaxReplicas is the number of replicas for each region. -Immutable, change should be made through pd-ctl after cluster creation -Optional: Defaults to 3

-location-labels
+phase
-[]string + +MemberPhase +
-(Optional) -

The label keys specified the location of a store. -The placement priorities is implied by the order of label keys. -For example, [“zone”, “rack”] means that we should place replicas to -different zones first, then to different racks if we don’t have enough zones. -Immutable, change should be made through pd-ctl after cluster creation

-strictly-match-label,string
+statefulSet
-bool + +Kubernetes apps/v1.StatefulSetStatus +
-(Optional) -

StrictlyMatchLabel strictly checks if the label of TiKV is matched with LocaltionLabels. -Immutable, change should be made through pd-ctl after cluster creation. -Imported from v3.1.0

-enable-placement-rules,string
+members
-bool + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterMember +
-(Optional) -

When PlacementRules feature is enabled. MaxReplicas and LocationLabels are not used anymore.

-

PDScheduleConfig

-

-(Appears on: -PDConfig) -

-

-

ScheduleConfig is the schedule configuration.

-

- - - - - - - - + + + + + + + +
FieldDescription
-max-snapshot-count
+leader
-uint64 + +MasterMember +
-(Optional) -

If the snapshot count of one store is greater than this value, -it will never be used as a source or target store. -Immutable, change should be made through pd-ctl after cluster creation -Optional: Defaults to 3

-max-pending-peer-count
+failureMembers
-uint64 + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.PDFailureMember +
-(Optional) -

Immutable, change should be made through pd-ctl after cluster creation -Optional: Defaults to 16

-max-merge-region-size
+unjoinedMembers
-uint64 - + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.UnjoinedMember + + +
+
+image
+ +string + +
+
+

MemberPhase

+

+(Appears on: +MasterStatus, +PDStatus, +PumpStatus, +TiCDCStatus, +TiDBStatus, +TiKVStatus, +WorkerStatus) +

+

+

MemberPhase is the current state of member

+

+

MemberType

+

+

MemberType represents member type

+

+

MetricsStatus

+

+(Appears on: +BasicAutoScalerStatus) +

+

+

MetricsStatus describe the basic metrics status in the last auto-scaling reconciliation

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+name
+ +string + +
+

Name indicates the metrics name

+
+currentValue
+ +string + +
+(Optional) +

CurrentValue indicates the value calculated in the last auto-scaling reconciliation

+
+thresholdValue
+ +string + +
+(Optional) +

TargetValue indicates the threshold value for this metrics in auto-scaling

+
+StorageMetricsStatus
+ + +StorageMetricsStatus + + +
+

+(Members of StorageMetricsStatus are embedded into this type.) +

+(Optional) +
+

MonitorComponentAccessor

+

+

+

MonitorContainer

+

+(Appears on: +GrafanaSpec, +InitializerSpec, +PrometheusSpec, +ReloaderSpec) +

+

+

MonitorContainer is the common attributes of the container of monitoring

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ResourceRequirements
+ + +Kubernetes core/v1.ResourceRequirements + + +
+

+(Members of ResourceRequirements are embedded into this type.) +

+
+baseImage
+ +string + +
+
+version
+ +string + +
+
+imagePullPolicy
+ + +Kubernetes core/v1.PullPolicy + + +
+(Optional) +
+

Networks

+

+(Appears on: +User) +

+

+

Networks is the configuration of [users.readonly.networks] section.

+

+ + + + + + + + + + + + + +
FieldDescription
+ip
+ +string + +
+(Optional) +
+

OpenTracing

+

+(Appears on: +TiDBConfig) +

+

+

OpenTracing is the opentracing section of the config.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+enable
+ +bool + +
+(Optional) +

Optional: Defaults to false

+
+sampler
+ + +OpenTracingSampler + + +
+(Optional) +
+reporter
+ + +OpenTracingReporter + + +
+(Optional) +
+rpc-metrics
+ +bool + +
+(Optional) +
+

OpenTracingReporter

+

+(Appears on: +OpenTracing) +

+

+

OpenTracingReporter is the config for opentracing reporter. +See https://godoc.org/github.com/uber/jaeger-client-go/config#ReporterConfig

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+queue-size
+ +int + +
+(Optional) +
+buffer-flush-interval
+ +time.Duration + +
+(Optional) +
+log-spans
+ +bool + +
+(Optional) +
+local-agent-host-port
+ +string + +
+(Optional) +
+

OpenTracingSampler

+

+(Appears on: +OpenTracing) +

+

+

OpenTracingSampler is the config for opentracing sampler. +See https://godoc.org/github.com/uber/jaeger-client-go/config#SamplerConfig

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+type
+ +string + +
+(Optional) +
+param
+ +float64 + +
+(Optional) +
+sampling-server-url
+ +string + +
+(Optional) +
+max-operations
+ +int + +
+(Optional) +
+sampling-refresh-interval
+ +time.Duration + +
+(Optional) +
+

PDConfig

+

+(Appears on: +PDSpec) +

+

+

PDConfig is the configuration of pd-server

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+force-new-cluster
+ +bool + +
+(Optional) +
+enable-grpc-gateway
+ +bool + +
+(Optional) +

Optional: Defaults to true

+
+lease
+ +int64 + +
+(Optional) +

LeaderLease time, if leader doesn’t update its TTL +in etcd after lease time, etcd will expire the leader key +and other servers can campaign the leader again. +Etcd only supports seconds TTL, so here is second too. +Optional: Defaults to 3

+
+log
+ + +PDLogConfig + + +
+(Optional) +

Log related config.

+
+log-file
+ +string + +
+(Optional) +

Backward compatibility.

+
+log-level
+ +string + +
+(Optional) +
+tso-save-interval
+ +string + +
+(Optional) +

TsoSaveInterval is the interval to save timestamp. +Optional: Defaults to 3s

+
+metric
+ + +PDMetricConfig + + +
+(Optional) +
+schedule
+ + +PDScheduleConfig + + +
+(Optional) +

Immutable, change should be made through pd-ctl after cluster creation

+
+replication
+ + +PDReplicationConfig + + +
+(Optional) +

Immutable, change should be made through pd-ctl after cluster creation

+
+namespace
+ + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.PDNamespaceConfig + + +
+(Optional) +
+pd-server
+ + +PDServerConfig + + +
+(Optional) +
+cluster-version
+ +string + +
+(Optional) +
+quota-backend-bytes
+ +string + +
+(Optional) +

QuotaBackendBytes Raise alarms when backend size exceeds the given quota. 0 means use the default quota. +the default size is 2GB, the maximum is 8GB.

+
+auto-compaction-mode
+ +string + +
+(Optional) +

AutoCompactionMode is either ‘periodic’ or ‘revision’. The default value is ‘periodic’.

+
+auto-compaction-retention-v2
+ +string + +
+(Optional) +

AutoCompactionRetention is either duration string with time unit +(e.g. ‘5m’ for 5-minute), or revision unit (e.g. ‘5000’). +If no time unit is provided and compaction mode is ‘periodic’, +the unit defaults to hour. For example, ‘5’ translates into 5-hour. +The default retention is 1 hour. +Before etcd v3.3.x, the type of retention is int. We add ‘v2’ suffix to make it backward compatible.

+
+tikv-interval
+ +string + +
+(Optional) +

TickInterval is the interval for etcd Raft tick.

+
+election-interval
+ +string + +
+(Optional) +

ElectionInterval is the interval for etcd Raft election.

+
+enable-prevote
+ +bool + +
+(Optional) +

Prevote is true to enable Raft Pre-Vote. +If enabled, Raft runs an additional election phase +to check whether it would get enough votes to win +an election, thus minimizing disruptions. +Optional: Defaults to true

+
+security
+ + +PDSecurityConfig + + +
+(Optional) +
+label-property
+ + +PDLabelPropertyConfig + + +
+(Optional) +
+namespace-classifier
+ +string + +
+(Optional) +

NamespaceClassifier is for classifying stores/regions into different +namespaces. +Optional: Defaults to true

+
+dashboard
+ + +DashboardConfig + + +
+(Optional) +
+

PDFailureMember

+

+(Appears on: +MasterStatus, +PDStatus) +

+

+

PDFailureMember is the pd failure member information

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+podName
+ +string + +
+
+memberID
+ +string + +
+
+pvcUID
+ +k8s.io/apimachinery/pkg/types.UID + +
+
+memberDeleted
+ +bool + +
+
+createdAt
+ + +Kubernetes meta/v1.Time + + +
+
+

PDLabelPropertyConfig

+

+(Appears on: +PDConfig) +

+

+

+

PDLogConfig

+

+(Appears on: +PDConfig) +

+

+

PDLogConfig serializes log related config in toml/json.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+level
+ +string + +
+(Optional) +

Log level. +Optional: Defaults to info

+
+format
+ +string + +
+(Optional) +

Log format. one of json, text, or console.

+
+disable-timestamp
+ +bool + +
+(Optional) +

Disable automatic timestamps in output.

+
+file
+ + +FileLogConfig + + +
+(Optional) +

File log config.

+
+development
+ +bool + +
+(Optional) +

Development puts the logger in development mode, which changes the +behavior of DPanicLevel and takes stacktraces more liberally.

+
+disable-caller
+ +bool + +
+(Optional) +

DisableCaller stops annotating logs with the calling function’s file +name and line number. By default, all logs are annotated.

+
+disable-stacktrace
+ +bool + +
+(Optional) +

DisableStacktrace completely disables automatic stacktrace capturing. By +default, stacktraces are captured for WarnLevel and above logs in +development and ErrorLevel and above in production.

+
+disable-error-verbose
+ +bool + +
+(Optional) +

DisableErrorVerbose stops annotating logs with the full verbose error +message.

+
+

PDMember

+

+(Appears on: +PDStatus) +

+

+

PDMember is PD member

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+name
+ +string + +
+
+id
+ +string + +
+

member id is actually a uint64, but apimachinery’s json only treats numbers as int64/float64 +so uint64 may overflow int64 and thus convert to float64

+
+clientURL
+ +string + +
+
+health
+ +bool + +
+
+lastTransitionTime
+ + +Kubernetes meta/v1.Time + + +
+

Last time the health transitioned from one to another.

+
+

PDMetricConfig

+

+(Appears on: +PDConfig) +

+

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+job
+ +string + +
+(Optional) +
+address
+ +string + +
+(Optional) +
+interval
+ +string + +
+(Optional) +
+

PDNamespaceConfig

+

+(Appears on: +PDConfig) +

+

+

PDNamespaceConfig is to overwrite the global setting for specific namespace

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+leader-schedule-limit
+ +uint64 + +
+(Optional) +

LeaderScheduleLimit is the max coexist leader schedules.

+
+region-schedule-limit
+ +uint64 + +
+(Optional) +

RegionScheduleLimit is the max coexist region schedules.

+
+replica-schedule-limit
+ +uint64 + +
+(Optional) +

ReplicaScheduleLimit is the max coexist replica schedules.

+
+merge-schedule-limit
+ +uint64 + +
+(Optional) +

MergeScheduleLimit is the max coexist merge schedules.

+
+hot-region-schedule-limit
+ +uint64 + +
+(Optional) +

HotRegionScheduleLimit is the max coexist hot region schedules.

+
+max-replicas
+ +uint64 + +
+(Optional) +

MaxReplicas is the number of replicas for each region.

+
+

PDReplicationConfig

+

+(Appears on: +PDConfig) +

+

+

PDReplicationConfig is the replication configuration.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+max-replicas
+ +uint64 + +
+(Optional) +

MaxReplicas is the number of replicas for each region. +Immutable, change should be made through pd-ctl after cluster creation +Optional: Defaults to 3

+
+location-labels
+ +[]string + +
+(Optional) +

The label keys specified the location of a store. +The placement priorities is implied by the order of label keys. +For example, [“zone”, “rack”] means that we should place replicas to +different zones first, then to different racks if we don’t have enough zones. +Immutable, change should be made through pd-ctl after cluster creation

+
+strictly-match-label,string
+ +bool + +
+(Optional) +

StrictlyMatchLabel strictly checks if the label of TiKV is matched with LocaltionLabels. +Immutable, change should be made through pd-ctl after cluster creation. +Imported from v3.1.0

+
+enable-placement-rules,string
+ +bool + +
+(Optional) +

When PlacementRules feature is enabled. MaxReplicas and LocationLabels are not used anymore.

+
+

PDScheduleConfig

+

+(Appears on: +PDConfig) +

+

+

ScheduleConfig is the schedule configuration.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+max-snapshot-count
+ +uint64 + +
+(Optional) +

If the snapshot count of one store is greater than this value, +it will never be used as a source or target store. +Immutable, change should be made through pd-ctl after cluster creation +Optional: Defaults to 3

+
+max-pending-peer-count
+ +uint64 + +
+(Optional) +

Immutable, change should be made through pd-ctl after cluster creation +Optional: Defaults to 16

+
+max-merge-region-size
+ +uint64 +
(Optional) @@ -8658,6 +9935,7 @@ string

(Appears on: GrafanaSpec, +MasterSpec, PDSpec, PrometheusSpec, ReloaderSpec, @@ -9083,6 +10361,7 @@ GcsStorageProvider

TLSCluster

(Appears on: +DMClusterSpec, TidbClusterSpec)

@@ -9868,154 +11147,416 @@ uint64

-stmt-summary
+stmt-summary
+ + +StmtSummary + + +
+(Optional) +
+repair-mode
+ +bool + +
+(Optional) +

RepairMode indicates that the TiDB is in the repair mode for table meta.

+
+repair-table-list
+ +[]string + +
+(Optional) +
+isolation-read
+ + +IsolationRead + + +
+(Optional) +

IsolationRead indicates that the TiDB reads data from which isolation level(engine and label).

+
+max-server-connections
+ +uint32 + +
+(Optional) +

MaxServerConnections is the maximum permitted number of simultaneous client connections.

+
+new_collations_enabled_on_first_bootstrap
+ +bool + +
+(Optional) +

NewCollationsEnabledOnFirstBootstrap indicates if the new collations are enabled, it effects only when a TiDB cluster bootstrapped on the first time.

+
+experimental
+ + +Experimental + + +
+(Optional) +

Experimental contains parameters for experimental features.

+
+enable-dynamic-config
+ +bool + +
+(Optional) +

EnableDynamicConfig enables the TiDB to fetch configs from PD and update itself during runtime. +see https://github.com/pingcap/tidb/pull/13660 for more details.

+
+enable-table-lock
+ +bool + +
+(Optional) +

imported from v3.1.0

+
+delay-clean-table-lock
+ +uint64 + +
+(Optional) +

imported from v3.1.0

+
+enable-telemetry
+ +bool + +
+(Optional) +

When enabled, usage data (for example, instance versions) will be reported to PingCAP periodically for user experience analytics. +If this config is set to false on all TiDB servers, telemetry will be always disabled regardless of the value of the global variable tidb_enable_telemetry. +See PingCAP privacy policy for details: https://pingcap.com/en/privacy-policy/. +Imported from v4.0.2. +Optional: Defaults to true

+
+

TiDBFailureMember

+

+(Appears on: +TiDBStatus) +

+

+

TiDBFailureMember is the tidb failure member information

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+podName
+ +string + +
+
+createdAt
+ + +Kubernetes meta/v1.Time + + +
+
+

TiDBGroupSpec

+

+(Appears on: +TiDBGroup) +

+

+

TiDBGroupSpec describes the attributes that a user creates on a TiDBGroup

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+TiDBSpec
+ + +TiDBSpec + + +
+

+(Members of TiDBSpec are embedded into this type.) +

+
+clusterName
+ +string + +
+

ClusterName describe the target TidbCluster in the same namespace

+
+

TiDBGroupStatus

+

+(Appears on: +TiDBGroup) +

+

+

Most recently observed status of the TiDBGroup

+

+ + + + + + + + + + + +
FieldDescription
+TiDBStatus
- -StmtSummary + +TiDBStatus
-(Optional) +

+(Members of TiDBStatus are embedded into this type.) +

+

TiDBMember

+

+(Appears on: +TiDBStatus) +

+

+

TiDBMember is TiDB member

+

+ + + + + + + + + +
FieldDescription
-repair-mode
+name
-bool +string
-(Optional) -

RepairMode indicates that the TiDB is in the repair mode for table meta.

-repair-table-list
+health
-[]string +bool
-(Optional)
-isolation-read
+lastTransitionTime
- -IsolationRead + +Kubernetes meta/v1.Time
-(Optional) -

IsolationRead indicates that the TiDB reads data from which isolation level(engine and label).

+

Last time the health transitioned from one to another.

-max-server-connections
+node
-uint32 +string
-(Optional) -

MaxServerConnections is the maximum permitted number of simultaneous client connections.

+

Node hosting pod of this TiDB member.

+

TiDBServiceSpec

+

+(Appears on: +TiDBSpec) +

+

+

+ + - - + + + +
-new_collations_enabled_on_first_bootstrap
- -bool - -
-(Optional) -

NewCollationsEnabledOnFirstBootstrap indicates if the new collations are enabled, it effects only when a TiDB cluster bootstrapped on the first time.

-
FieldDescription
-experimental
+ServiceSpec
- -Experimental + +ServiceSpec
-(Optional) -

Experimental contains parameters for experimental features.

-enable-dynamic-config
+externalTrafficPolicy
-bool + +Kubernetes core/v1.ServiceExternalTrafficPolicyType +
(Optional) -

EnableDynamicConfig enables the TiDB to fetch configs from PD and update itself during runtime. -see https://github.com/pingcap/tidb/pull/13660 for more details.

+

ExternalTrafficPolicy of the service +Optional: Defaults to omitted

-enable-table-lock
+exposeStatus
bool
(Optional) -

imported from v3.1.0

+

Whether expose the status port +Optional: Defaults to true

-delay-clean-table-lock
+mysqlNodePort
-uint64 +int
(Optional) -

imported from v3.1.0

+

Expose the tidb cluster mysql port to MySQLNodePort +Optional: Defaults to 0

-enable-telemetry
+statusNodePort
-bool +int
(Optional) -

When enabled, usage data (for example, instance versions) will be reported to PingCAP periodically for user experience analytics. -If this config is set to false on all TiDB servers, telemetry will be always disabled regardless of the value of the global variable tidb_enable_telemetry. -See PingCAP privacy policy for details: https://pingcap.com/en/privacy-policy/. -Imported from v4.0.2. -Optional: Defaults to true

+

Expose the tidb status node port to StatusNodePort +Optional: Defaults to 0

-

TiDBFailureMember

+

TiDBSlowLogTailerSpec

(Appears on: -TiDBStatus) +TiDBSpec)

-

TiDBFailureMember is the tidb failure member information

+

TiDBSlowLogTailerSpec represents an optional log tailer sidecar with TiDB

@@ -10027,35 +11568,55 @@ Optional: Defaults to true

+ + + +
-podName
+ResourceRequirements
+ + +Kubernetes core/v1.ResourceRequirements + + +
+

+(Members of ResourceRequirements are embedded into this type.) +

+
+image
string
+

Image used for slowlog tailer +Deprecated, use TidbCluster.HelperImage instead

-createdAt
+imagePullPolicy
- -Kubernetes meta/v1.Time + +Kubernetes core/v1.PullPolicy
+

ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present +Deprecated, use TidbCluster.HelperImagePullPolicy instead

-

TiDBGroupSpec

+

TiDBSpec

(Appears on: -TiDBGroup) +TiDBGroupSpec, +TidbClusterSpec)

-

TiDBGroupSpec describes the attributes that a user creates on a TiDBGroup

+

TiDBSpec contains details of TiDB members

@@ -10067,133 +11628,193 @@ Kubernetes meta/v1.Time + + + + + + + + - -
-TiDBSpec
+ComponentSpec
- -TiDBSpec + +ComponentSpec

-(Members of TiDBSpec are embedded into this type.) +(Members of ComponentSpec are embedded into this type.)

-clusterName
+ResourceRequirements
+ + +Kubernetes core/v1.ResourceRequirements + + +
+

+(Members of ResourceRequirements are embedded into this type.) +

+
+replicas
+ +int32 + +
+

The desired ready replicas

+
+baseImage
string
-

ClusterName describe the target TidbCluster in the same namespace

+(Optional) +

TODO: remove optional after defaulting introduced +Base image of the component, image tag is now allowed during validation

-

TiDBGroupStatus

-

-(Appears on: -TiDBGroup) -

-

-

Most recently observed status of the TiDBGroup

-

- - - - + + + + + + + + + + - - - -
FieldDescription +service
+ + +TiDBServiceSpec + + +
+(Optional) +

Service defines a Kubernetes service of TiDB cluster. +Optional: No kubernetes service will be created by default.

+
+binlogEnabled
+ +bool + +
+(Optional) +

Whether enable TiDB Binlog, it is encouraged to not set this field and rely on the default behavior +Optional: Defaults to true if PumpSpec is non-nil, otherwise false

+
+maxFailoverCount
+ +int32 + +
+(Optional) +

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover +Optional: Defaults to 3

+
-TiDBStatus
+separateSlowLog
- -TiDBStatus - +bool
-

-(Members of TiDBStatus are embedded into this type.) -

+(Optional) +

Whether output the slow log in an separate sidecar container +Optional: Defaults to true

-

TiDBMember

-

-(Appears on: -TiDBStatus) -

-

-

TiDBMember is TiDB member

-

- - - - + + - -
FieldDescription +tlsClient
+ + +TiDBTLSClient + + +
+(Optional) +

Whether enable the TLS connection between the SQL client and TiDB server +Optional: Defaults to nil

+
-name
+slowLogTailer
-string + +TiDBSlowLogTailerSpec +
+(Optional) +

The spec of the slow log tailer sidecar

-health
+plugins
-bool +[]string
+(Optional) +

Plugins is a list of plugins that are loaded by TiDB server, empty means plugin disabled

-lastTransitionTime
+config
- -Kubernetes meta/v1.Time + +TiDBConfig
-

Last time the health transitioned from one to another.

+(Optional) +

Config is the Configuration of tidb-servers

-node
+lifecycle
-string + +Kubernetes core/v1.Lifecycle +
-

Node hosting pod of this TiDB member.

+(Optional) +

Lifecycle describes actions that the management system should take in response to container lifecycle +events. For the PostStart and PreStop lifecycle handlers, management of the container blocks +until the action is complete, unless the container process fails, in which case the handler is aborted.

-

TiDBServiceSpec

+

TiDBStatus

(Appears on: -TiDBSpec) +TiDBGroupStatus, +TidbClusterStatus)

+

TiDBStatus is TiDB status

@@ -10205,10 +11826,10 @@ string @@ -10217,67 +11838,69 @@ ServiceSpec + + + +
-ServiceSpec
+phase
- -ServiceSpec + +MemberPhase
-externalTrafficPolicy
+statefulSet
- -Kubernetes core/v1.ServiceExternalTrafficPolicyType + +Kubernetes apps/v1.StatefulSetStatus
-(Optional) -

ExternalTrafficPolicy of the service -Optional: Defaults to omitted

-exposeStatus
+members
-bool + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBMember +
-(Optional) -

Whether expose the status port -Optional: Defaults to true

-mysqlNodePort
+failureMembers
-int + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBFailureMember +
-(Optional) -

Expose the tidb cluster mysql port to MySQLNodePort -Optional: Defaults to 0

-statusNodePort
+resignDDLOwnerRetryCount
-int +int32 + +
+
+image
+ +string
-(Optional) -

Expose the tidb status node port to StatusNodePort -Optional: Defaults to 0

-

TiDBSlowLogTailerSpec

+

TiDBTLSClient

(Appears on: TiDBSpec)

-

TiDBSlowLogTailerSpec represents an optional log tailer sidecar with TiDB

+

TiDBTLSClient can enable TLS connection between TiDB server and MySQL client

@@ -10289,55 +11912,70 @@ Optional: Defaults to 0

+ +
-ResourceRequirements
+enabled
- -Kubernetes core/v1.ResourceRequirements - +bool
-

-(Members of ResourceRequirements are embedded into this type.) -

+(Optional) +

When enabled, TiDB will accept TLS encrypted connections from MySQL client +The steps to enable this feature: +1. Generate a TiDB server-side certificate and a client-side certifiacete for the TiDB cluster. +There are multiple ways to generate certificates: +- user-provided certificates: https://pingcap.com/docs/stable/how-to/secure/enable-tls-clients/ +- use the K8s built-in certificate signing system signed certificates: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/ +- or use cert-manager signed certificates: https://cert-manager.io/ +2. Create a K8s Secret object which contains the TiDB server-side certificate created above. +The name of this Secret must be: -tidb-server-secret. +kubectl create secret generic -tidb-server-secret –namespace= –from-file=tls.crt= –from-file=tls.key= –from-file=ca.crt= +3. Create a K8s Secret object which contains the TiDB client-side certificate created above which will be used by TiDB Operator. +The name of this Secret must be: -tidb-client-secret. +kubectl create secret generic -tidb-client-secret –namespace= –from-file=tls.crt= –from-file=tls.key= –from-file=ca.crt= +4. Set Enabled to true.

+

TiFlashConfig

+

+(Appears on: +TiFlashSpec) +

+

+

TiFlashConfig is the configuration of TiFlash.

+

+ + - - + + + +
-image
- -string - -
-

Image used for slowlog tailer -Deprecated, use TidbCluster.HelperImage instead

-
FieldDescription
-imagePullPolicy
+config
- -Kubernetes core/v1.PullPolicy + +CommonConfig
-

ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present -Deprecated, use TidbCluster.HelperImagePullPolicy instead

+(Optional) +

commonConfig is the Configuration of TiFlash process

-

TiDBSpec

+

TiFlashSpec

(Appears on: -TiDBGroupSpec, TidbClusterSpec)

-

TiDBSpec contains details of TiDB members

+

TiFlashSpec contains details of TiFlash members

@@ -10379,6 +12017,17 @@ Kubernetes core/v1.ResourceRequirements + + + + + + + + + + + + + + + + + +
+serviceAccount
+ +string + +
+

Specify a Service Account for TiFlash

+
replicas
int32 @@ -10397,145 +12046,201 @@ string
(Optional) -

TODO: remove optional after defaulting introduced -Base image of the component, image tag is now allowed during validation

+

Base image of the component, image tag is now allowed during validation

+
+privileged
+ +bool + +
+(Optional) +

Whether create the TiFlash container in privileged mode, it is highly discouraged to enable this in +critical environment. +Optional: defaults to false

+
+maxFailoverCount
+ +int32 + +
+(Optional) +

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover +Optional: Defaults to 3

+
+storageClaims
+ + +[]StorageClaim + + +
+

The persistent volume claims of the TiFlash data storages. +TiFlash supports multiple disks.

-service
+config
- -TiDBServiceSpec + +TiFlashConfig
(Optional) -

Service defines a Kubernetes service of TiDB cluster. -Optional: No kubernetes service will be created by default.

+

Config is the Configuration of TiFlash

-binlogEnabled
+logTailer
-bool + +LogTailerSpec +
(Optional) -

Whether enable TiDB Binlog, it is encouraged to not set this field and rely on the default behavior -Optional: Defaults to true if PumpSpec is non-nil, otherwise false

+

LogTailer is the configurations of the log tailers for TiFlash

+

TiKVBackupConfig

+

+(Appears on: +TiKVConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-maxFailoverCount
+num-threads
-int32 +int64
(Optional) -

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover -Optional: Defaults to 3

+

TiKVBlockCacheConfig

+

+(Appears on: +TiKVStorageConfig) +

+

+

TiKVBlockCacheConfig is the config of a block cache

+

+ + + + + + + +
FieldDescription
-separateSlowLog
+shared
bool
(Optional) -

Whether output the slow log in an separate sidecar container -Optional: Defaults to true

+

Optional: Defaults to true

-tlsClient
+capacity
- -TiDBTLSClient - +string
(Optional) -

Whether enable the TLS connection between the SQL client and TiDB server -Optional: Defaults to nil

-slowLogTailer
+num-shard-bits
- -TiDBSlowLogTailerSpec - +int64
(Optional) -

The spec of the slow log tailer sidecar

-plugins
+strict-capacity-limit
-[]string +bool
(Optional) -

Plugins is a list of plugins that are loaded by TiDB server, empty means plugin disabled

-config
+high-pri-pool-ratio
- -TiDBConfig - +float64
(Optional) -

Config is the Configuration of tidb-servers

-lifecycle
+memory-allocator
- -Kubernetes core/v1.Lifecycle - +string
(Optional) -

Lifecycle describes actions that the management system should take in response to container lifecycle -events. For the PostStart and PreStop lifecycle handlers, management of the container blocks -until the action is complete, unless the container process fails, in which case the handler is aborted.

-

TiDBStatus

+

TiKVCfConfig

(Appears on: -TiDBGroupStatus, -TidbClusterStatus) +TiKVDbConfig, +TiKVRaftDBConfig)

-

TiDBStatus is TiDB status

+

TiKVCfConfig is the config of a cf

@@ -10547,361 +12252,251 @@ until the action is complete, unless the container process fails, in which case - -
-phase
+block-size
- -MemberPhase - +string
+(Optional)
-statefulSet
+block-cache-size
- -Kubernetes apps/v1.StatefulSetStatus - +string
+(Optional)
-members
+disable-block-cache
- -map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBMember - +bool
+(Optional)
-failureMembers
+cache-index-and-filter-blocks
- -map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBFailureMember - +bool
+(Optional)
-resignDDLOwnerRetryCount
+pin-l0-filter-and-index-blocks
-int32 +bool
+(Optional)
-image
+use-bloom-filter
-string +bool
+(Optional)
-

TiDBTLSClient

-

-(Appears on: -TiDBSpec) -

-

-

TiDBTLSClient can enable TLS connection between TiDB server and MySQL client

-

- - - - - - - - - -
FieldDescription
-enabled
+optimize-filters-for-hits
bool
(Optional) -

When enabled, TiDB will accept TLS encrypted connections from MySQL client -The steps to enable this feature: -1. Generate a TiDB server-side certificate and a client-side certifiacete for the TiDB cluster. -There are multiple ways to generate certificates: -- user-provided certificates: https://pingcap.com/docs/stable/how-to/secure/enable-tls-clients/ -- use the K8s built-in certificate signing system signed certificates: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/ -- or use cert-manager signed certificates: https://cert-manager.io/ -2. Create a K8s Secret object which contains the TiDB server-side certificate created above. -The name of this Secret must be: -tidb-server-secret. -kubectl create secret generic -tidb-server-secret –namespace= –from-file=tls.crt= –from-file=tls.key= –from-file=ca.crt= -3. Create a K8s Secret object which contains the TiDB client-side certificate created above which will be used by TiDB Operator. -The name of this Secret must be: -tidb-client-secret. -kubectl create secret generic -tidb-client-secret –namespace= –from-file=tls.crt= –from-file=tls.key= –from-file=ca.crt= -4. Set Enabled to true.

-

TiFlashConfig

-

-(Appears on: -TiFlashSpec) -

-

-

TiFlashConfig is the configuration of TiFlash.

-

- - - - + + - - - -
FieldDescription +whole-key-filtering
+ +bool + +
+(Optional) +
-config
+bloom-filter-bits-per-key
- -CommonConfig - +int64
(Optional) -

commonConfig is the Configuration of TiFlash process

-

TiFlashSpec

-

-(Appears on: -TidbClusterSpec) -

-

-

TiFlashSpec contains details of TiFlash members

-

- - - - + + - - - -
FieldDescription +block-based-bloom-filter
+ +bool + +
+(Optional) +
-ComponentSpec
+read-amp-bytes-per-bit
- -ComponentSpec - +int64
-

-(Members of ComponentSpec are embedded into this type.) -

+(Optional)
-ResourceRequirements
- - -Kubernetes core/v1.ResourceRequirements - +compression-per-level
+ +[]string
-

-(Members of ResourceRequirements are embedded into this type.) -

+(Optional)
-serviceAccount
+write-buffer-size
string
-

Specify a Service Account for TiFlash

+(Optional)
-replicas
+max-write-buffer-number
-int32 +int64
-

The desired ready replicas

+(Optional)
-baseImage
+min-write-buffer-number-to-merge
-string +int64
(Optional) -

Base image of the component, image tag is now allowed during validation

-privileged
+max-bytes-for-level-base
-bool +string
(Optional) -

Whether create the TiFlash container in privileged mode, it is highly discouraged to enable this in -critical environment. -Optional: defaults to false

-maxFailoverCount
+target-file-size-base
-int32 +string
(Optional) -

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover -Optional: Defaults to 3

-storageClaims
+level0-file-num-compaction-trigger
- -[]StorageClaim - +int64
-

The persistent volume claims of the TiFlash data storages. -TiFlash supports multiple disks.

+(Optional)
-config
+level0-slowdown-writes-trigger
- -TiFlashConfig - +int64
(Optional) -

Config is the Configuration of TiFlash

-logTailer
+level0-stop-writes-trigger
- -LogTailerSpec - +int64
(Optional) -

LogTailer is the configurations of the log tailers for TiFlash

-

TiKVBackupConfig

-

-(Appears on: -TiKVConfig) -

-

-

- - - - - - - - - -
FieldDescription
-num-threads
+max-compaction-bytes
-int64 +string
(Optional)
-

TiKVBlockCacheConfig

-

-(Appears on: -TiKVStorageConfig) -

-

-

TiKVBlockCacheConfig is the config of a block cache

-

- - - - - - - - - -
FieldDescription
-shared
+compaction-pri
-bool +int64
(Optional) -

Optional: Defaults to true

-capacity
+dynamic-level-bytes
-string +bool
@@ -10910,7 +12505,7 @@ string
-num-shard-bits
+num-levels
int64 @@ -10921,9 +12516,9 @@ int64
-strict-capacity-limit
+max-bytes-for-level-multiplier
-bool +int64
@@ -10932,9 +12527,9 @@ bool
-high-pri-pool-ratio
+compaction-style
-float64 +int64
@@ -10943,37 +12538,18 @@ float64
-memory-allocator
+disable-auto-compactions
-string +bool
(Optional)
-

TiKVCfConfig

-

-(Appears on: -TiKVDbConfig, -TiKVRaftDBConfig) -

-

-

TiKVCfConfig is the config of a cf

-

- - - - - - - - + +
FieldDescription
-block-size
+soft-pending-compaction-bytes-limit
string @@ -10984,7 +12560,7 @@ string
-block-cache-size
+hard-pending-compaction-bytes-limit
string @@ -10995,7 +12571,7 @@ string
-disable-block-cache
+force-consistency-checks
bool @@ -11006,9 +12582,9 @@ bool
-cache-index-and-filter-blocks
+prop-size-index-distance
-bool +int64
@@ -11017,9 +12593,9 @@ bool
-pin-l0-filter-and-index-blocks
+prop-keys-index-distance
-bool +int64
@@ -11028,7 +12604,7 @@ bool
-use-bloom-filter
+enable-doubly-skiplist
bool @@ -11039,174 +12615,243 @@ bool
-optimize-filters-for-hits
+titan
-bool + +TiKVTitanCfConfig +
(Optional)
+

TiKVClient

+

+(Appears on: +TiDBConfig) +

+

+

TiKVClient is the config for tikv client.

+

+ + + + + + + + + +
FieldDescription
-whole-key-filtering
+grpc-connection-count
-bool +uint
(Optional) +

GrpcConnectionCount is the max gRPC connections that will be established +with each tikv-server. +Optional: Defaults to 16

-bloom-filter-bits-per-key
+grpc-keepalive-time
-int64 +uint
(Optional) +

After a duration of this time in seconds if the client doesn’t see any activity it pings +the server to see if the transport is still alive. +Optional: Defaults to 10

-block-based-bloom-filter
+grpc-keepalive-timeout
-bool +uint
(Optional) +

After having pinged for keepalive check, the client waits for a duration of Timeout in seconds +and if no activity is seen even after that the connection is closed. +Optional: Defaults to 3

-read-amp-bytes-per-bit
+commit-timeout
-int64 +string
(Optional) +

CommitTimeout is the max time which command ‘commit’ will wait. +Optional: Defaults to 41s

-compression-per-level
+max-txn-time-use
-[]string +uint
(Optional) +

MaxTxnTimeUse is the max time a Txn may use (in seconds) from its startTS to commitTS. +Optional: Defaults to 590

-write-buffer-size
+max-batch-size
-string +uint
(Optional) +

MaxBatchSize is the max batch size when calling batch commands API. +Optional: Defaults to 128

-max-write-buffer-number
+overload-threshold
-int64 +uint
(Optional) +

If TiKV load is greater than this, TiDB will wait for a while to avoid little batch. +Optional: Defaults to 200

-min-write-buffer-number-to-merge
+max-batch-wait-time
-int64 +time.Duration
(Optional) +

MaxBatchWaitTime in nanosecond is the max wait time for batch. +Optional: Defaults to 0

-max-bytes-for-level-base
+batch-wait-size
-string +uint
(Optional) +

BatchWaitSize is the max wait size for batch. +Optional: Defaults to 8

-target-file-size-base
+region-cache-ttl
-string +uint
(Optional) +

If a Region has not been accessed for more than the given duration (in seconds), it +will be reloaded from the PD. +Optional: Defaults to 600

-level0-file-num-compaction-trigger
+store-limit
int64
(Optional) +

If a store has been up to the limit, it will return error for successive request to +prevent the store occupying too much token in dispatching level. +Optional: Defaults to 0

-level0-slowdown-writes-trigger
+store-liveness-timeout
-int64 +string
(Optional) +

StoreLivenessTimeout is the timeout for store liveness check request.

-level0-stop-writes-trigger
+copr-cache
-int64 + +CoprocessorCache +
(Optional)
+

TiKVConfig

+

+(Appears on: +TiKVSpec) +

+

+

TiKVConfig is the configuration of TiKV.

+

+ + + + + + + + @@ -11347,206 +13003,211 @@ TiKVTitanCfConfig (Optional) - -
FieldDescription
-max-compaction-bytes
+log-level
string
(Optional) +

Optional: Defaults to info

-compaction-pri
+log-file
-int64 +string
@@ -11215,9 +12860,9 @@ int64
-dynamic-level-bytes
+slow-log-file
-bool +string
@@ -11226,9 +12871,9 @@ bool
-num-levels
+slow-log-threshold
-int64 +string
@@ -11237,20 +12882,21 @@ int64
-max-bytes-for-level-multiplier
+log-rotation-timespan
-int64 +string
(Optional) +

Optional: Defaults to 24h

-compaction-style
+log-rotation-size
-int64 +string
@@ -11259,9 +12905,9 @@ int64
-disable-auto-compactions
+refresh-config-interval
-bool +string
@@ -11270,9 +12916,9 @@ bool
-soft-pending-compaction-bytes-limit
+panic-when-unexpected-key-or-data
-string +bool
@@ -11281,9 +12927,11 @@ string
-hard-pending-compaction-bytes-limit
+server
-string + +TiKVServerConfig +
@@ -11292,9 +12940,11 @@ string
-force-consistency-checks
+storage
-bool + +TiKVStorageConfig +
@@ -11303,9 +12953,11 @@ bool
-prop-size-index-distance
+raftstore
-int64 + +TiKVRaftstoreConfig +
@@ -11314,9 +12966,11 @@ int64
-prop-keys-index-distance
+rocksdb
-int64 + +TiKVDbConfig +
@@ -11325,9 +12979,11 @@ int64
-enable-doubly-skiplist
+coprocessor
-bool + +TiKVCoprocessorConfig +
@@ -11336,10 +12992,10 @@ bool
-titan
+readpool
- -TiKVTitanCfConfig + +TiKVReadPoolConfig
-

TiKVClient

-

-(Appears on: -TiDBConfig) -

-

-

TiKVClient is the config for tikv client.

-

- - - - - - - - + +
FieldDescription
-grpc-connection-count
+raftdb
-uint + +TiKVRaftDBConfig +
(Optional) -

GrpcConnectionCount is the max gRPC connections that will be established -with each tikv-server. -Optional: Defaults to 16

-grpc-keepalive-time
+import
-uint + +TiKVImportConfig +
(Optional) -

After a duration of this time in seconds if the client doesn’t see any activity it pings -the server to see if the transport is still alive. -Optional: Defaults to 10

-grpc-keepalive-timeout
+gc
-uint + +TiKVGCConfig +
(Optional) -

After having pinged for keepalive check, the client waits for a duration of Timeout in seconds -and if no activity is seen even after that the connection is closed. -Optional: Defaults to 3

-commit-timeout
+pd
-string + +TiKVPDConfig +
(Optional) -

CommitTimeout is the max time which command ‘commit’ will wait. -Optional: Defaults to 41s

-max-txn-time-use
+security
-uint + +TiKVSecurityConfig +
(Optional) -

MaxTxnTimeUse is the max time a Txn may use (in seconds) from its startTS to commitTS. -Optional: Defaults to 590

-max-batch-size
+pessimistic-txn
-uint + +TiKVPessimisticTxn +
(Optional) -

MaxBatchSize is the max batch size when calling batch commands API. -Optional: Defaults to 128

-overload-threshold
+backup
-uint + +TiKVBackupConfig +
(Optional) -

If TiKV load is greater than this, TiDB will wait for a while to avoid little batch. -Optional: Defaults to 200

+

TiKVCoprocessorConfig

+

+(Appears on: +TiKVConfig) +

+

+

TiKVCoprocessorConfig is the configuration of TiKV Coprocessor component.

+

+ + + + + + + +
FieldDescription
-max-batch-wait-time
+split-region-on-table
-time.Duration +bool
-(Optional) -

MaxBatchWaitTime in nanosecond is the max wait time for batch. -Optional: Defaults to 0

+

When it is set to true, TiKV will try to split a Region with table prefix if that Region +crosses tables. +It is recommended to turn off this option if there will be a large number of tables created. +Optional: Defaults to false +optional

-batch-wait-size
+batch-split-limit
-uint +int64
-(Optional) -

BatchWaitSize is the max wait size for batch. -Optional: Defaults to 8

+

One split check produces several split keys in batch. This config limits the number of produced +split keys in one batch. +optional

-region-cache-ttl
+region-max-size
-uint +string
-(Optional) -

If a Region has not been accessed for more than the given duration (in seconds), it -will be reloaded from the PD. -Optional: Defaults to 600

+

When Region [a,e) size exceeds region-max-size, it will be split into several Regions [a,b), +[b,c), [c,d), [d,e) and the size of [a,b), [b,c), [c,d) will be region-split-size (or a +little larger). See also: region-split-size +Optional: Defaults to 144MB +optional

-store-limit
+region-split-size
-int64 +string
-(Optional) -

If a store has been up to the limit, it will return error for successive request to -prevent the store occupying too much token in dispatching level. -Optional: Defaults to 0

+

When Region [a,e) size exceeds region-max-size, it will be split into several Regions [a,b), +[b,c), [c,d), [d,e) and the size of [a,b), [b,c), [c,d) will be region-split-size (or a +little larger). See also: region-max-size +Optional: Defaults to 96MB +optional

-store-liveness-timeout
+region-max-keys
-string +int64
-(Optional) -

StoreLivenessTimeout is the timeout for store liveness check request.

+

When the number of keys in Region [a,e) exceeds the region-max-keys, it will be split into +several Regions [a,b), [b,c), [c,d), [d,e) and the number of keys in [a,b), [b,c), [c,d) will be +region-split-keys. See also: region-split-keys +Optional: Defaults to 1440000 +optional

-copr-cache
+region-split-keys
- -CoprocessorCache - +int64
-(Optional) +

When the number of keys in Region [a,e) exceeds the region-max-keys, it will be split into +several Regions [a,b), [b,c), [c,d), [d,e) and the number of keys in [a,b), [b,c), [c,d) will be +region-split-keys. See also: region-max-keys +Optional: Defaults to 960000 +optional

-

TiKVConfig

+

TiKVCoprocessorReadPoolConfig

(Appears on: -TiKVSpec) +TiKVReadPoolConfig)

-

TiKVConfig is the configuration of TiKV.

@@ -11558,114 +13219,135 @@ CoprocessorCache + +
-log-level
+high-concurrency
-string +int64
(Optional) -

Optional: Defaults to info

+

Optional: Defaults to 8

-log-file
+normal-concurrency
-string +int64
(Optional) +

Optional: Defaults to 8

-slow-log-file
+low-concurrency
-string +int64
(Optional) +

Optional: Defaults to 8

-slow-log-threshold
+max-tasks-per-worker-high
-string +int64
(Optional) +

Optional: Defaults to 2000

-log-rotation-timespan
+max-tasks-per-worker-normal
-string +int64
(Optional) -

Optional: Defaults to 24h

+

Optional: Defaults to 2000

-log-rotation-size
+max-tasks-per-worker-low
-string +int64
(Optional) +

Optional: Defaults to 2000

-refresh-config-interval
+stack-size
string
(Optional) +

Optional: Defaults to 10MB

-panic-when-unexpected-key-or-data
+use-unified-pool
bool
(Optional) +

Optional: Defaults to true

+

TiKVDbConfig

+

+(Appears on: +TiKVConfig) +

+

+

TiKVDbConfig is the rocksdb config.

+

+ + + + + + + + + + + + - -
FieldDescription
-server
+wal-recovery-mode
- -TiKVServerConfig - +int64
(Optional) +

Optional: Defaults to 2

-storage
+wal-ttl-seconds
- -TiKVStorageConfig - +int64
@@ -11674,11 +13356,9 @@ TiKVStorageConfig
-raftstore
+wal-size-limit
- -TiKVRaftstoreConfig - +string
@@ -11687,102 +13367,105 @@ TiKVRaftstoreConfig
-rocksdb
+max-total-wal-size
- -TiKVDbConfig - +string
(Optional) +

Optional: Defaults to 4GB

-coprocessor
+max-background-jobs
- -TiKVCoprocessorConfig - +int64
(Optional) +

Optional: Defaults to 8

-readpool
+max-manifest-file-size
- -TiKVReadPoolConfig - +string
(Optional) +

Optional: Defaults to 128MB

-raftdb
+create-if-missing
- -TiKVRaftDBConfig - +bool
(Optional) +

Optional: Defaults to true

-import
+max-open-files
- -TiKVImportConfig - +int64
(Optional) +

Optional: Defaults to 40960

-gc
+enable-statistics
- -TiKVGCConfig - +bool
(Optional) +

Optional: Defaults to true

-pd
+stats-dump-period
- -TiKVPDConfig - +string + +
+(Optional) +

Optional: Defaults to 10m

+
+compaction-readahead-size
+ +string
(Optional) +

Optional: Defaults to 0

-security
+info-log-max-size
- -TiKVSecurityConfig - +string
@@ -11791,11 +13474,9 @@ TiKVSecurityConfig
-pessimistic-txn
+info-log-roll-time
- -TiKVPessimisticTxn - +string
@@ -11804,245 +13485,195 @@ TiKVPessimisticTxn
-backup
+info-log-keep-log-file-num
- -TiKVBackupConfig - +int64
(Optional)
-

TiKVCoprocessorConfig

-

-(Appears on: -TiKVConfig) -

-

-

TiKVCoprocessorConfig is the configuration of TiKV Coprocessor component.

-

- - - - + + - - - -
FieldDescription +info-log-dir
+ +string + +
+(Optional) +
-split-region-on-table
+rate-bytes-per-sec
-bool +string
-

When it is set to true, TiKV will try to split a Region with table prefix if that Region -crosses tables. -It is recommended to turn off this option if there will be a large number of tables created. -Optional: Defaults to false -optional

+(Optional)
-batch-split-limit
+rate-limiter-mode
int64
-

One split check produces several split keys in batch. This config limits the number of produced -split keys in one batch. -optional

+(Optional)
-region-max-size
+auto-tuned
-string +bool
-

When Region [a,e) size exceeds region-max-size, it will be split into several Regions [a,b), -[b,c), [c,d), [d,e) and the size of [a,b), [b,c), [c,d) will be region-split-size (or a -little larger). See also: region-split-size -Optional: Defaults to 144MB -optional

+(Optional)
-region-split-size
+bytes-per-sync
string
-

When Region [a,e) size exceeds region-max-size, it will be split into several Regions [a,b), -[b,c), [c,d), [d,e) and the size of [a,b), [b,c), [c,d) will be region-split-size (or a -little larger). See also: region-max-size -Optional: Defaults to 96MB -optional

+(Optional)
-region-max-keys
+wal-bytes-per-sync
-int64 +string
-

When the number of keys in Region [a,e) exceeds the region-max-keys, it will be split into -several Regions [a,b), [b,c), [c,d), [d,e) and the number of keys in [a,b), [b,c), [c,d) will be -region-split-keys. See also: region-split-keys -Optional: Defaults to 1440000 -optional

+(Optional)
-region-split-keys
+max-sub-compactions
int64
-

When the number of keys in Region [a,e) exceeds the region-max-keys, it will be split into -several Regions [a,b), [b,c), [c,d), [d,e) and the number of keys in [a,b), [b,c), [c,d) will be -region-split-keys. See also: region-max-keys -Optional: Defaults to 960000 -optional

+(Optional) +

Optional: Defaults to 3

-

TiKVCoprocessorReadPoolConfig

-

-(Appears on: -TiKVReadPoolConfig) -

-

-

- - - - - - - -
FieldDescription
-high-concurrency
+writable-file-max-buffer-size
-int64 +string
(Optional) -

Optional: Defaults to 8

-normal-concurrency
+use-direct-io-for-flush-and-compaction
-int64 +bool
(Optional) -

Optional: Defaults to 8

-low-concurrency
+enable-pipelined-write
-int64 +bool
(Optional) -

Optional: Defaults to 8

-max-tasks-per-worker-high
+defaultcf
-int64 + +TiKVCfConfig +
(Optional) -

Optional: Defaults to 2000

-max-tasks-per-worker-normal
+writecf
-int64 + +TiKVCfConfig +
(Optional) -

Optional: Defaults to 2000

-max-tasks-per-worker-low
+lockcf
-int64 + +TiKVCfConfig +
(Optional) -

Optional: Defaults to 2000

-stack-size
+raftcf
-string + +TiKVCfConfig +
(Optional) -

Optional: Defaults to 10MB

-use-unified-pool
+titan
-bool + +TiKVTitanDBConfig +
(Optional) -

Optional: Defaults to true

-

TiKVDbConfig

-

-(Appears on: -TiKVConfig) -

+

TiKVEncryptionConfig

-

TiKVDbConfig is the rocksdb config.

@@ -12054,161 +13685,247 @@ bool + +
-wal-recovery-mode
+data-encryption-method
-int64 +string
-(Optional) -

Optional: Defaults to 2

+

Encrypyion method, use data key encryption raw rocksdb data +Possible values: plaintext, aes128-ctr, aes192-ctr, aes256-ctr +Optional: Default to plaintext +optional

-wal-ttl-seconds
+data-key-rotation-period
-int64 +string
-(Optional) +

The frequency of datakey rotation, It managered by tikv +Optional: default to 7d +optional

-wal-size-limit
+master-key
-string + +TiKVMasterKeyConfig +
-(Optional) +

Master key config

-max-total-wal-size
+previous-master-key
-string + +TiKVMasterKeyConfig +
-(Optional) -

Optional: Defaults to 4GB

+

Previous master key config +It used in master key rotation, the data key should decryption by previous master key and then encrypytion by new master key

+

TiKVFailureStore

+

+(Appears on: +TiKVStatus) +

+

+

TiKVFailureStore is the tikv failure store information

+

+ + - - + + + + + +
-max-background-jobs
- -int64 - -
-(Optional) -

Optional: Defaults to 8

-
FieldDescription
-max-manifest-file-size
+podName
string
-(Optional) -

Optional: Defaults to 128MB

-create-if-missing
+storeID
-bool +string
-(Optional) -

Optional: Defaults to true

-max-open-files
+createdAt
-int64 + +Kubernetes meta/v1.Time +
-(Optional) -

Optional: Defaults to 40960

+

TiKVGCConfig

+

+(Appears on: +TiKVConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-enable-statistics
+ batch-keys
-bool +int64
(Optional) -

Optional: Defaults to true

+

Optional: Defaults to 512

-stats-dump-period
+ max-write-bytes-per-sec
string
(Optional) -

Optional: Defaults to 10m

+

TiKVGroupSpec

+

+(Appears on: +TiKVGroup) +

+

+

TiKVGroupSpec describes the attributes that a user creates on a TiKVGroup

+

+ + + + + + + + + +
FieldDescription
-compaction-readahead-size
+TiKVSpec
-string + +TiKVSpec +
-(Optional) -

Optional: Defaults to 0

+

+(Members of TiKVSpec are embedded into this type.) +

-info-log-max-size
+clusterName
string
-(Optional) +

ClusterName describe the target TidbCluster in the same namespace

+

TiKVGroupStatus

+

+(Appears on: +TiKVGroup) +

+

+

Most recently observed status of the TiKVGroup

+

+ + + + + + + + + +
FieldDescription
-info-log-roll-time
+TiKVStatus
-string + +TiKVStatus +
-(Optional) +

+(Members of TiKVStatus are embedded into this type.) +

+

TiKVImportConfig

+

+(Appears on: +TiKVConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-info-log-keep-log-file-num
+import-dir
-int64 +string
@@ -12217,9 +13934,9 @@ int64
-info-log-dir
+num-threads
-string +int64
@@ -12228,9 +13945,9 @@ string
-rate-bytes-per-sec
+num-import-jobs
-string +int64
@@ -12239,7 +13956,7 @@ string
-rate-limiter-mode
+num-import-sst-jobs
int64 @@ -12250,9 +13967,9 @@ int64
-auto-tuned
+max-prepare-duration
-bool +string
@@ -12261,7 +13978,7 @@ bool
-bytes-per-sync
+region-split-size
string @@ -12272,9 +13989,9 @@ string
-wal-bytes-per-sync
+stream-channel-window
-string +int64
@@ -12283,19 +14000,18 @@ string
-max-sub-compactions
+max-open-engines
int64
(Optional) -

Optional: Defaults to 3

-writable-file-max-buffer-size
+upload-speed-limit
string @@ -12304,96 +14020,150 @@ string (Optional)
+

TiKVMasterKeyConfig

+

+(Appears on: +TiKVEncryptionConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-use-direct-io-for-flush-and-compaction
+type
-bool +string
-(Optional) +

Use KMS encryption or use file encryption, possible values: kms, file +If set to kms, kms MasterKeyKMSConfig should be filled, if set to file MasterKeyFileConfig should be filled +optional

-enable-pipelined-write
+MasterKeyFileConfig
-bool + +MasterKeyFileConfig +
-(Optional) +

+(Members of MasterKeyFileConfig are embedded into this type.) +

+

Master key file config +If the type set to file, this config should be filled

-defaultcf
+MasterKeyKMSConfig
- -TiKVCfConfig + +MasterKeyKMSConfig
-(Optional) +

+(Members of MasterKeyKMSConfig are embedded into this type.) +

+

Master key KMS config +If the type set to kms, this config should be filled

+

TiKVPDConfig

+

+(Appears on: +TiKVConfig) +

+

+

+ + + + + + + +
FieldDescription
-writecf
+endpoints
- -TiKVCfConfig - +[]string
(Optional) +

The PD endpoints for the client.

+

Default is empty.

-lockcf
+retry-interval
- -TiKVCfConfig - +string
(Optional) +

The interval at which to retry a PD connection initialization.

+

Default is 300ms. +Optional: Defaults to 300ms

-raftcf
+retry-max-count
- -TiKVCfConfig - +int64
(Optional) +

The maximum number of times to retry a PD connection initialization.

+

Default is isize::MAX, represented by -1. +Optional: Defaults to -1

-titan
+retry-log-every
- -TiKVTitanDBConfig - +int64
(Optional) +

If the client observes the same error message on retry, it can repeat the message only +every n times.

+

Default is 10. Set to 1 to disable this feature. +Optional: Defaults to 10

-

TiKVEncryptionConfig

+

TiKVPessimisticTxn

+

+(Appears on: +TiKVConfig) +

@@ -12406,67 +14176,62 @@ TiKVTitanDBConfig
-data-encryption-method
+enabled
-string +bool
-

Encrypyion method, use data key encryption raw rocksdb data -Possible values: plaintext, aes128-ctr, aes192-ctr, aes256-ctr -Optional: Default to plaintext -optional

+(Optional)
-data-key-rotation-period
+wait-for-lock-timeout
string
-

The frequency of datakey rotation, It managered by tikv -Optional: default to 7d -optional

+(Optional) +

The default and maximum delay before responding to TiDB when pessimistic +transactions encounter locks

-master-key
+wake-up-delay-duration
- -TiKVMasterKeyConfig - +string
-

Master key config

+(Optional) +

If more than one transaction is waiting for the same lock, only the one with smallest +start timestamp will be waked up immediately when the lock is released. Others will +be waked up after wake_up_delay_duration to reduce contention and make the oldest +one more likely acquires the lock.

-previous-master-key
+pipelined
- -TiKVMasterKeyConfig - +bool
-

Previous master key config -It used in master key rotation, the data key should decryption by previous master key and then encrypytion by new master key

+(Optional)
-

TiKVFailureStore

+

TiKVRaftDBConfig

(Appears on: -TiKVStatus) +TiKVConfig)

-

TiKVFailureStore is the tikv failure store information

@@ -12478,68 +14243,73 @@ It used in master key rotation, the data key should decryption by previous maste - -
-podName
+wal-recovery-mode
string
+(Optional)
-storeID
+wal-dir
string
+(Optional)
-createdAt
+wal-ttl-seconds
- -Kubernetes meta/v1.Time - +int64
+(Optional)
-

TiKVGCConfig

-

-(Appears on: -TiKVConfig) -

-

-

- - - - + + - - + + + + - -
FieldDescription +wal-size-limit
+ +string + +
+(Optional) +
- batch-keys
+max-total-wal-size
+ +string + +
+(Optional) +
+max-background-jobs
int64
(Optional) -

Optional: Defaults to 512

- max-write-bytes-per-sec
+max-manifest-file-size
string @@ -12548,103 +14318,64 @@ string (Optional)
-

TiKVGroupSpec

-

-(Appears on: -TiKVGroup) -

-

-

TiKVGroupSpec describes the attributes that a user creates on a TiKVGroup

-

- - - - + + - - + + + + - -
FieldDescription +create-if-missing
+ +bool + +
+(Optional) +
-TiKVSpec
+max-open-files
- -TiKVSpec - +int64 + +
+(Optional) +
+enable-statistics
+ +bool
-

-(Members of TiKVSpec are embedded into this type.) -

+(Optional)
-clusterName
+stats-dump-period
string
-

ClusterName describe the target TidbCluster in the same namespace

+(Optional)
-

TiKVGroupStatus

-

-(Appears on: -TiKVGroup) -

-

-

Most recently observed status of the TiKVGroup

-

- - - - - - - - - -
FieldDescription
-TiKVStatus
+compaction-readahead-size
- -TiKVStatus - +string
-

-(Members of TiKVStatus are embedded into this type.) -

+(Optional)
-

TiKVImportConfig

-

-(Appears on: -TiKVConfig) -

-

-

- - - - - - - - - -
FieldDescription
-import-dir
+info-log-max-size
string @@ -12655,9 +14386,9 @@ string
-num-threads
+info-log-roll-time
-int64 +string
@@ -12666,7 +14397,7 @@ int64
-num-import-jobs
+info-log-keep-log-file-num
int64 @@ -12677,9 +14408,9 @@ int64
-num-import-sst-jobs
+info-log-dir
-int64 +string
@@ -12688,9 +14419,9 @@ int64
-max-prepare-duration
+max-sub-compactions
-string +int64
@@ -12699,7 +14430,7 @@ string
-region-split-size
+writable-file-max-buffer-size
string @@ -12710,9 +14441,9 @@ string
-stream-channel-window
+use-direct-io-for-flush-and-compaction
-int64 +bool
@@ -12721,9 +14452,9 @@ int64
-max-open-engines
+enable-pipelined-write
-int64 +bool
@@ -12732,87 +14463,59 @@ int64
-upload-speed-limit
+allow-concurrent-memtable-write
-string +bool
(Optional)
-

TiKVMasterKeyConfig

-

-(Appears on: -TiKVEncryptionConfig) -

-

-

- - - - - - - -
FieldDescription
-type
+bytes-per-sync
string
-

Use KMS encryption or use file encryption, possible values: kms, file -If set to kms, kms MasterKeyKMSConfig should be filled, if set to file MasterKeyFileConfig should be filled -optional

+(Optional)
-MasterKeyFileConfig
+wal-bytes-per-sync
- -MasterKeyFileConfig - +string
-

-(Members of MasterKeyFileConfig are embedded into this type.) -

-

Master key file config -If the type set to file, this config should be filled

+(Optional)
-MasterKeyKMSConfig
+defaultcf
- -MasterKeyKMSConfig + +TiKVCfConfig
-

-(Members of MasterKeyKMSConfig are embedded into this type.) -

-

Master key KMS config -If the type set to kms, this config should be filled

+(Optional)
-

TiKVPDConfig

+

TiKVRaftstoreConfig

(Appears on: TiKVConfig)

+

TiKVRaftstoreConfig is the configuration of TiKV raftstore component.

@@ -12824,82 +14527,57 @@ If the type set to kms, this config should be filled

- -
-endpoints
+sync-log
-[]string +bool
(Optional) -

The PD endpoints for the client.

-

Default is empty.

+

true for high reliability, prevent data loss when power failure. +Optional: Defaults to true

-retry-interval
+prevote
-string +bool
(Optional) -

The interval at which to retry a PD connection initialization.

-

Default is 300ms. -Optional: Defaults to 300ms

+

Optional: Defaults to true

-retry-max-count
+raft-base-tick-interval
-int64 +string
(Optional) -

The maximum number of times to retry a PD connection initialization.

-

Default is isize::MAX, represented by -1. -Optional: Defaults to -1

+

raft-base-tick-interval is a base tick interval (ms).

-retry-log-every
+raft-heartbeat-ticks
int64
(Optional) -

If the client observes the same error message on retry, it can repeat the message only -every n times.

-

Default is 10. Set to 1 to disable this feature. -Optional: Defaults to 10

-

TiKVPessimisticTxn

-

-(Appears on: -TiKVConfig) -

-

-

- - - - - - - - - -
FieldDescription
-enabled
+raft-election-timeout-ticks
-bool +int64
@@ -12908,228 +14586,241 @@ bool
-wait-for-lock-timeout
+raft-entry-max-size
string
(Optional) -

The default and maximum delay before responding to TiDB when pessimistic -transactions encounter locks

+

When the entry exceed the max size, reject to propose it. +Optional: Defaults to 8MB

-wake-up-delay-duration
+raft-max-size-per-msg
string
(Optional) -

If more than one transaction is waiting for the same lock, only the one with smallest -start timestamp will be waked up immediately when the lock is released. Others will -be waked up after wake_up_delay_duration to reduce contention and make the oldest -one more likely acquires the lock.

+

Limit the max size of each append message. +Optional: Defaults to 1MB

-pipelined
+raft-max-inflight-msgs
-bool +int64
(Optional) +

Limit the max number of in-flight append messages during optimistic +replication phase. +Optional: Defaults to 256

-

TiKVRaftDBConfig

-

-(Appears on: -TiKVConfig) -

-

-

- - - - - - - - - -
FieldDescription
-wal-recovery-mode
+raft-log-gc-tick-interval
string
(Optional) +

Interval to gc unnecessary raft log (ms). +Optional: Defaults to 10s

-wal-dir
+raft-log-gc-threshold
-string +int64
(Optional) +

A threshold to gc stale raft log, must >= 1. +Optional: Defaults to 50

-wal-ttl-seconds
+raft-log-gc-count-limit
int64
(Optional) +

When entry count exceed this value, gc will be forced trigger. +Optional: Defaults to 72000

-wal-size-limit
+raft-log-gc-size-limit
string
(Optional) +

When the approximate size of raft log entries exceed this value +gc will be forced trigger. +Optional: Defaults to 72MB

-max-total-wal-size
+raft-entry-cache-life-time
string
(Optional) +

When a peer is not responding for this time, leader will not keep entry cache for it.

-max-background-jobs
+raft-reject-transfer-leader-duration
-int64 +string
(Optional) +

When a peer is newly added, reject transferring leader to the peer for a while.

-max-manifest-file-size
+split-region-check-tick-interval
string
(Optional) +

Interval (ms) to check region whether need to be split or not. +Optional: Defaults to 10s

-create-if-missing
+region-split-check-diff
-bool +string
(Optional) +

/ When size change of region exceed the diff since last check, it +/ will be checked again whether it should be split. +Optional: Defaults to 6MB

-max-open-files
+region-compact-check-interval
-int64 +string
(Optional) +

/ Interval (ms) to check whether start compaction for a region. +Optional: Defaults to 5m

-enable-statistics
+clean-stale-peer-delay
-bool +string
(Optional) +

delay time before deleting a stale peer +Optional: Defaults to 10m

-stats-dump-period
+region-compact-check-step
-string +int64
(Optional) +

/ Number of regions for each time checking. +Optional: Defaults to 100

-compaction-readahead-size
+region-compact-min-tombstones
-string +int64
(Optional) +

/ Minimum number of tombstones to trigger manual compaction. +Optional: Defaults to 10000

-info-log-max-size
+region-compact-tombstones-percent
-string +int64
(Optional) +

/ Minimum percentage of tombstones to trigger manual compaction. +/ Should between 1 and 100. +Optional: Defaults to 30

-info-log-roll-time
+pd-heartbeat-tick-interval
string
(Optional) +

Optional: Defaults to 60s

-info-log-keep-log-file-num
+pd-store-heartbeat-tick-interval
-int64 +string
(Optional) +

Optional: Defaults to 10s

-info-log-dir
+snap-mgr-gc-tick-interval
string @@ -13140,9 +14831,9 @@ string
-max-sub-compactions
+snap-gc-timeout
-int64 +string
@@ -13151,31 +14842,33 @@ int64
-writable-file-max-buffer-size
+lock-cf-compact-interval
string
(Optional) +

Optional: Defaults to 10m

-use-direct-io-for-flush-and-compaction
+lock-cf-compact-bytes-threshold
-bool +string
(Optional) +

Optional: Defaults to 256MB

-enable-pipelined-write
+notify-capacity
-bool +int64
@@ -13184,9 +14877,9 @@ bool
-allow-concurrent-memtable-write
+messages-per-tick
-bool +int64
@@ -13195,110 +14888,96 @@ bool
-bytes-per-sync
+max-peer-down-duration
string
(Optional) +

/ When a peer is not active for max-peer-down-duration +/ the peer is considered to be down and is reported to PD. +Optional: Defaults to 5m

-wal-bytes-per-sync
+max-leader-missing-duration
string
(Optional) +

/ If the leader of a peer is missing for longer than max-leader-missing-duration +/ the peer would ask pd to confirm whether it is valid in any region. +/ If the peer is stale and is not valid in any region, it will destroy itself.

-defaultcf
+abnormal-leader-missing-duration
- -TiKVCfConfig - +string
(Optional) +

/ Similar to the max-leader-missing-duration, instead it will log warnings and +/ try to alert monitoring systems, if there is any.

-

TiKVRaftstoreConfig

-

-(Appears on: -TiKVConfig) -

-

-

TiKVRaftstoreConfig is the configuration of TiKV raftstore component.

-

- - - - - - - - + +
FieldDescription
-sync-log
+peer-stale-state-check-interval
-bool +string
(Optional) -

true for high reliability, prevent data loss when power failure. -Optional: Defaults to true

-prevote
+leader-transfer-max-log-lag
-bool +int64
(Optional) -

Optional: Defaults to true

-raft-base-tick-interval
+snap-apply-batch-size
string
(Optional) -

raft-base-tick-interval is a base tick interval (ms).

-raft-heartbeat-ticks
+consistency-check-interval
-int64 +string
(Optional) +

Interval (ms) to check region whether the data is consistent. +Optional: Defaults to 0

-raft-election-timeout-ticks
+report-region-flow-interval
-int64 +string
@@ -13307,243 +14986,240 @@ int64
-raft-entry-max-size
+raft-store-max-leader-lease
string
(Optional) -

When the entry exceed the max size, reject to propose it. -Optional: Defaults to 8MB

+

The lease provided by a successfully proposed and applied entry.

-raft-max-size-per-msg
+right-derive-when-split
-string +bool
(Optional) -

Limit the max size of each append message. -Optional: Defaults to 1MB

+

Right region derive origin region id when split.

-raft-max-inflight-msgs
+allow-remove-leader
-int64 +bool
(Optional) -

Limit the max number of in-flight append messages during optimistic -replication phase. -Optional: Defaults to 256

-raft-log-gc-tick-interval
+merge-max-log-gap
-string +int64
(Optional) -

Interval to gc unnecessary raft log (ms). -Optional: Defaults to 10s

+

/ Max log gap allowed to propose merge.

-raft-log-gc-threshold
+merge-check-tick-interval
-int64 +string
(Optional) -

A threshold to gc stale raft log, must >= 1. -Optional: Defaults to 50

+

/ Interval to re-propose merge.

-raft-log-gc-count-limit
+use-delete-range
-int64 +bool
(Optional) -

When entry count exceed this value, gc will be forced trigger. -Optional: Defaults to 72000

-raft-log-gc-size-limit
+cleanup-import-sst-interval
string
(Optional) -

When the approximate size of raft log entries exceed this value -gc will be forced trigger. -Optional: Defaults to 72MB

+

Optional: Defaults to 10m

-raft-entry-cache-life-time
+apply-max-batch-size
-string +int64
(Optional) -

When a peer is not responding for this time, leader will not keep entry cache for it.

-raft-reject-transfer-leader-duration
+apply-pool-size
-string +int64
(Optional) -

When a peer is newly added, reject transferring leader to the peer for a while.

+

Optional: Defaults to 2

-split-region-check-tick-interval
+store-max-batch-size
-string +int64
(Optional) -

Interval (ms) to check region whether need to be split or not. -Optional: Defaults to 10s

-region-split-check-diff
+store-pool-size
-string +int64
(Optional) -

/ When size change of region exceed the diff since last check, it -/ will be checked again whether it should be split. -Optional: Defaults to 6MB

+

Optional: Defaults to 2

-region-compact-check-interval
+store-reschedule-duration
string
(Optional) -

/ Interval (ms) to check whether start compaction for a region. -Optional: Defaults to 5m

+

Optional: Defaults to 3s

-clean-stale-peer-delay
+apply-yield-duration
string
(Optional) -

delay time before deleting a stale peer -Optional: Defaults to 10m

+

Optional: Defaults to 500ms

-region-compact-check-step
+hibernate-regions
-int64 +bool
(Optional) -

/ Number of regions for each time checking. -Optional: Defaults to 100

-region-compact-min-tombstones
+apply-early
-int64 +bool
(Optional) -

/ Minimum number of tombstones to trigger manual compaction. -Optional: Defaults to 10000

+

Optional: Defaults to false

-region-compact-tombstones-percent
+perf-level
int64
(Optional) -

/ Minimum percentage of tombstones to trigger manual compaction. -/ Should between 1 and 100. -Optional: Defaults to 30

+

Optional: Defaults to 0

-pd-heartbeat-tick-interval
+dev-assert
-string +bool
(Optional) -

Optional: Defaults to 60s

+

Optional: Defaults to false

+

TiKVReadPoolConfig

+

+(Appears on: +TiKVConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-pd-store-heartbeat-tick-interval
+unified
-string + +TiKVUnifiedReadPoolConfig +
(Optional) -

Optional: Defaults to 10s

-snap-mgr-gc-tick-interval
+coprocessor
-string + +TiKVCoprocessorReadPoolConfig +
@@ -13552,44 +15228,61 @@ string
-snap-gc-timeout
+storage
-string + +TiKVStorageReadPoolConfig +
(Optional)
+

TiKVSecurityConfig

+

+(Appears on: +TiKVConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-lock-cf-compact-interval
+ca-path
string
(Optional) -

Optional: Defaults to 10m

-lock-cf-compact-bytes-threshold
+cert-path
string
(Optional) -

Optional: Defaults to 256MB

-notify-capacity
+key-path
-int64 +string
@@ -13598,105 +15291,173 @@ int64
-messages-per-tick
+cert-allowed-cn
-int64 +[]string
(Optional) +

CertAllowedCN is the Common Name that allowed

-max-peer-down-duration
+override-ssl-target
string
(Optional) -

/ When a peer is not active for max-peer-down-duration -/ the peer is considered to be down and is reported to PD. -Optional: Defaults to 5m

-max-leader-missing-duration
+cipher-file
string
(Optional) -

/ If the leader of a peer is missing for longer than max-leader-missing-duration -/ the peer would ask pd to confirm whether it is valid in any region. -/ If the peer is stale and is not valid in any region, it will destroy itself.

-abnormal-leader-missing-duration
+encryption
-string + +TiKVSecurityConfigEncryption +
(Optional) -

/ Similar to the max-leader-missing-duration, instead it will log warnings and -/ try to alert monitoring systems, if there is any.

+

TiKVSecurityConfigEncryption

+

+(Appears on: +TiKVSecurityConfig) +

+

+

+ + + + + + + + + +
FieldDescription
-peer-stale-state-check-interval
+data-encryption-method
string
(Optional) +

Encryption method to use for data files. +Possible values are “plaintext”, “aes128-ctr”, “aes192-ctr” and “aes256-ctr”. Value other than +“plaintext” means encryption is enabled, in which case master key must be specified.

-leader-transfer-max-log-lag
+data-key-rotation-period
-int64 +string
(Optional) +

Specifies how often TiKV rotates data encryption key.

-snap-apply-batch-size
+master-key
-string + +TiKVSecurityConfigEncryptionMasterKey +
(Optional) +

Specifies master key if encryption is enabled. There are three types of master key:

+
    +
  • “plaintext”:

    +

    Plaintext as master key means no master key is given and only applicable when +encryption is not enabled, i.e. data-encryption-method = “plaintext”. This type doesn’t +have sub-config items. Example:

    +

    [security.encryption.master-key] +type = “plaintext”

  • +
  • “kms”:

    +

    Use a KMS service to supply master key. Currently only AWS KMS is supported. This type of +master key is recommended for production use. Example:

    +

    [security.encryption.master-key] +type = “kms”

    +

    KMS CMK key id. Must be a valid KMS CMK where the TiKV process has access to.

    +

    In production is recommended to grant access of the CMK to TiKV using IAM.

    +

    key-id = “1234abcd-12ab-34cd-56ef-1234567890ab”

    +

    AWS region of the KMS CMK.

    +

    region = “us-west-2”

    +

    (Optional) AWS KMS service endpoint. Only required when non-default KMS endpoint is

    +

    desired.

    +

    endpoint = “https://kms.us-west-2.amazonaws.com”

  • +
  • “file”:

    +

    Supply a custom encryption key stored in a file. It is recommended NOT to use in production, +as it breaks the purpose of encryption at rest, unless the file is stored in tempfs. +The file must contain a 256-bits (32 bytes, regardless of key length implied by +data-encryption-method) key encoded as hex string and end with newline (“\n”). Example:

    +

    [security.encryption.master-key] +type = “file” +path = “/path/to/master/key/file”

  • +
-consistency-check-interval
+previous-master-key
-string + +TiKVSecurityConfigEncryptionPreviousMasterKey +
(Optional) -

Interval (ms) to check region whether the data is consistent. -Optional: Defaults to 0

+

Specifies the old master key when rotating master key. Same config format as master-key. +The key is only access once during TiKV startup, after that TiKV do not need access to the key. +And it is okay to leave the stale previous-master-key config after master key rotation.

+

TiKVSecurityConfigEncryptionMasterKey

+

+(Appears on: +TiKVSecurityConfigEncryption) +

+

+

+ + + + + + + + + +
FieldDescription
-report-region-flow-interval
+type
string @@ -13707,33 +15468,60 @@ string
-raft-store-max-leader-lease
+MasterKeyFileConfig
-string + +MasterKeyFileConfig +
-(Optional) -

The lease provided by a successfully proposed and applied entry.

+

+(Members of MasterKeyFileConfig are embedded into this type.) +

+

Master key file config +If the type set to file, this config should be filled

-right-derive-when-split
+MasterKeyKMSConfig
-bool + +MasterKeyKMSConfig +
-(Optional) -

Right region derive origin region id when split.

+

+(Members of MasterKeyKMSConfig are embedded into this type.) +

+

Master key KMS config +If the type set to kms, this config should be filled

+

TiKVSecurityConfigEncryptionPreviousMasterKey

+

+(Appears on: +TiKVSecurityConfigEncryption) +

+

+

+ + + + + + + + + +
FieldDescription
-allow-remove-leader
+type
-bool +string
@@ -13742,192 +15530,205 @@ bool
-merge-max-log-gap
+MasterKeyFileConfig
-int64 + +MasterKeyFileConfig +
-(Optional) -

/ Max log gap allowed to propose merge.

+

+(Members of MasterKeyFileConfig are embedded into this type.) +

+

Master key file config +If the type set to file, this config should be filled

-merge-check-tick-interval
+MasterKeyKMSConfig
-string + +MasterKeyKMSConfig +
-(Optional) -

/ Interval to re-propose merge.

+

+(Members of MasterKeyKMSConfig are embedded into this type.) +

+

Master key KMS config +If the type set to kms, this config should be filled

+

TiKVServerConfig

+

+(Appears on: +TiKVConfig) +

+

+

TiKVServerConfig is the configuration of TiKV server.

+

+ + + + + + + + - -
FieldDescription
-use-delete-range
+status-thread-pool-size
-bool +string
(Optional) +

Optional: Defaults to 1

-cleanup-import-sst-interval
+grpc-compression-type
string
(Optional) -

Optional: Defaults to 10m

+

Optional: Defaults to none

-apply-max-batch-size
+grpc-concurrency
-int64 +uint
(Optional) +

Optional: Defaults to 4

-apply-pool-size
+grpc-concurrent-stream
-int64 +uint
(Optional) -

Optional: Defaults to 2

+

Optional: Defaults to 1024

-store-max-batch-size
+grpc-memory-pool-quota
-int64 +string
(Optional) +

Optional: Defaults to 32G

-store-pool-size
+grpc-raft-conn-num
-int64 +uint
(Optional) -

Optional: Defaults to 2

+

Optional: Defaults to 10

-store-reschedule-duration
+grpc-stream-initial-window-size
string
(Optional) -

Optional: Defaults to 3s

+

Optional: Defaults to 2MB

-apply-yield-duration
+grpc-keepalive-time
string
(Optional) -

Optional: Defaults to 500ms

+

Optional: Defaults to 10s

-hibernate-regions
+grpc-keepalive-timeout
-bool +string
(Optional) +

Optional: Defaults to 3s

-apply-early
+concurrent-send-snap-limit
-bool +uint
(Optional) -

Optional: Defaults to false

+

Optional: Defaults to 32

-perf-level
+concurrent-recv-snap-limit
-int64 +uint
(Optional) -

Optional: Defaults to 0

+

Optional: Defaults to 32

-dev-assert
+end-point-recursion-limit
-bool +uint
(Optional) -

Optional: Defaults to false

+

Optional: Defaults to 1000

-

TiKVReadPoolConfig

-

-(Appears on: -TiKVConfig) -

-

-

- - - - - - - - - -
FieldDescription
-unified
+end-point-stream-channel-size
- -TiKVUnifiedReadPoolConfig - +uint
@@ -13936,11 +15737,9 @@ TiKVUnifiedReadPoolConfig
-coprocessor
+end-point-batch-row-limit
- -TiKVCoprocessorReadPoolConfig - +uint
@@ -13949,39 +15748,20 @@ TiKVCoprocessorReadPoolConfig
-storage
+end-point-stream-batch-row-limit
- -TiKVStorageReadPoolConfig - +uint
(Optional)
-

TiKVSecurityConfig

-

-(Appears on: -TiKVConfig) -

-

-

- - - - - - - - - -
FieldDescription
-ca-path
+end-point-enable-batch-if-possible
-string +uint
@@ -13990,7 +15770,7 @@ string
-cert-path
+end-point-request-max-handle-duration
string @@ -14001,32 +15781,32 @@ string
-key-path
+snap-max-write-bytes-per-sec
string
(Optional) +

Optional: Defaults to 100MB

-cert-allowed-cn
+snap-max-total-size
-[]string +string
(Optional) -

CertAllowedCN is the Common Name that allowed

-override-ssl-target
+stats-concurrency
-string +uint
@@ -14035,9 +15815,9 @@ string
-cipher-file
+heavy-load-threshold
-string +uint
@@ -14046,127 +15826,70 @@ string
-encryption
+heavy-load-wait-duration
- -TiKVSecurityConfigEncryption - +string
(Optional) +

Optional: Defaults to 60s

-

TiKVSecurityConfigEncryption

-

-(Appears on: -TiKVSecurityConfig) -

-

-

- - - - - - - -
FieldDescription
-data-encryption-method
+labels
-string +map[string]string
(Optional) -

Encryption method to use for data files. -Possible values are “plaintext”, “aes128-ctr”, “aes192-ctr” and “aes256-ctr”. Value other than -“plaintext” means encryption is enabled, in which case master key must be specified.

-data-key-rotation-period
+enable-request-batch
-string +bool
(Optional) -

Specifies how often TiKV rotates data encryption key.

-master-key
+request-batch-enable-cross-command
- -TiKVSecurityConfigEncryptionMasterKey - +bool
(Optional) -

Specifies master key if encryption is enabled. There are three types of master key:

-
    -
  • “plaintext”:

    -

    Plaintext as master key means no master key is given and only applicable when -encryption is not enabled, i.e. data-encryption-method = “plaintext”. This type doesn’t -have sub-config items. Example:

    -

    [security.encryption.master-key] -type = “plaintext”

  • -
  • “kms”:

    -

    Use a KMS service to supply master key. Currently only AWS KMS is supported. This type of -master key is recommended for production use. Example:

    -

    [security.encryption.master-key] -type = “kms”

    -

    KMS CMK key id. Must be a valid KMS CMK where the TiKV process has access to.

    -

    In production is recommended to grant access of the CMK to TiKV using IAM.

    -

    key-id = “1234abcd-12ab-34cd-56ef-1234567890ab”

    -

    AWS region of the KMS CMK.

    -

    region = “us-west-2”

    -

    (Optional) AWS KMS service endpoint. Only required when non-default KMS endpoint is

    -

    desired.

    -

    endpoint = “https://kms.us-west-2.amazonaws.com”

  • -
  • “file”:

    -

    Supply a custom encryption key stored in a file. It is recommended NOT to use in production, -as it breaks the purpose of encryption at rest, unless the file is stored in tempfs. -The file must contain a 256-bits (32 bytes, regardless of key length implied by -data-encryption-method) key encoded as hex string and end with newline (“\n”). Example:

    -

    [security.encryption.master-key] -type = “file” -path = “/path/to/master/key/file”

  • -
-previous-master-key
+request-batch-wait-duration
- -TiKVSecurityConfigEncryptionPreviousMasterKey - +string
(Optional) -

Specifies the old master key when rotating master key. Same config format as master-key. -The key is only access once during TiKV startup, after that TiKV do not need access to the key. -And it is okay to leave the stale previous-master-key config after master key rotation.

-

TiKVSecurityConfigEncryptionMasterKey

+

TiKVSpec

(Appears on: -TiKVSecurityConfigEncryption) +TiKVGroupSpec, +TidbClusterSpec)

+

TiKVSpec contains details of TiKV members

@@ -14178,278 +15901,275 @@ And it is okay to leave the stale previous-master-key config after master key ro - - - - - - - -
-type
- -string - -
-(Optional) -
-MasterKeyFileConfig
+ComponentSpec
- -MasterKeyFileConfig + +ComponentSpec

-(Members of MasterKeyFileConfig are embedded into this type.) +(Members of ComponentSpec are embedded into this type.)

-

Master key file config -If the type set to file, this config should be filled

-MasterKeyKMSConfig
+ResourceRequirements
- -MasterKeyKMSConfig - - -
-

-(Members of MasterKeyKMSConfig are embedded into this type.) -

-

Master key KMS config -If the type set to kms, this config should be filled

-
-

TiKVSecurityConfigEncryptionPreviousMasterKey

-

-(Appears on: -TiKVSecurityConfigEncryption) -

+ +Kubernetes core/v1.ResourceRequirements + +
+ +

+(Members of ResourceRequirements are embedded into this type.)

- - - - - + - - - -
FieldDescription
-type
+serviceAccount
string
-(Optional) +

Specify a Service Account for tikv

-MasterKeyFileConfig
+replicas
- -MasterKeyFileConfig - +int32
-

-(Members of MasterKeyFileConfig are embedded into this type.) -

-

Master key file config -If the type set to file, this config should be filled

+

The desired ready replicas

-MasterKeyKMSConfig
+baseImage
- -MasterKeyKMSConfig - +string
-

-(Members of MasterKeyKMSConfig are embedded into this type.) -

-

Master key KMS config -If the type set to kms, this config should be filled

+(Optional) +

TODO: remove optional after defaulting introduced +Base image of the component, image tag is now allowed during validation

-

TiKVServerConfig

-

-(Appears on: -TiKVConfig) -

-

-

TiKVServerConfig is the configuration of TiKV server.

-

- - - - + + - - + +
FieldDescription +privileged
+ +bool + +
+(Optional) +

Whether create the TiKV container in privileged mode, it is highly discouraged to enable this in +critical environment. +Optional: defaults to false

+
-status-thread-pool-size
+maxFailoverCount
-string +int32
(Optional) -

Optional: Defaults to 1

+

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover +Optional: Defaults to 3

-grpc-compression-type
+storageClassName
string
(Optional) -

Optional: Defaults to none

+

The storageClassName of the persistent volume for TiKV data storage. +Defaults to Kubernetes default storage class.

-grpc-concurrency
+dataSubDir
-uint +string
(Optional) -

Optional: Defaults to 4

+

Subdirectory within the volume to store TiKV Data. By default, the data +is stored in the root directory of volume which is mounted at +/var/lib/tikv. +Specifying this will change the data directory to a subdirectory, e.g. +/var/lib/tikv/data if you set the value to “data”. +It’s dangerous to change this value for a running cluster as it will +upgrade your cluster to use a new storage directory. +Defaults to “” (volume’s root).

-grpc-concurrent-stream
+config
-uint + +TiKVConfig +
(Optional) -

Optional: Defaults to 1024

+

Config is the Configuration of tikv-servers

+

TiKVStatus

+

+(Appears on: +TiKVGroupStatus, +TidbClusterStatus) +

+

+

TiKVStatus is TiKV status

+

+ + + + + + + + + +
FieldDescription
-grpc-memory-pool-quota
+synced
-string +bool
-(Optional) -

Optional: Defaults to 32G

-grpc-raft-conn-num
+phase
-uint + +MemberPhase +
-(Optional) -

Optional: Defaults to 10

-grpc-stream-initial-window-size
+statefulSet
-string + +Kubernetes apps/v1.StatefulSetStatus +
-(Optional) -

Optional: Defaults to 2MB

-grpc-keepalive-time
+stores
-string + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiKVStore +
-(Optional) -

Optional: Defaults to 10s

-grpc-keepalive-timeout
+tombstoneStores
-string + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiKVStore +
-(Optional) -

Optional: Defaults to 3s

-concurrent-send-snap-limit
+failureStores
-uint + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiKVFailureStore +
-(Optional) -

Optional: Defaults to 32

-concurrent-recv-snap-limit
+image
-uint +string
-(Optional) -

Optional: Defaults to 32

+

TiKVStorageConfig

+

+(Appears on: +TiKVConfig) +

+

+

TiKVStorageConfig is the config of storage

+

+ + + + + + + + + +
FieldDescription
-end-point-recursion-limit
+max-key-size
-uint +int64
(Optional) -

Optional: Defaults to 1000

-end-point-stream-channel-size
+scheduler-notify-capacity
-uint +int64
@@ -14458,42 +16178,47 @@ uint
-end-point-batch-row-limit
+scheduler-concurrency
-uint +int64
(Optional) +

Optional: Defaults to 2048000

-end-point-stream-batch-row-limit
+scheduler-worker-pool-size
-uint +int64
(Optional) +

Optional: Defaults to 4

-end-point-enable-batch-if-possible
+scheduler-pending-write-threshold
-uint +string
(Optional) +

Optional: Defaults to 100MB

-end-point-request-max-handle-duration
+block-cache
-string + +TiKVBlockCacheConfig +
@@ -14502,115 +16227,142 @@ string
-snap-max-write-bytes-per-sec
+reserve-space
string
(Optional) -

Optional: Defaults to 100MB

+

The size of the temporary file that preoccupies the extra space when +TiKV is started. The name of temporary file is space_placeholder_file, +located in the storage.data-dir directory. When TiKV runs out of disk +space and cannot be started normally, you can delete this file as an +emergency intervention and set it to 0MB. Default value is 2GB.

+

TiKVStorageReadPoolConfig

+

+(Appears on: +TiKVReadPoolConfig) +

+

+

+ + + + + + + +
FieldDescription
-snap-max-total-size
+high-concurrency
-string +int64
(Optional) +

Optional: Defaults to 4

-stats-concurrency
+normal-concurrency
-uint +int64
(Optional) +

Optional: Defaults to 4

-heavy-load-threshold
+low-concurrency
-uint +int64
(Optional) +

Optional: Defaults to 4

-heavy-load-wait-duration
+max-tasks-per-worker-high
-string +int64
(Optional) -

Optional: Defaults to 60s

+

Optional: Defaults to 2000

-labels
+max-tasks-per-worker-normal
-map[string]string +int64
(Optional) +

Optional: Defaults to 2000

-enable-request-batch
+max-tasks-per-worker-low
-bool +int64
(Optional) +

Optional: Defaults to 2000

-request-batch-enable-cross-command
+stack-size
-bool +string
(Optional) +

Optional: Defaults to 10MB

-request-batch-wait-duration
+use-unified-pool
-string +bool
(Optional) +

Optional: Defaults to true

-

TiKVSpec

+

TiKVStore

(Appears on: -TiKVGroupSpec, -TidbClusterSpec) +TiKVStatus)

-

TiKVSpec contains details of TiKV members

+

TiKVStores is either Up/Down/Offline/Tombstone

@@ -14622,250 +16374,228 @@ string + +
-ComponentSpec
+id
- -ComponentSpec - +string
-

-(Members of ComponentSpec are embedded into this type.) -

+

store id is also uint64, due to the same reason as pd id, we store id as string

-ResourceRequirements
+podName
- -Kubernetes core/v1.ResourceRequirements - +string
-

-(Members of ResourceRequirements are embedded into this type.) -

-serviceAccount
+ip
string
-

Specify a Service Account for tikv

-replicas
+leaderCount
int32
-

The desired ready replicas

-baseImage
+state
string
-(Optional) -

TODO: remove optional after defaulting introduced -Base image of the component, image tag is now allowed during validation

-privileged
+lastHeartbeatTime
-bool + +Kubernetes meta/v1.Time +
-(Optional) -

Whether create the TiKV container in privileged mode, it is highly discouraged to enable this in -critical environment. -Optional: defaults to false

-maxFailoverCount
+lastTransitionTime
-int32 + +Kubernetes meta/v1.Time +
-(Optional) -

MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover -Optional: Defaults to 3

+

Last time the health transitioned from one to another.

+

TiKVTitanCfConfig

+

+(Appears on: +TiKVCfConfig) +

+

+

TiKVTitanCfConfig is the titian config.

+

+ + + + + + + + - -
FieldDescription
-storageClassName
+min-blob-size
string
(Optional) -

The storageClassName of the persistent volume for TiKV data storage. -Defaults to Kubernetes default storage class.

-dataSubDir
+blob-file-compression
string
(Optional) -

Subdirectory within the volume to store TiKV Data. By default, the data -is stored in the root directory of volume which is mounted at -/var/lib/tikv. -Specifying this will change the data directory to a subdirectory, e.g. -/var/lib/tikv/data if you set the value to “data”. -It’s dangerous to change this value for a running cluster as it will -upgrade your cluster to use a new storage directory. -Defaults to “” (volume’s root).

-config
+blob-cache-size
- -TiKVConfig - +string
(Optional) -

Config is the Configuration of tikv-servers

-

TiKVStatus

-

-(Appears on: -TiKVGroupStatus, -TidbClusterStatus) -

-

-

TiKVStatus is TiKV status

-

- - - - + + - -
FieldDescription +min-gc-batch-size
+ +string + +
+(Optional) +
-synced
+max-gc-batch-size
-bool +string
+(Optional)
-phase
+discardable-ratio
- -MemberPhase - +float64
+(Optional)
-statefulSet
+sample-ratio
- -Kubernetes apps/v1.StatefulSetStatus - +float64
+(Optional)
-stores
+merge-small-file-threshold
- -map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiKVStore - +string
+(Optional)
-tombstoneStores
+blob-run-mode
- -map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiKVStore - +string
+(Optional)
-failureStores
+level_merge
- -map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiKVFailureStore - +bool
+

optional

-image
+gc-merge-rewrite
-string +bool
+

optional

-

TiKVStorageConfig

+

TiKVTitanDBConfig

(Appears on: -TiKVConfig) +TiKVDbConfig)

-

TiKVStorageConfig is the config of storage

+

TiKVTitanDBConfig is the config a titian db.

@@ -14877,9 +16607,9 @@ string - - - - - - - -
-max-key-size
+enabled
-int64 +bool
@@ -14888,9 +16618,9 @@ int64
-scheduler-notify-capacity
+dirname
-int64 +string
@@ -14899,72 +16629,41 @@ int64
-scheduler-concurrency
+disable-gc
-int64 +bool
(Optional) -

Optional: Defaults to 2048000

-scheduler-worker-pool-size
+max-background-gc
int64
(Optional) -

Optional: Defaults to 4

-
-scheduler-pending-write-threshold
- -string - -
-(Optional) -

Optional: Defaults to 100MB

-
-block-cache
- - -TiKVBlockCacheConfig - - -
-(Optional)
-reserve-space
+purge-obsolete-files-period
string
-(Optional) -

The size of the temporary file that preoccupies the extra space when -TiKV is started. The name of temporary file is space_placeholder_file, -located in the storage.data-dir directory. When TiKV runs out of disk -space and cannot be started normally, you can delete this file as an -emergency intervention and set it to 0MB. Default value is 2GB.

+(Optional) +

The value of this field will be truncated to seconds.

-

TiKVStorageReadPoolConfig

+

TiKVUnifiedReadPoolConfig

(Appears on: TiKVReadPoolConfig) @@ -14981,109 +16680,123 @@ emergency intervention and set it to 0MB. Default value is 2GB.

-high-concurrency
+min-thread-count
-int64 +int32 (Optional) -

Optional: Defaults to 4

-normal-concurrency
+max-thread-count
-int64 +int32 (Optional) -

Optional: Defaults to 4

-low-concurrency
+stack-size
-int64 +string (Optional) -

Optional: Defaults to 4

-max-tasks-per-worker-high
+max-tasks-per-worker
-int64 +int32 (Optional) -

Optional: Defaults to 2000

+ + +

TidbAutoScalerSpec

+

+(Appears on: +TidbClusterAutoScalerSpec) +

+

+

TidbAutoScalerSpec describes the spec for tidb auto-scaling

+

+ + - - + + + + + +
-max-tasks-per-worker-normal
- -int64 - -
-(Optional) -

Optional: Defaults to 2000

-
FieldDescription
-max-tasks-per-worker-low
+BasicAutoScalerSpec
-int64 + +BasicAutoScalerSpec +
-(Optional) -

Optional: Defaults to 2000

+

+(Members of BasicAutoScalerSpec are embedded into this type.) +

+

TidbAutoScalerStatus

+

+(Appears on: +TidbClusterAutoSclaerStatus) +

+

+

TidbAutoScalerStatus describe the auto-scaling status of tidb

+

+ + - - + + + +
-stack-size
- -string - -
-(Optional) -

Optional: Defaults to 10MB

-
FieldDescription
-use-unified-pool
+BasicAutoScalerStatus
-bool + +BasicAutoScalerStatus +
-(Optional) -

Optional: Defaults to true

+

+(Members of BasicAutoScalerStatus are embedded into this type.) +

-

TiKVStore

+

TidbClusterAutoScalerRef

(Appears on: -TiKVStatus) +TidbClusterStatus)

-

TiKVStores is either Up/Down/Offline/Tombstone

+

TidbClusterAutoScalerRef indicates to the target auto-scaler ref

@@ -15095,18 +16808,17 @@ bool + +
-id
+name
string
-

store id is also uint64, due to the same reason as pd id, we store id as string

-podName
+namespace
string @@ -15114,70 +16826,102 @@ string
+

TidbClusterAutoScalerSpec

+

+(Appears on: +TidbClusterAutoScaler) +

+

+

TidbAutoScalerSpec describes the state of the TidbClusterAutoScaler

+

+ + + + + + + +
FieldDescription
-ip
+cluster
-string + +TidbClusterRef +
+

TidbClusterRef describe the target TidbCluster

-leaderCount
+metricsUrl
-int32 +string
+(Optional) +

We used prometheus to fetch the metrics resources until the pd could provide it. +MetricsUrl represents the url to fetch the metrics info

-state
+monitor
-string + +TidbMonitorRef +
+(Optional) +

TidbMonitorRef describe the target TidbMonitor, when MetricsUrl and Monitor are both set, +Operator will use MetricsUrl

-lastHeartbeatTime
+tikv
- -Kubernetes meta/v1.Time + +TikvAutoScalerSpec
+(Optional) +

TiKV represents the auto-scaling spec for tikv

-lastTransitionTime
+tidb
- -Kubernetes meta/v1.Time + +TidbAutoScalerSpec
-

Last time the health transitioned from one to another.

+(Optional) +

TiDB represents the auto-scaling spec for tidb

-

TiKVTitanCfConfig

+

TidbClusterAutoSclaerStatus

(Appears on: -TiKVCfConfig) +TidbClusterAutoScaler)

-

TiKVTitanCfConfig is the titian config.

+

TidbClusterAutoSclaerStatus describe the whole status

@@ -15189,134 +16933,147 @@ Kubernetes meta/v1.Time - - - - - - - - + +
-min-blob-size
- -string - -
-(Optional) -
-blob-file-compression
- -string - -
-(Optional) -
-blob-cache-size
+tikv
-string + +TikvAutoScalerStatus +
(Optional) +

Tikv describes the status for the tikv in the last auto-scaling reconciliation

-min-gc-batch-size
+tidb
-string + +TidbAutoScalerStatus +
(Optional) +

Tidb describes the status for the tidb in the last auto-scaling reconciliation

+

TidbClusterCondition

+

+(Appears on: +TidbClusterStatus) +

+

+

TidbClusterCondition describes the state of a tidb cluster at a certain point.

+

+ + - - + + + +
-max-gc-batch-size
- -string - -
-(Optional) -FieldDescription
-discardable-ratio
+type
-float64 + +TidbClusterConditionType +
-(Optional) +

Type of the condition.

-sample-ratio
+status
-float64 + +Kubernetes core/v1.ConditionStatus +
-(Optional) +

Status of the condition, one of True, False, Unknown.

-merge-small-file-threshold
+lastUpdateTime
-string + +Kubernetes meta/v1.Time +
-(Optional) +

The last time this condition was updated.

-blob-run-mode
+lastTransitionTime
-string + +Kubernetes meta/v1.Time +
(Optional) +

Last time the condition transitioned from one status to another.

-level_merge
+reason
-bool +string
-

optional

+(Optional) +

The reason for the condition’s last transition.

-gc-merge-rewrite
+message
-bool +string
-

optional

+(Optional) +

A human readable message indicating details about the transition.

-

TiKVTitanDBConfig

+

TidbClusterConditionType

(Appears on: -TiKVDbConfig) +DMClusterCondition, +TidbClusterCondition)

-

TiKVTitanDBConfig is the config a titian db.

+

TidbClusterConditionType represents a tidb cluster condition value.

+

+

TidbClusterRef

+

+(Appears on: +TidbClusterAutoScalerSpec, +TidbInitializerSpec, +TidbMonitorSpec) +

+

+

TidbClusterRef reference to a TidbCluster

@@ -15328,514 +17085,405 @@ bool + +
-enabled
+namespace
-bool +string
(Optional) +

Namespace is the namespace that TidbCluster object locates, +default to the same namespace with TidbMonitor

-dirname
+name
string
-(Optional) +

Name is the name of TidbCluster object

+

TidbClusterSpec

+

+(Appears on: +TidbCluster) +

+

+

TidbClusterSpec describes the attributes that a user creates on a tidb cluster

+

+ + + + + + + + - -
FieldDescription
-disable-gc
+discovery
-bool + +DiscoverySpec +
-(Optional) +

Discovery spec

-max-background-gc
+pd
-int64 + +PDSpec +
(Optional) +

PD cluster spec

-purge-obsolete-files-period
+tidb
-string + +TiDBSpec +
(Optional) -

The value of this field will be truncated to seconds.

+

TiDB cluster spec

-

TiKVUnifiedReadPoolConfig

-

-(Appears on: -TiKVReadPoolConfig) -

-

-

- - - - - - - - - -
FieldDescription
-min-thread-count
+tikv
-int32 + +TiKVSpec +
(Optional) +

TiKV cluster spec

-max-thread-count
+tiflash
-int32 + +TiFlashSpec +
(Optional) +

TiFlash cluster spec

-stack-size
+ticdc
-string + +TiCDCSpec +
(Optional) +

TiCDC cluster spec

-max-tasks-per-worker
+pump
-int32 + +PumpSpec +
(Optional) +

Pump cluster spec

-

TidbAutoScalerSpec

-

-(Appears on: -TidbClusterAutoScalerSpec) -

-

-

TidbAutoScalerSpec describes the spec for tidb auto-scaling

-

- - - - - - - - - -
FieldDescription
-BasicAutoScalerSpec
+helper
- -BasicAutoScalerSpec + +HelperSpec
-

-(Members of BasicAutoScalerSpec are embedded into this type.) -

+(Optional) +

Helper spec

-

TidbAutoScalerStatus

-

-(Appears on: -TidbClusterAutoSclaerStatus) -

-

-

TidbAutoScalerStatus describe the auto-scaling status of tidb

-

- - - - - - - - - -
FieldDescription
-BasicAutoScalerStatus
+paused
- -BasicAutoScalerStatus - +bool
-

-(Members of BasicAutoScalerStatus are embedded into this type.) -

+(Optional) +

Indicates that the tidb cluster is paused and will not be processed by +the controller.

-

TidbClusterAutoScalerRef

-

-(Appears on: -TidbClusterStatus) -

-

-

TidbClusterAutoScalerRef indicates to the target auto-scaler ref

-

- - - - - - - - - -
FieldDescription
-name
+version
string
+(Optional) +

TODO: remove optional after defaulting logic introduced +TiDB cluster version

-namespace
+schedulerName
string
+

SchedulerName of TiDB cluster Pods

-

TidbClusterAutoScalerSpec

-

-(Appears on: -TidbClusterAutoScaler) -

-

-

TidbAutoScalerSpec describes the state of the TidbClusterAutoScaler

-

- - - - - - - - - - -
FieldDescription
-cluster
+pvReclaimPolicy
- -TidbClusterRef + +Kubernetes core/v1.PersistentVolumeReclaimPolicy
-

TidbClusterRef describe the target TidbCluster

+

Persistent volume reclaim policy applied to the PVs that consumed by TiDB cluster

-metricsUrl
+imagePullPolicy
-string + +Kubernetes core/v1.PullPolicy +
-(Optional) -

We used prometheus to fetch the metrics resources until the pd could provide it. -MetricsUrl represents the url to fetch the metrics info

+
+

ImagePullPolicy of TiDB cluster Pods

-monitor
+imagePullSecrets
- -TidbMonitorRef + +[]Kubernetes core/v1.LocalObjectReference
(Optional) -

TidbMonitorRef describe the target TidbMonitor, when MetricsUrl and Monitor are both set, -Operator will use MetricsUrl

+

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-tikv
+configUpdateStrategy
- -TikvAutoScalerSpec + +ConfigUpdateStrategy
-(Optional) -

TiKV represents the auto-scaling spec for tikv

+

ConfigUpdateStrategy determines how the configuration change is applied to the cluster. +UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the +cluster component is needed to reload the configuration change. +UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the +related components to use the new ConfigMap, that is, the new configuration will be applied automatically.

-tidb
+enablePVReclaim
- -TidbAutoScalerSpec - +bool
(Optional) -

TiDB represents the auto-scaling spec for tidb

+

Whether enable PVC reclaim for orphan PVC left by statefulset scale-in +Optional: Defaults to false

-

TidbClusterAutoSclaerStatus

-

-(Appears on: -TidbClusterAutoScaler) -

-

-

TidbClusterAutoSclaerStatus describe the whole status

-

- - - - - - - - - -
FieldDescription
-tikv
+tlsCluster
- -TikvAutoScalerStatus + +TLSCluster
(Optional) -

Tikv describes the status for the tikv in the last auto-scaling reconciliation

+

Whether enable the TLS connection between TiDB server components +Optional: Defaults to nil

-tidb
+hostNetwork
- -TidbAutoScalerStatus - +bool
(Optional) -

Tidb describes the status for the tidb in the last auto-scaling reconciliation

+

Whether Hostnetwork is enabled for TiDB cluster Pods +Optional: Defaults to false

-

TidbClusterCondition

-

-(Appears on: -TidbClusterStatus) -

-

-

TidbClusterCondition describes the state of a tidb cluster at a certain point.

-

- - - - - - - - - -
FieldDescription
-type
+affinity
- -TidbClusterConditionType + +Kubernetes core/v1.Affinity
-

Type of the condition.

+(Optional) +

Affinity of TiDB cluster Pods

-status
+priorityClassName
- -Kubernetes core/v1.ConditionStatus - +string
-

Status of the condition, one of True, False, Unknown.

+(Optional) +

PriorityClassName of TiDB cluster Pods +Optional: Defaults to omitted

-lastUpdateTime
+nodeSelector
- -Kubernetes meta/v1.Time - +map[string]string
-

The last time this condition was updated.

+(Optional) +

Base node selectors of TiDB cluster Pods, components may add or override selectors upon this respectively

-lastTransitionTime
+annotations
- -Kubernetes meta/v1.Time - +map[string]string
(Optional) -

Last time the condition transitioned from one status to another.

+

Base annotations of TiDB cluster Pods, components may add or override selectors upon this respectively

-reason
+tolerations
-string + +[]Kubernetes core/v1.Toleration +
(Optional) -

The reason for the condition’s last transition.

+

Base tolerations of TiDB cluster Pods, components may add more tolerations upon this respectively

-message
+timezone
string
(Optional) -

A human readable message indicating details about the transition.

+

Time zone of TiDB cluster Pods +Optional: Defaults to UTC

-

TidbClusterConditionType

-

-(Appears on: -TidbClusterCondition) -

-

-

TidbClusterConditionType represents a tidb cluster condition value.

-

-

TidbClusterRef

-

-(Appears on: -TidbClusterAutoScalerSpec, -TidbInitializerSpec, -TidbMonitorSpec) -

-

-

TidbClusterRef reference to a TidbCluster

-

- - - - - - - -
FieldDescription
-namespace
+services
-string + +[]Service +
-(Optional) -

Namespace is the namespace that TidbCluster object locates, -default to the same namespace with TidbMonitor

+

Services list non-headless services type used in TidbCluster +Deprecated

-name
+enableDynamicConfiguration
-string +bool
-

Name is the name of TidbCluster object

+(Optional) +

EnableDynamicConfiguration indicates whether DynamicConfiguration is enabled for the tidbcluster

-

TidbClusterSpec

+

TidbClusterStatus

(Appears on: TidbCluster)

-

TidbClusterSpec describes the attributes that a user creates on a tidb cluster

+

TidbClusterStatus represents the current status of a tidb cluster.

@@ -15847,363 +17495,310 @@ string - - - - - - - - - - - - + +
-discovery
+clusterID
- -DiscoverySpec - +string
-

Discovery spec

pd
- -PDSpec - - -
-(Optional) -

PD cluster spec

-
-tidb
- - -TiDBSpec + +PDStatus
-(Optional) -

TiDB cluster spec

tikv
- -TiKVSpec - - -
-(Optional) -

TiKV cluster spec

-
-tiflash
- - -TiFlashSpec - - -
-(Optional) -

TiFlash cluster spec

-
-ticdc
- - -TiCDCSpec + +TiKVStatus
-(Optional) -

TiCDC cluster spec

-pump
+tidb
- -PumpSpec + +TiDBStatus
-(Optional) -

Pump cluster spec

-helper
+Pump
- -HelperSpec + +PumpStatus
-(Optional) -

Helper spec

-paused
+tiflash
-bool + +TiFlashStatus +
-(Optional) -

Indicates that the tidb cluster is paused and will not be processed by -the controller.

-version
+ticdc
-string + +TiCDCStatus +
-(Optional) -

TODO: remove optional after defaulting logic introduced -TiDB cluster version

-schedulerName
+monitor
-string + +TidbMonitorRef +
-

SchedulerName of TiDB cluster Pods

-pvReclaimPolicy
+auto-scaler,omitempyt
- -Kubernetes core/v1.PersistentVolumeReclaimPolicy + +TidbClusterAutoScalerRef
-

Persistent volume reclaim policy applied to the PVs that consumed by TiDB cluster

-imagePullPolicy
+conditions
- -Kubernetes core/v1.PullPolicy + +[]TidbClusterCondition
-

ImagePullPolicy of TiDB cluster Pods

+(Optional) +

Represents the latest available observations of a tidb cluster’s state.

-imagePullSecrets
+tikv-groups
- -[]Kubernetes core/v1.LocalObjectReference + +[]GroupRef
(Optional) -

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-configUpdateStrategy
+tidb-groups
- -ConfigUpdateStrategy + +[]GroupRef
-

ConfigUpdateStrategy determines how the configuration change is applied to the cluster. -UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the -cluster component is needed to reload the configuration change. -UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the -related components to use the new ConfigMap, that is, the new configuration will be applied automatically.

+(Optional)
+

TidbInitializerSpec

+

+(Appears on: +TidbInitializer) +

+

+

TidbInitializer spec encode the desired state of tidb initializer Job

+

+ + + + + + + +
FieldDescription
-enablePVReclaim
+image
-bool +string
-(Optional) -

Whether enable PVC reclaim for orphan PVC left by statefulset scale-in -Optional: Defaults to false

-tlsCluster
+cluster
- -TLSCluster + +TidbClusterRef
-(Optional) -

Whether enable the TLS connection between TiDB server components -Optional: Defaults to nil

-hostNetwork
+imagePullPolicy
-bool + +Kubernetes core/v1.PullPolicy +
(Optional) -

Whether Hostnetwork is enabled for TiDB cluster Pods -Optional: Defaults to false

-affinity
+imagePullSecrets
- -Kubernetes core/v1.Affinity + +[]Kubernetes core/v1.LocalObjectReference
(Optional) -

Affinity of TiDB cluster Pods

+

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-priorityClassName
+permitHost
string
(Optional) -

PriorityClassName of TiDB cluster Pods -Optional: Defaults to omitted

+

permitHost is the host which will only be allowed to connect to the TiDB.

-nodeSelector
+initSql
-map[string]string +string
(Optional) -

Base node selectors of TiDB cluster Pods, components may add or override selectors upon this respectively

+

InitSql is the SQL statements executed after the TiDB cluster is bootstrapped.

-annotations
+initSqlConfigMap
-map[string]string +string
(Optional) -

Base annotations of TiDB cluster Pods, components may add or override selectors upon this respectively

+

InitSqlConfigMapName reference a configmap that provide init-sql, take high precedence than initSql if set

-tolerations
+passwordSecret
- -[]Kubernetes core/v1.Toleration - +string
(Optional) -

Base tolerations of TiDB cluster Pods, components may add more tolerations upon this respectively

-timezone
+resources
-string + +Kubernetes core/v1.ResourceRequirements +
(Optional) -

Time zone of TiDB cluster Pods -Optional: Defaults to UTC

-services
+timezone
- -[]Service - +string
-

Services list non-headless services type used in TidbCluster -Deprecated

+(Optional) +

Time zone of TiDB initializer Pods

-enableDynamicConfiguration
+tlsClientSecretName
-bool +string
(Optional) -

EnableDynamicConfiguration indicates whether DynamicConfiguration is enabled for the tidbcluster

+

TLSClientSecretName is the name of secret which stores tidb server client certificate +Optional: Defaults to nil

-

TidbClusterStatus

+

TidbInitializerStatus

(Appears on: -TidbCluster) +TidbInitializer)

-

TidbClusterStatus represents the current status of a tidb cluster.

@@ -16215,68 +17810,112 @@ bool + +
-clusterID
+JobStatus
-string + +Kubernetes batch/v1.JobStatus +
+

+(Members of JobStatus are embedded into this type.) +

-pd
+phase
- -PDStatus + +InitializePhase
+

Phase is a user readable state inferred from the underlying Job status and TidbCluster status

+

TidbMonitorRef

+

+(Appears on: +DMClusterStatus, +TidbClusterAutoScalerSpec, +TidbClusterStatus) +

+

+

TidbMonitorRef reference to a TidbMonitor

+

+ + + + + + + + + +
FieldDescription
-tikv
+namespace
- -TiKVStatus - +string
+(Optional) +

Namespace is the namespace that TidbMonitor object locates, +default to the same namespace with TidbClusterAutoScaler

-tidb
+name
- -TiDBStatus - +string
+

Name is the name of TidbMonitor object

-Pump
+grafanaEnabled
- -PumpStatus - +bool
+(Optional) +

GrafanaEnabled indicate whether the grafana is enabled for this target tidbmonitor

+

TidbMonitorSpec

+

+(Appears on: +TidbMonitor) +

+

+

TidbMonitor spec encode the desired state of tidb monitoring component

+

+ + + + + + + + @@ -16285,10 +17924,10 @@ TiFlashStatus @@ -16297,22 +17936,23 @@ TiCDCStatus @@ -16321,91 +17961,71 @@ TidbClusterAutoScalerRef - -
FieldDescription
-tiflash
+clusters
- -TiFlashStatus + +[]TidbClusterRef
-ticdc
+prometheus
- -TiCDCStatus + +PrometheusSpec
-monitor
+grafana
- -TidbMonitorRef + +GrafanaSpec
+(Optional)
-auto-scaler,omitempyt
+reloader
- -TidbClusterAutoScalerRef + +ReloaderSpec
-conditions
+initializer
- -[]TidbClusterCondition + +InitializerSpec
-(Optional) -

Represents the latest available observations of a tidb cluster’s state.

-tikv-groups
+pvReclaimPolicy
- -[]GroupRef + +Kubernetes core/v1.PersistentVolumeReclaimPolicy
-(Optional) +

Persistent volume reclaim policy applied to the PVs that consumed by TiDB cluster

-tidb-groups
+imagePullPolicy
- -[]GroupRef + +Kubernetes core/v1.PullPolicy
-(Optional)
-

TidbInitializerSpec

-

-(Appears on: -TidbInitializer) -

-

-

TidbInitializer spec encode the desired state of tidb initializer Job

-

- - - - - - - -
FieldDescription
-image
+imagePullSecrets
-string + +[]Kubernetes core/v1.LocalObjectReference +
+(Optional) +

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-cluster
+persistent
- -TidbClusterRef - +bool
+(Optional)
-imagePullPolicy
+storageClassName
- -Kubernetes core/v1.PullPolicy - +string
@@ -16414,111 +18034,119 @@ Kubernetes core/v1.PullPolicy
-imagePullSecrets
+storage
- -[]Kubernetes core/v1.LocalObjectReference - +string
(Optional) -

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-permitHost
+nodeSelector
-string +map[string]string
(Optional) -

permitHost is the host which will only be allowed to connect to the TiDB.

-initSql
+annotations
-string +map[string]string
(Optional) -

InitSql is the SQL statements executed after the TiDB cluster is bootstrapped.

-initSqlConfigMap
+tolerations
-string + +[]Kubernetes core/v1.Toleration +
(Optional) -

InitSqlConfigMapName reference a configmap that provide init-sql, take high precedence than initSql if set

-passwordSecret
+kubePrometheusURL
string
(Optional) +

kubePrometheusURL is where tidb-monitoring get the common metrics of kube-prometheus. +Ref: https://github.com/coreos/kube-prometheus

-resources
+alertmanagerURL
- -Kubernetes core/v1.ResourceRequirements - +string
(Optional) +

alertmanagerURL is where tidb-monitoring push alerts to. +Ref: https://prometheus.io/docs/alerting/alertmanager/

-timezone
+alertManagerRulesVersion
string
(Optional) -

Time zone of TiDB initializer Pods

+

alertManagerRulesVersion is the version of the tidb cluster that used for alert rules. +default to current tidb cluster version, for example: v3.0.15

-tlsClientSecretName
+additionalContainers
-string + +[]Kubernetes core/v1.Container +
(Optional) -

TLSClientSecretName is the name of secret which stores tidb server client certificate -Optional: Defaults to nil

-

TidbInitializerStatus

+

TidbMonitorStatus

(Appears on: -TidbInitializer) +TidbMonitor) +

+

+

TODO: sync status

+

+

TikvAutoScalerSpec

+

+(Appears on: +TidbClusterAutoScalerSpec)

+

TikvAutoScalerSpec describes the spec for tikv auto-scaling

@@ -16530,42 +18158,28 @@ Optional: Defaults to nil

- - - -
-JobStatus
+BasicAutoScalerSpec
- -Kubernetes batch/v1.JobStatus + +BasicAutoScalerSpec

-(Members of JobStatus are embedded into this type.) +(Members of BasicAutoScalerSpec are embedded into this type.)

-phase
- - -InitializePhase - - -
-

Phase is a user readable state inferred from the underlying Job status and TidbCluster status

-
-

TidbMonitorRef

+

TikvAutoScalerStatus

(Appears on: -TidbClusterAutoScalerSpec, -TidbClusterStatus) +TidbClusterAutoSclaerStatus)

-

TidbMonitorRef reference to a TidbMonitor

+

TikvAutoScalerStatus describe the auto-scaling status of tikv

@@ -16577,49 +18191,28 @@ InitializePhase - - - - - - - -
-namespace
- -string - -
-(Optional) -

Namespace is the namespace that TidbMonitor object locates, -default to the same namespace with TidbClusterAutoScaler

-
-name
- -string - -
-

Name is the name of TidbMonitor object

-
-grafanaEnabled
+BasicAutoScalerStatus
-bool + +BasicAutoScalerStatus +
-(Optional) -

GrafanaEnabled indicate whether the grafana is enabled for this target tidbmonitor

+

+(Members of BasicAutoScalerStatus are embedded into this type.) +

-

TidbMonitorSpec

+

TxnLocalLatches

(Appears on: -TidbMonitor) +TiDBConfig)

-

TidbMonitor spec encode the desired state of tidb monitoring component

+

TxnLocalLatches is the TxnLocalLatches section of the config.

@@ -16631,60 +18224,50 @@ bool - - - - - - - + +
-clusters
- - -[]TidbClusterRef - - -
-
-prometheus
+enabled
- -PrometheusSpec - +bool
+(Optional)
-grafana
+capacity
- -GrafanaSpec - +uint
(Optional)
-reloader
- - -ReloaderSpec - - -
-
+

UnjoinedMember

+

+(Appears on: +MasterStatus, +PDStatus) +

+

+

UnjoinedMember is the pd unjoin cluster member information

+

+ + + + + + + + +
FieldDescription
-initializer
+podName
- -InitializerSpec - +string
@@ -16692,48 +18275,45 @@ InitializerSpec
-pvReclaimPolicy
+pvcUID
- -Kubernetes core/v1.PersistentVolumeReclaimPolicy - +k8s.io/apimachinery/pkg/types.UID
-

Persistent volume reclaim policy applied to the PVs that consumed by TiDB cluster

-imagePullPolicy
+createdAt
- -Kubernetes core/v1.PullPolicy + +Kubernetes meta/v1.Time
+

User

+

+

User is the configuration of users.

+

+ + - - + + + + + +
-imagePullSecrets
- - -[]Kubernetes core/v1.LocalObjectReference - - -
-(Optional) -

ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

-
FieldDescription
-persistent
+password
-bool +string
@@ -16742,7 +18322,7 @@ bool
-storageClassName
+profile
string @@ -16753,7 +18333,7 @@ string
-storage
+quota
string @@ -16764,108 +18344,108 @@ string
-nodeSelector
+networks
-map[string]string + +Networks +
(Optional)
+

WorkerConfig

+

+(Appears on: +WorkerSpec) +

+

+

WorkerConfig is the configuration of dm-worker-server

+

+ + - - + + + +
-annotations
- -map[string]string - -
-(Optional) -FieldDescription
-tolerations
+log-level
- -[]Kubernetes core/v1.Toleration - +string
(Optional) +

Log level. +Optional: Defaults to info

-kubePrometheusURL
+log-file
string
(Optional) -

kubePrometheusURL is where tidb-monitoring get the common metrics of kube-prometheus. -Ref: https://github.com/coreos/kube-prometheus

+

File log config.

-alertmanagerURL
+log-format
string
(Optional) -

alertmanagerURL is where tidb-monitoring push alerts to. -Ref: https://prometheus.io/docs/alerting/alertmanager/

+

Log format. one of json or text.

-alertManagerRulesVersion
+keepalive-ttl
-string +int64
(Optional) -

alertManagerRulesVersion is the version of the tidb cluster that used for alert rules. -default to current tidb cluster version, for example: v3.0.15

+

KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd +Optional: Defaults to 10

-additionalContainers
+DMSecurityConfig
- -[]Kubernetes core/v1.Container + +DMSecurityConfig
(Optional) +

dm-worker’s security config

-

TidbMonitorStatus

+

WorkerMember

(Appears on: -TidbMonitor) -

-

-

TODO: sync status

-

-

TikvAutoScalerSpec

-

-(Appears on: -TidbClusterAutoScalerSpec) +WorkerStatus)

-

TikvAutoScalerSpec describes the spec for tikv auto-scaling

+

WorkerMember is DM Worker status

@@ -16877,28 +18457,33 @@ default to current tidb cluster version, for example: v3.0.15

+ + + +
-BasicAutoScalerSpec
+podName
- -BasicAutoScalerSpec - +string + +
+
+id
+ +string
-

-(Members of BasicAutoScalerSpec are embedded into this type.) -

-

TikvAutoScalerStatus

+

WorkerSpec

(Appears on: -TidbClusterAutoSclaerStatus) +DMClusterSpec)

-

TikvAutoScalerStatus describe the auto-scaling status of tikv

+

WorkerSpec contains details of dm-worker members

@@ -16910,114 +18495,113 @@ BasicAutoScalerSpec - -
-BasicAutoScalerStatus
+ComponentSpec
- -BasicAutoScalerStatus + +ComponentSpec

-(Members of BasicAutoScalerStatus are embedded into this type.) +(Members of ComponentSpec are embedded into this type.)

-

TxnLocalLatches

-

-(Appears on: -TiDBConfig) -

+ + +ResourceRequirements
+ + +Kubernetes core/v1.ResourceRequirements + + + +

-

TxnLocalLatches is the TxnLocalLatches section of the config.

+(Members of ResourceRequirements are embedded into this type.)

- - - - - + - - - -
FieldDescription
-enabled
+replicas
-bool +int32
-(Optional) +

The desired ready replicas

-capacity
+baseImage
-uint +string
(Optional) +

TODO: remove optional after defaulting introduced +Base image of the component, image tag is now allowed during validation

-

UnjoinedMember

-

-(Appears on: -PDStatus) -

-

-

UnjoinedMember is the pd unjoin cluster member information

-

- - - - - - - -
FieldDescription
-podName
+storageClassName
string
+(Optional) +

The storageClassName of the persistent volume for dm-worker data storage. +Defaults to Kubernetes default storage class.

-pvcUID
+dataSubDir
-k8s.io/apimachinery/pkg/types.UID +string
+(Optional) +

Subdirectory within the volume to store dm-worker Data. By default, the data +is stored in the root directory of volume which is mounted at +/var/lib/dm-worker. +Specifying this will change the data directory to a subdirectory, e.g. +/var/lib/dm-worker/data if you set the value to “data”. +It’s dangerous to change this value for a running cluster as it will +upgrade your cluster to use a new storage directory. +Defaults to “” (volume’s root).

-createdAt
+config
- -Kubernetes meta/v1.Time + +WorkerConfig
+(Optional) +

Config is the Configuration of dm-worker-servers

-

User

+

WorkerStatus

-

User is the configuration of users.

+(Appears on: +DMClusterStatus) +

+

+

WorkerStatus is dm-worker status

@@ -17029,48 +18613,48 @@ Kubernetes meta/v1.Time diff --git a/pkg/apis/pingcap/v1alpha1/crd_kinds.go b/pkg/apis/pingcap/v1alpha1/crd_kinds.go index c92c35ee0f..cbb63f0d00 100644 --- a/pkg/apis/pingcap/v1alpha1/crd_kinds.go +++ b/pkg/apis/pingcap/v1alpha1/crd_kinds.go @@ -25,6 +25,10 @@ const ( TiDBClusterKind = "TidbCluster" TiDBClusterKindKey = "tidbcluster" + DMClusterName = "dmclusters" + DMCLusterKind = "DMCluster" + DMClusterKindKey = "dmcluster" + BackupName = "backups" BackupKind = "Backup" BackupKindKey = "backup" @@ -71,6 +75,7 @@ type CrdKind struct { type CrdKinds struct { KindsString string TiDBCluster CrdKind + DMCluster CrdKind Backup CrdKind Restore CrdKind BackupSchedule CrdKind @@ -84,6 +89,7 @@ type CrdKinds struct { var DefaultCrdKinds = CrdKinds{ KindsString: "", TiDBCluster: CrdKind{Plural: TiDBClusterName, Kind: TiDBClusterKind, ShortNames: []string{"tc"}, SpecName: SpecPath + TiDBClusterKind}, + DMCluster: CrdKind{Plural: DMClusterName, Kind: DMCLusterKind, ShortNames: []string{"dc"}, SpecName: SpecPath + DMCLusterKind}, Backup: CrdKind{Plural: BackupName, Kind: BackupKind, ShortNames: []string{"bk"}, SpecName: SpecPath + BackupKind}, Restore: CrdKind{Plural: RestoreName, Kind: RestoreKind, ShortNames: []string{"rt"}, SpecName: SpecPath + RestoreKind}, BackupSchedule: CrdKind{Plural: BackupScheduleName, Kind: BackupScheduleKind, ShortNames: []string{"bks"}, SpecName: SpecPath + BackupScheduleKind}, diff --git a/pkg/apis/pingcap/v1alpha1/dm_config.go b/pkg/apis/pingcap/v1alpha1/dm_config.go new file mode 100644 index 0000000000..aa500942e0 --- /dev/null +++ b/pkg/apis/pingcap/v1alpha1/dm_config.go @@ -0,0 +1,98 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +// Maintain a copy of MasterConfig to make it more friendly with the kubernetes API: +// +// - add 'omitempty' json and toml tag to avoid passing the empty value of primitive types to dm-master-server, e.g. 0 of int +// - change all numeric type to pointer, e.g. uint -> *uint, so that 'omitempty' could work properly +// - add openapi-gen tags so that the kubernetes-style OpenAPI schema could be properly generated +// - make the whole config struct deepcopy friendly +// +// only adding field is allowed, DO NOT change existing field definition or remove field. +// some fields maybe illegal for certain version of DM, this should be addressed in the ValidationWebhook. + +// initially copied from dm-master v2.0.0-rc + +// MasterConfig is the configuration of dm-master-server +// +k8s:openapi-gen=true +type MasterConfig struct { + // Log level. + // Optional: Defaults to info + // +optional + LogLevel *string `toml:"log-level" json:"log-level"` + // File log config. + // +optional + LogFile *string `toml:"log-file" json:"log-file"` + // Log format. one of json or text. + // +optional + LogFormat *string `toml:"log-format" json:"log-format"` + + // RPC timeout when dm-master request to dm-worker + // Optional: Defaults to 30s + // +optional + RPCTimeoutStr *string `toml:"rpc-timeout" json:"rpc-timeout"` + // RPC agent rate limit when dm-master request to dm-worker + // Optional: Defaults to 10 + // +optional + RPCRateLimit *float64 `toml:"rpc-rate-limit" json:"rpc-rate-limit"` + // RPC agent rate burst when dm-master request to dm-worker + // Optional: Defaults to 40 + // +optional + RPCRateBurst *int `toml:"rpc-rate-burst" json:"rpc-rate-burst"` + // dm-master's security config + // +optional + // +k8s:openapi-gen=false + DMSecurityConfig +} + +// WorkerConfig is the configuration of dm-worker-server +// +k8s:openapi-gen=true +type WorkerConfig struct { + // Log level. + // Optional: Defaults to info + // +optional + LogLevel *string `toml:"log-level" json:"log-level"` + // File log config. + // +optional + LogFile *string `toml:"log-file" json:"log-file"` + // Log format. one of json or text. + // +optional + LogFormat *string `toml:"log-format" json:"log-format"` + + // KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd + // Optional: Defaults to 10 + // +optional + KeepAliveTTL *int64 `toml:"keepalive-ttl" json:"keepalive-ttl"` + // dm-worker's security config + // +optional + DMSecurityConfig +} + +// DM common security config +type DMSecurityConfig struct { + // SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty + // +optional + SSLCA *string `toml:"ssl-ca" json:"ssl-ca" yaml:"ssl-ca"` + // SSLCert is the path of file that contains X509 certificate in PEM format. + // +optional + SSLCert *string `toml:"ssl-cert" json:"ssl-cert" yaml:"ssl-cert"` + // SSLKey is the path of file that contains X509 key in PEM format. + // +optional + SSLKey *string `toml:"ssl-key" json:"ssl-key" yaml:"ssl-key"` + // CertAllowedCN is the Common Name that allowed + // +optional + // +k8s:openapi-gen=false + CertAllowedCN []string `toml:"cert-allowed-cn" json:"cert-allowed-cn" yaml:"cert-allowed-cn"` +} diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index e0d3f69871..850572d62d 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -40,6 +40,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.CommonConfig": schema_pkg_apis_pingcap_v1alpha1_CommonConfig(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ComponentSpec": schema_pkg_apis_pingcap_v1alpha1_ComponentSpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ConfigMapRef": schema_pkg_apis_pingcap_v1alpha1_ConfigMapRef(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMCluster": schema_pkg_apis_pingcap_v1alpha1_DMCluster(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMClusterSpec": schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec": schema_pkg_apis_pingcap_v1alpha1_DMDiscoverySpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DashboardConfig": schema_pkg_apis_pingcap_v1alpha1_DashboardConfig(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DiscoverySpec": schema_pkg_apis_pingcap_v1alpha1_DiscoverySpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DumplingConfig": schema_pkg_apis_pingcap_v1alpha1_DumplingConfig(ref), @@ -55,8 +58,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.IsolationRead": schema_pkg_apis_pingcap_v1alpha1_IsolationRead(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.Log": schema_pkg_apis_pingcap_v1alpha1_Log(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.LogTailerSpec": schema_pkg_apis_pingcap_v1alpha1_LogTailerSpec(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterConfig": schema_pkg_apis_pingcap_v1alpha1_MasterConfig(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterKeyFileConfig": schema_pkg_apis_pingcap_v1alpha1_MasterKeyFileConfig(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterKeyKMSConfig": schema_pkg_apis_pingcap_v1alpha1_MasterKeyKMSConfig(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterSpec": schema_pkg_apis_pingcap_v1alpha1_MasterSpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MetricsStatus": schema_pkg_apis_pingcap_v1alpha1_MetricsStatus(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MonitorContainer": schema_pkg_apis_pingcap_v1alpha1_MonitorContainer(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.OpenTracing": schema_pkg_apis_pingcap_v1alpha1_OpenTracing(ref), @@ -155,6 +160,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TikvAutoScalerSpec": schema_pkg_apis_pingcap_v1alpha1_TikvAutoScalerSpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TikvAutoScalerStatus": schema_pkg_apis_pingcap_v1alpha1_TikvAutoScalerStatus(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TxnLocalLatches": schema_pkg_apis_pingcap_v1alpha1_TxnLocalLatches(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerConfig": schema_pkg_apis_pingcap_v1alpha1_WorkerConfig(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerSpec": schema_pkg_apis_pingcap_v1alpha1_WorkerSpec(ref), "k8s.io/api/core/v1.AWSElasticBlockStoreVolumeSource": schema_k8sio_api_core_v1_AWSElasticBlockStoreVolumeSource(ref), "k8s.io/api/core/v1.Affinity": schema_k8sio_api_core_v1_Affinity(ref), "k8s.io/api/core/v1.AttachedVolume": schema_k8sio_api_core_v1_AttachedVolume(ref), @@ -1280,6 +1287,237 @@ func schema_pkg_apis_pingcap_v1alpha1_ConfigMapRef(ref common.ReferenceCallback) } } +func schema_pkg_apis_pingcap_v1alpha1_DMCluster(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DMCluster is the control script's spec", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec defines the behavior of a dm cluster", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMClusterSpec"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMClusterSpec"}, + } +} + +func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DMClusterSpec describes the attributes that a user creates on a dm cluster", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "discovery": { + SchemaProps: spec.SchemaProps{ + Description: "Discovery spec", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec"), + }, + }, + "dm_master": { + SchemaProps: spec.SchemaProps{ + Description: "dm-master cluster spec", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterSpec"), + }, + }, + "dm_worker": { + SchemaProps: spec.SchemaProps{ + Description: "dm-worker cluster spec", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerSpec"), + }, + }, + "paused": { + SchemaProps: spec.SchemaProps{ + Description: "Indicates that the dm cluster is paused and will not be processed by the controller.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "version": { + SchemaProps: spec.SchemaProps{ + Description: "dm cluster version", + Type: []string{"string"}, + Format: "", + }, + }, + "schedulerName": { + SchemaProps: spec.SchemaProps{ + Description: "SchedulerName of DM cluster Pods", + Type: []string{"string"}, + Format: "", + }, + }, + "pvReclaimPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "Persistent volume reclaim policy applied to the PVs that consumed by DM cluster", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "ImagePullPolicy of DM cluster Pods", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullSecrets": { + SchemaProps: spec.SchemaProps{ + Description: "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), + }, + }, + }, + }, + }, + "configUpdateStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "ConfigUpdateStrategy determines how the configuration change is applied to the cluster. UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the cluster component is needed to reload the configuration change. UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the related components to use the new ConfigMap, that is, the new configuration will be applied automatically.", + Type: []string{"string"}, + Format: "", + }, + }, + "enablePVReclaim": { + SchemaProps: spec.SchemaProps{ + Description: "Whether enable PVC reclaim for orphan PVC left by statefulset scale-in Optional: Defaults to false", + Type: []string{"boolean"}, + Format: "", + }, + }, + "tlsCluster": { + SchemaProps: spec.SchemaProps{ + Description: "Whether enable the TLS connection between DM server components Optional: Defaults to nil", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TLSCluster"), + }, + }, + "nodeSelector": { + SchemaProps: spec.SchemaProps{ + Description: "Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "annotations": { + SchemaProps: spec.SchemaProps{ + Description: "Base annotations of DM cluster Pods, components may add or override selectors upon this respectively", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "tolerations": { + SchemaProps: spec.SchemaProps{ + Description: "Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Toleration"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterSpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TLSCluster", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerSpec", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.Toleration"}, + } +} + +func schema_pkg_apis_pingcap_v1alpha1_DMDiscoverySpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DMDiscoverySpec contains details of Discovery members for dm", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "limits": { + SchemaProps: spec.SchemaProps{ + Description: "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "requests": { + SchemaProps: spec.SchemaProps{ + Description: "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "host": { + SchemaProps: spec.SchemaProps{ + Description: "Host indicates the existed TiDB discovery host. If not specified, dm cluster will start a new one", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"host"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + } +} + func schema_pkg_apis_pingcap_v1alpha1_DashboardConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1961,6 +2199,61 @@ func schema_pkg_apis_pingcap_v1alpha1_LogTailerSpec(ref common.ReferenceCallback } } +func schema_pkg_apis_pingcap_v1alpha1_MasterConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MasterConfig is the configuration of dm-master-server", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "log-level": { + SchemaProps: spec.SchemaProps{ + Description: "Log level. Optional: Defaults to info", + Type: []string{"string"}, + Format: "", + }, + }, + "log-file": { + SchemaProps: spec.SchemaProps{ + Description: "File log config.", + Type: []string{"string"}, + Format: "", + }, + }, + "log-format": { + SchemaProps: spec.SchemaProps{ + Description: "Log format. one of json or text.", + Type: []string{"string"}, + Format: "", + }, + }, + "rpc-timeout": { + SchemaProps: spec.SchemaProps{ + Description: "RPC timeout when dm-master request to dm-worker Optional: Defaults to 30s", + Type: []string{"string"}, + Format: "", + }, + }, + "rpc-rate-limit": { + SchemaProps: spec.SchemaProps{ + Description: "RPC agent rate limit when dm-master request to dm-worker Optional: Defaults to 10", + Type: []string{"number"}, + Format: "double", + }, + }, + "rpc-rate-burst": { + SchemaProps: spec.SchemaProps{ + Description: "RPC agent rate burst when dm-master request to dm-worker Optional: Defaults to 40", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + }, + }, + } +} + func schema_pkg_apis_pingcap_v1alpha1_MasterKeyFileConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -2036,21 +2329,268 @@ func schema_pkg_apis_pingcap_v1alpha1_MasterKeyKMSConfig(ref common.ReferenceCal } } -func schema_pkg_apis_pingcap_v1alpha1_MetricsStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_pkg_apis_pingcap_v1alpha1_MasterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "MetricsStatus describe the basic metrics status in the last auto-scaling reconciliation", + Description: "MasterSpec contains details of dm-master members", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "name": { + "version": { SchemaProps: spec.SchemaProps{ - Description: "Name indicates the metrics name", + Description: "Version of the component. Override the cluster-level version if non-empty Optional: Defaults to cluster-level setting", Type: []string{"string"}, Format: "", }, }, - "currentValue": { + "imagePullPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullSecrets": { + SchemaProps: spec.SchemaProps{ + Description: "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), + }, + }, + }, + }, + }, + "hostNetwork": { + SchemaProps: spec.SchemaProps{ + Description: "Whether Hostnetwork of the component is enabled. Override the cluster-level setting if present Optional: Defaults to cluster-level setting", + Type: []string{"boolean"}, + Format: "", + }, + }, + "affinity": { + SchemaProps: spec.SchemaProps{ + Description: "Affinity of the component. Override the cluster-level one if present Optional: Defaults to cluster-level setting", + Ref: ref("k8s.io/api/core/v1.Affinity"), + }, + }, + "priorityClassName": { + SchemaProps: spec.SchemaProps{ + Description: "PriorityClassName of the component. Override the cluster-level one if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "schedulerName": { + SchemaProps: spec.SchemaProps{ + Description: "SchedulerName of the component. Override the cluster-level one if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "nodeSelector": { + SchemaProps: spec.SchemaProps{ + Description: "NodeSelector of the component. Merged into the cluster-level nodeSelector if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "annotations": { + SchemaProps: spec.SchemaProps{ + Description: "Annotations of the component. Merged into the cluster-level annotations if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "tolerations": { + SchemaProps: spec.SchemaProps{ + Description: "Tolerations of the component. Override the cluster-level tolerations if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Toleration"), + }, + }, + }, + }, + }, + "podSecurityContext": { + SchemaProps: spec.SchemaProps{ + Description: "PodSecurityContext of the component", + Ref: ref("k8s.io/api/core/v1.PodSecurityContext"), + }, + }, + "configUpdateStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "ConfigUpdateStrategy of the component. Override the cluster-level updateStrategy if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "env": { + SchemaProps: spec.SchemaProps{ + Description: "List of environment variables to set in the container, like v1.Container.Env. Note that following env names cannot be used and may be overrided by tidb-operator built envs. - NAMESPACE - TZ - SERVICE_NAME - PEER_SERVICE_NAME - HEADLESS_SERVICE_NAME - SET_NAME - HOSTNAME - CLUSTER_NAME - POD_NAME - BINLOG_ENABLED - SLOW_LOG_FILE", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.EnvVar"), + }, + }, + }, + }, + }, + "additionalContainers": { + SchemaProps: spec.SchemaProps{ + Description: "Additional containers of the component.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Container"), + }, + }, + }, + }, + }, + "additionalVolumes": { + SchemaProps: spec.SchemaProps{ + Description: "Additional volumes of component pod. Currently this only supports additional volume mounts for sidecar containers.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Volume"), + }, + }, + }, + }, + }, + "terminationGracePeriodSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "limits": { + SchemaProps: spec.SchemaProps{ + Description: "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "requests": { + SchemaProps: spec.SchemaProps{ + Description: "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "replicas": { + SchemaProps: spec.SchemaProps{ + Description: "The desired ready replicas", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "baseImage": { + SchemaProps: spec.SchemaProps{ + Description: "Base image of the component, image tag is now allowed during validation", + Type: []string{"string"}, + Format: "", + }, + }, + "service": { + SchemaProps: spec.SchemaProps{ + Description: "Service defines a Kubernetes service of Master cluster. Optional: Defaults to `.spec.services` in favor of backward compatibility", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ServiceSpec"), + }, + }, + "maxFailoverCount": { + SchemaProps: spec.SchemaProps{ + Description: "MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. Optional: Defaults to 3", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "storageClassName": { + SchemaProps: spec.SchemaProps{ + Description: "The storageClassName of the persistent volume for dm-master data storage. Defaults to Kubernetes default storage class.", + Type: []string{"string"}, + Format: "", + }, + }, + "dataSubDir": { + SchemaProps: spec.SchemaProps{ + Description: "Subdirectory within the volume to store dm-master Data. By default, the data is stored in the root directory of volume which is mounted at /var/lib/dm-master. Specifying this will change the data directory to a subdirectory, e.g. /var/lib/dm-master/data if you set the value to \"data\". It's dangerous to change this value for a running cluster as it will upgrade your cluster to use a new storage directory. Defaults to \"\" (volume's root).", + Type: []string{"string"}, + Format: "", + }, + }, + "config": { + SchemaProps: spec.SchemaProps{ + Description: "Config is the Configuration of dm-master-servers", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterConfig"), + }, + }, + }, + Required: []string{"replicas"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterConfig", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ServiceSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + } +} + +func schema_pkg_apis_pingcap_v1alpha1_MetricsStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MetricsStatus describe the basic metrics status in the last auto-scaling reconciliation", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name indicates the metrics name", + Type: []string{"string"}, + Format: "", + }, + }, + "currentValue": { SchemaProps: spec.SchemaProps{ Description: "CurrentValue indicates the value calculated in the last auto-scaling reconciliation", Type: []string{"string"}, @@ -10137,6 +10677,289 @@ func schema_pkg_apis_pingcap_v1alpha1_TxnLocalLatches(ref common.ReferenceCallba } } +func schema_pkg_apis_pingcap_v1alpha1_WorkerConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "WorkerConfig is the configuration of dm-worker-server", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "log-level": { + SchemaProps: spec.SchemaProps{ + Description: "Log level. Optional: Defaults to info", + Type: []string{"string"}, + Format: "", + }, + }, + "log-file": { + SchemaProps: spec.SchemaProps{ + Description: "File log config.", + Type: []string{"string"}, + Format: "", + }, + }, + "log-format": { + SchemaProps: spec.SchemaProps{ + Description: "Log format. one of json or text.", + Type: []string{"string"}, + Format: "", + }, + }, + "keepalive-ttl": { + SchemaProps: spec.SchemaProps{ + Description: "KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd Optional: Defaults to 10", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "DMSecurityConfig": { + SchemaProps: spec.SchemaProps{ + Description: "dm-worker's security config", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMSecurityConfig"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMSecurityConfig"}, + } +} + +func schema_pkg_apis_pingcap_v1alpha1_WorkerSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "WorkerSpec contains details of dm-worker members", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "version": { + SchemaProps: spec.SchemaProps{ + Description: "Version of the component. Override the cluster-level version if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "imagePullSecrets": { + SchemaProps: spec.SchemaProps{ + Description: "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), + }, + }, + }, + }, + }, + "hostNetwork": { + SchemaProps: spec.SchemaProps{ + Description: "Whether Hostnetwork of the component is enabled. Override the cluster-level setting if present Optional: Defaults to cluster-level setting", + Type: []string{"boolean"}, + Format: "", + }, + }, + "affinity": { + SchemaProps: spec.SchemaProps{ + Description: "Affinity of the component. Override the cluster-level one if present Optional: Defaults to cluster-level setting", + Ref: ref("k8s.io/api/core/v1.Affinity"), + }, + }, + "priorityClassName": { + SchemaProps: spec.SchemaProps{ + Description: "PriorityClassName of the component. Override the cluster-level one if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "schedulerName": { + SchemaProps: spec.SchemaProps{ + Description: "SchedulerName of the component. Override the cluster-level one if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "nodeSelector": { + SchemaProps: spec.SchemaProps{ + Description: "NodeSelector of the component. Merged into the cluster-level nodeSelector if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "annotations": { + SchemaProps: spec.SchemaProps{ + Description: "Annotations of the component. Merged into the cluster-level annotations if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "tolerations": { + SchemaProps: spec.SchemaProps{ + Description: "Tolerations of the component. Override the cluster-level tolerations if non-empty Optional: Defaults to cluster-level setting", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Toleration"), + }, + }, + }, + }, + }, + "podSecurityContext": { + SchemaProps: spec.SchemaProps{ + Description: "PodSecurityContext of the component", + Ref: ref("k8s.io/api/core/v1.PodSecurityContext"), + }, + }, + "configUpdateStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "ConfigUpdateStrategy of the component. Override the cluster-level updateStrategy if present Optional: Defaults to cluster-level setting", + Type: []string{"string"}, + Format: "", + }, + }, + "env": { + SchemaProps: spec.SchemaProps{ + Description: "List of environment variables to set in the container, like v1.Container.Env. Note that following env names cannot be used and may be overrided by tidb-operator built envs. - NAMESPACE - TZ - SERVICE_NAME - PEER_SERVICE_NAME - HEADLESS_SERVICE_NAME - SET_NAME - HOSTNAME - CLUSTER_NAME - POD_NAME - BINLOG_ENABLED - SLOW_LOG_FILE", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.EnvVar"), + }, + }, + }, + }, + }, + "additionalContainers": { + SchemaProps: spec.SchemaProps{ + Description: "Additional containers of the component.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Container"), + }, + }, + }, + }, + }, + "additionalVolumes": { + SchemaProps: spec.SchemaProps{ + Description: "Additional volumes of component pod. Currently this only supports additional volume mounts for sidecar containers.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.Volume"), + }, + }, + }, + }, + }, + "terminationGracePeriodSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "limits": { + SchemaProps: spec.SchemaProps{ + Description: "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "requests": { + SchemaProps: spec.SchemaProps{ + Description: "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "replicas": { + SchemaProps: spec.SchemaProps{ + Description: "The desired ready replicas", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "baseImage": { + SchemaProps: spec.SchemaProps{ + Description: "Base image of the component, image tag is now allowed during validation", + Type: []string{"string"}, + Format: "", + }, + }, + "storageClassName": { + SchemaProps: spec.SchemaProps{ + Description: "The storageClassName of the persistent volume for dm-worker data storage. Defaults to Kubernetes default storage class.", + Type: []string{"string"}, + Format: "", + }, + }, + "dataSubDir": { + SchemaProps: spec.SchemaProps{ + Description: "Subdirectory within the volume to store dm-worker Data. By default, the data is stored in the root directory of volume which is mounted at /var/lib/dm-worker. Specifying this will change the data directory to a subdirectory, e.g. /var/lib/dm-worker/data if you set the value to \"data\". It's dangerous to change this value for a running cluster as it will upgrade your cluster to use a new storage directory. Defaults to \"\" (volume's root).", + Type: []string{"string"}, + Format: "", + }, + }, + "config": { + SchemaProps: spec.SchemaProps{ + Description: "Config is the Configuration of dm-worker-servers", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerConfig"), + }, + }, + }, + Required: []string{"replicas"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerConfig", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + } +} + func schema_k8sio_api_core_v1_AWSElasticBlockStoreVolumeSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 36c7687df9..de46f04ce9 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -47,6 +47,10 @@ const ( TiFlashMemberType MemberType = "tiflash" // TiCDCMemberType is ticdc container type TiCDCMemberType MemberType = "ticdc" + // DMMasterMemberType is dm-master container type + DMMasterMemberType MemberType = "dm-master" + // DMWorkerMemberType is dm-worker container type + DMWorkerMemberType MemberType = "dm-master" // SlowLogTailerMemberType is tidb log tailer container type SlowLogTailerMemberType MemberType = "slowlog" // UnknownMemberType is unknown container type @@ -1437,3 +1441,272 @@ type IngressSpec struct { // +optional TLS []extensionsv1beta1.IngressTLS `json:"tls,omitempty"` } + +// +k8s:openapi-gen=true +// DMCluster is the control script's spec +type DMCluster struct { + metav1.TypeMeta `json:",inline"` + // +k8s:openapi-gen=false + metav1.ObjectMeta `json:"metadata"` + + // Spec defines the behavior of a dm cluster + Spec DMClusterSpec `json:"spec"` + + // +k8s:openapi-gen=false + // Most recently observed status of the dm cluster + Status DMClusterStatus `json:"status"` +} + +// +k8s:openapi-gen=true +// DMDiscoverySpec contains details of Discovery members for dm +type DMDiscoverySpec struct { + corev1.ResourceRequirements `json:",inline"` + // Host indicates the existed TiDB discovery host. If not specified, dm cluster will start a new one + Host string `json:"host"` +} + +// +k8s:openapi-gen=true +// DMClusterSpec describes the attributes that a user creates on a dm cluster +type DMClusterSpec struct { + // Discovery spec + Discovery DMDiscoverySpec `json:"discovery,omitempty"` + + // dm-master cluster spec + // +optional + Master *MasterSpec `json:"dm_master,omitempty"` + + // dm-worker cluster spec + // +optional + Worker *WorkerSpec `json:"dm_worker,omitempty"` + + // Indicates that the dm cluster is paused and will not be processed by + // the controller. + // +optional + Paused bool `json:"paused,omitempty"` + + // TODO: remove optional after defaulting logic introduced + // dm cluster version + // +optional + Version string `json:"version"` + + // SchedulerName of DM cluster Pods + // +kubebuilder:default=tidb-scheduler + SchedulerName string `json:"schedulerName,omitempty"` + + // Persistent volume reclaim policy applied to the PVs that consumed by DM cluster + // +kubebuilder:default=Retain + PVReclaimPolicy *corev1.PersistentVolumeReclaimPolicy `json:"pvReclaimPolicy,omitempty"` + + // ImagePullPolicy of DM cluster Pods + // +kubebuilder:default=IfNotPresent + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + + // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images. + // +optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + + // ConfigUpdateStrategy determines how the configuration change is applied to the cluster. + // UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the + // cluster component is needed to reload the configuration change. + // UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the + // related components to use the new ConfigMap, that is, the new configuration will be applied automatically. + // +kubebuilder:validation:Enum=InPlace,RollingUpdate + // +kubebuilder:default=InPlacne + ConfigUpdateStrategy ConfigUpdateStrategy `json:"configUpdateStrategy,omitempty"` + + // Whether enable PVC reclaim for orphan PVC left by statefulset scale-in + // Optional: Defaults to false + // +optional + EnablePVReclaim *bool `json:"enablePVReclaim,omitempty"` + + // Whether enable the TLS connection between DM server components + // Optional: Defaults to nil + // +optional + TLSCluster *TLSCluster `json:"tlsCluster,omitempty"` + + // Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Base annotations of DM cluster Pods, components may add or override selectors upon this respectively + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + + // Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` +} + +// DMClusterStatus represents the current status of a dm cluster. +type DMClusterStatus struct { + Master MasterStatus `json:"dm_master,omitempty"` + Worker WorkerStatus `json:"dm_worker,omitempty"` + + Monitor *TidbMonitorRef `json:"monitor,omitempty"` + // Represents the latest available observations of a dm cluster's state. + // +optional + Conditions []DMClusterCondition `json:"conditions,omitempty"` +} + +// +k8s:openapi-gen=true +// MasterSpec contains details of dm-master members +type MasterSpec struct { + ComponentSpec `json:",inline"` + corev1.ResourceRequirements `json:",inline"` + + // The desired ready replicas + // +kubebuilder:validation:Minimum=1 + Replicas int32 `json:"replicas"` + + // TODO: remove optional after defaulting introduced + // Base image of the component, image tag is now allowed during validation + // +kubebuilder:default=pingcap/dm-master + // +optional + BaseImage string `json:"baseImage"` + + // Service defines a Kubernetes service of Master cluster. + // Optional: Defaults to `.spec.services` in favor of backward compatibility + // +optional + Service *ServiceSpec `json:"service,omitempty"` + + // MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. + // Optional: Defaults to 3 + // +kubebuilder:validation:Minimum=0 + // +optional + MaxFailoverCount *int32 `json:"maxFailoverCount,omitempty"` + + // The storageClassName of the persistent volume for dm-master data storage. + // Defaults to Kubernetes default storage class. + // +optional + StorageClassName *string `json:"storageClassName,omitempty"` + + // Subdirectory within the volume to store dm-master Data. By default, the data + // is stored in the root directory of volume which is mounted at + // /var/lib/dm-master. + // Specifying this will change the data directory to a subdirectory, e.g. + // /var/lib/dm-master/data if you set the value to "data". + // It's dangerous to change this value for a running cluster as it will + // upgrade your cluster to use a new storage directory. + // Defaults to "" (volume's root). + // +optional + DataSubDir string `json:"dataSubDir,omitempty"` + + // Config is the Configuration of dm-master-servers + // +optional + Config *MasterConfig `json:"config,omitempty"` +} + +// +k8s:openapi-gen=true +// WorkerSpec contains details of dm-worker members +type WorkerSpec struct { + ComponentSpec `json:",inline"` + corev1.ResourceRequirements `json:",inline"` + + // The desired ready replicas + // +kubebuilder:validation:Minimum=1 + Replicas int32 `json:"replicas"` + + // TODO: remove optional after defaulting introduced + // Base image of the component, image tag is now allowed during validation + // +kubebuilder:default=pingcap/dm-wokrer + // +optional + BaseImage string `json:"baseImage"` + + // The storageClassName of the persistent volume for dm-worker data storage. + // Defaults to Kubernetes default storage class. + // +optional + StorageClassName *string `json:"storageClassName,omitempty"` + + // Subdirectory within the volume to store dm-worker Data. By default, the data + // is stored in the root directory of volume which is mounted at + // /var/lib/dm-worker. + // Specifying this will change the data directory to a subdirectory, e.g. + // /var/lib/dm-worker/data if you set the value to "data". + // It's dangerous to change this value for a running cluster as it will + // upgrade your cluster to use a new storage directory. + // Defaults to "" (volume's root). + // +optional + DataSubDir string `json:"dataSubDir,omitempty"` + + // Config is the Configuration of dm-worker-servers + // +optional + Config *WorkerConfig `json:"config,omitempty"` +} + +// DMClusterCondition is dm cluster condition +type DMClusterCondition struct { + // Type of the condition. + Type TidbClusterConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // The last time this condition was updated. + LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` + // Last time the condition transitioned from one status to another. + // +optional + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + // +optional + Reason string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + // +optional + Message string `json:"message,omitempty"` +} + +// DMClusterConditionType represents a dm cluster condition value. +type DMClusterConditionType string + +const ( + // DMClusterReady indicates that the dm cluster is ready or not. + // This is defined as: + // - All statefulsets are up to date (currentRevision == updateRevision). + // - All Master members are healthy. + // - All Worker pods are up. + DMClusterReady DMClusterConditionType = "Ready" +) + +// MasterStatus is dm-master status +type MasterStatus struct { + Synced bool `json:"synced,omitempty"` + Phase MemberPhase `json:"phase,omitempty"` + StatefulSet *apps.StatefulSetStatus `json:"statefulSet,omitempty"` + Members map[string]MasterMember `json:"members,omitempty"` + Leader MasterMember `json:"leader,omitempty"` + FailureMembers map[string]PDFailureMember `json:"failureMembers,omitempty"` + UnjoinedMembers map[string]UnjoinedMember `json:"unjoinedMembers,omitempty"` + Image string `json:"image,omitempty"` +} + +// MasterMember is dm-master member status +type MasterMember struct { + Name string `json:"name"` + // member id is actually a uint64, but apimachinery's json only treats numbers as int64/float64 + // so uint64 may overflow int64 and thus convert to float64 + ID string `json:"id"` + ClientURL string `json:"clientURL"` + Health bool `json:"health"` + // Last time the health transitioned from one to another. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` +} + +// MasterFailureMember is the dm-master failure member information +type MasterFailureMember struct { + PodName string `json:"podName,omitempty"` + MemberID string `json:"memberID,omitempty"` + PVCUID types.UID `json:"pvcUID,omitempty"` + MemberDeleted bool `json:"memberDeleted,omitempty"` + CreatedAt metav1.Time `json:"createdAt,omitempty"` +} + +// WorkerStatus is dm-worker status +type WorkerStatus struct { + Synced bool `json:"synced,omitempty"` + Phase MemberPhase `json:"phase,omitempty"` + StatefulSet *apps.StatefulSetStatus `json:"statefulSet,omitempty"` + Workers map[string]WorkerMember `json:"workers,omitempty"` +} + +// WorkerMember is DM Worker status +type WorkerMember struct { + PodName string `json:"podName,omitempty"` + ID string `json:"id,omitempty"` +} diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index 8b21c17004..7232219884 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -771,6 +771,7 @@ func (in *CrdKind) DeepCopy() *CrdKind { func (in *CrdKinds) DeepCopyInto(out *CrdKinds) { *out = *in in.TiDBCluster.DeepCopyInto(&out.TiDBCluster) + in.DMCluster.DeepCopyInto(&out.DMCluster) in.Backup.DeepCopyInto(&out.Backup) in.Restore.DeepCopyInto(&out.Restore) in.BackupSchedule.DeepCopyInto(&out.BackupSchedule) @@ -819,6 +820,195 @@ func (in *CustomMetric) DeepCopy() *CustomMetric { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMCluster) DeepCopyInto(out *DMCluster) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMCluster. +func (in *DMCluster) DeepCopy() *DMCluster { + if in == nil { + return nil + } + out := new(DMCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMClusterCondition) DeepCopyInto(out *DMClusterCondition) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMClusterCondition. +func (in *DMClusterCondition) DeepCopy() *DMClusterCondition { + if in == nil { + return nil + } + out := new(DMClusterCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMClusterSpec) DeepCopyInto(out *DMClusterSpec) { + *out = *in + in.Discovery.DeepCopyInto(&out.Discovery) + if in.Master != nil { + in, out := &in.Master, &out.Master + *out = new(MasterSpec) + (*in).DeepCopyInto(*out) + } + if in.Worker != nil { + in, out := &in.Worker, &out.Worker + *out = new(WorkerSpec) + (*in).DeepCopyInto(*out) + } + if in.PVReclaimPolicy != nil { + in, out := &in.PVReclaimPolicy, &out.PVReclaimPolicy + *out = new(v1.PersistentVolumeReclaimPolicy) + **out = **in + } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + if in.EnablePVReclaim != nil { + in, out := &in.EnablePVReclaim, &out.EnablePVReclaim + *out = new(bool) + **out = **in + } + if in.TLSCluster != nil { + in, out := &in.TLSCluster, &out.TLSCluster + *out = new(TLSCluster) + **out = **in + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMClusterSpec. +func (in *DMClusterSpec) DeepCopy() *DMClusterSpec { + if in == nil { + return nil + } + out := new(DMClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMClusterStatus) DeepCopyInto(out *DMClusterStatus) { + *out = *in + in.Master.DeepCopyInto(&out.Master) + in.Worker.DeepCopyInto(&out.Worker) + if in.Monitor != nil { + in, out := &in.Monitor, &out.Monitor + *out = new(TidbMonitorRef) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]DMClusterCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMClusterStatus. +func (in *DMClusterStatus) DeepCopy() *DMClusterStatus { + if in == nil { + return nil + } + out := new(DMClusterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMDiscoverySpec) DeepCopyInto(out *DMDiscoverySpec) { + *out = *in + in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMDiscoverySpec. +func (in *DMDiscoverySpec) DeepCopy() *DMDiscoverySpec { + if in == nil { + return nil + } + out := new(DMDiscoverySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMSecurityConfig) DeepCopyInto(out *DMSecurityConfig) { + *out = *in + if in.SSLCA != nil { + in, out := &in.SSLCA, &out.SSLCA + *out = new(string) + **out = **in + } + if in.SSLCert != nil { + in, out := &in.SSLCert, &out.SSLCert + *out = new(string) + **out = **in + } + if in.SSLKey != nil { + in, out := &in.SSLKey, &out.SSLKey + *out = new(string) + **out = **in + } + if in.CertAllowedCN != nil { + in, out := &in.CertAllowedCN, &out.CertAllowedCN + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMSecurityConfig. +func (in *DMSecurityConfig) DeepCopy() *DMSecurityConfig { + if in == nil { + return nil + } + out := new(DMSecurityConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DashboardConfig) DeepCopyInto(out *DashboardConfig) { *out = *in @@ -1715,6 +1905,70 @@ func (in *LogTailerSpec) DeepCopy() *LogTailerSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterConfig) DeepCopyInto(out *MasterConfig) { + *out = *in + if in.LogLevel != nil { + in, out := &in.LogLevel, &out.LogLevel + *out = new(string) + **out = **in + } + if in.LogFile != nil { + in, out := &in.LogFile, &out.LogFile + *out = new(string) + **out = **in + } + if in.LogFormat != nil { + in, out := &in.LogFormat, &out.LogFormat + *out = new(string) + **out = **in + } + if in.RPCTimeoutStr != nil { + in, out := &in.RPCTimeoutStr, &out.RPCTimeoutStr + *out = new(string) + **out = **in + } + if in.RPCRateLimit != nil { + in, out := &in.RPCRateLimit, &out.RPCRateLimit + *out = new(float64) + **out = **in + } + if in.RPCRateBurst != nil { + in, out := &in.RPCRateBurst, &out.RPCRateBurst + *out = new(int) + **out = **in + } + in.DMSecurityConfig.DeepCopyInto(&out.DMSecurityConfig) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterConfig. +func (in *MasterConfig) DeepCopy() *MasterConfig { + if in == nil { + return nil + } + out := new(MasterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterFailureMember) DeepCopyInto(out *MasterFailureMember) { + *out = *in + in.CreatedAt.DeepCopyInto(&out.CreatedAt) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterFailureMember. +func (in *MasterFailureMember) DeepCopy() *MasterFailureMember { + if in == nil { + return nil + } + out := new(MasterFailureMember) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MasterKeyFileConfig) DeepCopyInto(out *MasterKeyFileConfig) { *out = *in @@ -1782,6 +2036,104 @@ func (in *MasterKeyKMSConfig) DeepCopy() *MasterKeyKMSConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterMember) DeepCopyInto(out *MasterMember) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterMember. +func (in *MasterMember) DeepCopy() *MasterMember { + if in == nil { + return nil + } + out := new(MasterMember) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterSpec) DeepCopyInto(out *MasterSpec) { + *out = *in + in.ComponentSpec.DeepCopyInto(&out.ComponentSpec) + in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements) + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ServiceSpec) + (*in).DeepCopyInto(*out) + } + if in.MaxFailoverCount != nil { + in, out := &in.MaxFailoverCount, &out.MaxFailoverCount + *out = new(int32) + **out = **in + } + if in.StorageClassName != nil { + in, out := &in.StorageClassName, &out.StorageClassName + *out = new(string) + **out = **in + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(MasterConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterSpec. +func (in *MasterSpec) DeepCopy() *MasterSpec { + if in == nil { + return nil + } + out := new(MasterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterStatus) DeepCopyInto(out *MasterStatus) { + *out = *in + if in.StatefulSet != nil { + in, out := &in.StatefulSet, &out.StatefulSet + *out = new(appsv1.StatefulSetStatus) + (*in).DeepCopyInto(*out) + } + if in.Members != nil { + in, out := &in.Members, &out.Members + *out = make(map[string]MasterMember, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + in.Leader.DeepCopyInto(&out.Leader) + if in.FailureMembers != nil { + in, out := &in.FailureMembers, &out.FailureMembers + *out = make(map[string]PDFailureMember, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.UnjoinedMembers != nil { + in, out := &in.UnjoinedMembers, &out.UnjoinedMembers + *out = make(map[string]UnjoinedMember, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterStatus. +func (in *MasterStatus) DeepCopy() *MasterStatus { + if in == nil { + return nil + } + out := new(MasterStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetricsStatus) DeepCopyInto(out *MetricsStatus) { *out = *in @@ -7528,3 +7880,112 @@ func (in *User) DeepCopy() *User { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerConfig) DeepCopyInto(out *WorkerConfig) { + *out = *in + if in.LogLevel != nil { + in, out := &in.LogLevel, &out.LogLevel + *out = new(string) + **out = **in + } + if in.LogFile != nil { + in, out := &in.LogFile, &out.LogFile + *out = new(string) + **out = **in + } + if in.LogFormat != nil { + in, out := &in.LogFormat, &out.LogFormat + *out = new(string) + **out = **in + } + if in.KeepAliveTTL != nil { + in, out := &in.KeepAliveTTL, &out.KeepAliveTTL + *out = new(int64) + **out = **in + } + in.DMSecurityConfig.DeepCopyInto(&out.DMSecurityConfig) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerConfig. +func (in *WorkerConfig) DeepCopy() *WorkerConfig { + if in == nil { + return nil + } + out := new(WorkerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerMember) DeepCopyInto(out *WorkerMember) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerMember. +func (in *WorkerMember) DeepCopy() *WorkerMember { + if in == nil { + return nil + } + out := new(WorkerMember) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerSpec) DeepCopyInto(out *WorkerSpec) { + *out = *in + in.ComponentSpec.DeepCopyInto(&out.ComponentSpec) + in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements) + if in.StorageClassName != nil { + in, out := &in.StorageClassName, &out.StorageClassName + *out = new(string) + **out = **in + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(WorkerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerSpec. +func (in *WorkerSpec) DeepCopy() *WorkerSpec { + if in == nil { + return nil + } + out := new(WorkerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerStatus) DeepCopyInto(out *WorkerStatus) { + *out = *in + if in.StatefulSet != nil { + in, out := &in.StatefulSet, &out.StatefulSet + *out = new(appsv1.StatefulSetStatus) + (*in).DeepCopyInto(*out) + } + if in.Workers != nil { + in, out := &in.Workers, &out.Workers + *out = make(map[string]WorkerMember, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerStatus. +func (in *WorkerStatus) DeepCopy() *WorkerStatus { + if in == nil { + return nil + } + out := new(WorkerStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/util/crdutil.go b/pkg/util/crdutil.go index f1cb0e4204..f61ec774f4 100644 --- a/pkg/util/crdutil.go +++ b/pkg/util/crdutil.go @@ -261,6 +261,8 @@ func GetCrdKindFromKindName(kindName string) (v1alpha1.CrdKind, error) { switch strings.ToLower(kindName) { case v1alpha1.TiDBClusterKindKey: return v1alpha1.DefaultCrdKinds.TiDBCluster, nil + case v1alpha1.DMClusterKindKey: + return v1alpha1.DefaultCrdKinds.DMCluster, nil case v1alpha1.BackupKindKey: return v1alpha1.DefaultCrdKinds.Backup, nil case v1alpha1.RestoreKindKey: From 55a63650c06c03794b0edc4b09970485e883aa21 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 6 Aug 2020 14:23:08 +0800 Subject: [PATCH 02/37] address comment --- pkg/apis/pingcap/v1alpha1/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index de46f04ce9..d1fed75e7d 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -50,7 +50,7 @@ const ( // DMMasterMemberType is dm-master container type DMMasterMemberType MemberType = "dm-master" // DMWorkerMemberType is dm-worker container type - DMWorkerMemberType MemberType = "dm-master" + DMWorkerMemberType MemberType = "dm-worker" // SlowLogTailerMemberType is tidb log tailer container type SlowLogTailerMemberType MemberType = "slowlog" // UnknownMemberType is unknown container type From f146be1773a7d3cabb1c48821e59063fcd92341c Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 6 Aug 2020 18:22:37 +0800 Subject: [PATCH 03/37] address comments --- docs/api-references/docs.md | 219 ++++++++++++------ pkg/apis/pingcap/v1alpha1/dm_config.go | 33 ++- .../pingcap/v1alpha1/openapi_generated.go | 104 +++++---- pkg/apis/pingcap/v1alpha1/types.go | 71 ++++-- .../pingcap/v1alpha1/zz_generated.deepcopy.go | 40 +++- 5 files changed, 305 insertions(+), 162 deletions(-) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 9f9caca414..ddc72e6101 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -3411,7 +3411,6 @@ string

(Appears on: ComponentSpec, -DMClusterSpec, TidbClusterSpec)

@@ -3820,7 +3819,7 @@ DMDiscoverySpec

- - - - + + + + + + + + - - - - + + + + + + + + - - - - @@ -5871,6 +5875,9 @@ DMSecurityConfig @@ -6140,6 +6147,62 @@ Kubernetes meta/v1.Time
-password
+synced
-string +bool
-(Optional)
-profile
+phase
-string + +MemberPhase +
-(Optional)
-quota
+statefulSet
-string + +Kubernetes apps/v1.StatefulSetStatus +
-(Optional)
-networks
+workers
- -Networks + +map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerMember
-(Optional)
-dm_master
+master
MasterSpec @@ -3834,7 +3833,7 @@ MasterSpec
-dm_worker
+worker
WorkerSpec @@ -3925,23 +3924,6 @@ Kubernetes core/v1.PullPolicy
-configUpdateStrategy
- - -ConfigUpdateStrategy - - -
-

ConfigUpdateStrategy determines how the configuration change is applied to the cluster. -UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the -cluster component is needed to reload the configuration change. -UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the -related components to use the new ConfigMap, that is, the new configuration will be applied automatically.

-
enablePVReclaim
bool @@ -3970,6 +3952,20 @@ Optional: Defaults to nil

+affinity
+ + +Kubernetes core/v1.Affinity + + +
+(Optional) +

Affinity of DM cluster Pods

+
nodeSelector
map[string]string @@ -3994,6 +3990,19 @@ map[string]string
+timezone
+ +string + +
+(Optional) +

Time zone of DM cluster Pods +Optional: Defaults to UTC

+
tolerations
@@ -4154,7 +4163,7 @@ DMDiscoverySpec
-dm_master
+master
MasterSpec @@ -4168,7 +4177,7 @@ MasterSpec
-dm_worker
+worker
WorkerSpec @@ -4259,23 +4268,6 @@ Kubernetes core/v1.PullPolicy
-configUpdateStrategy
- - -ConfigUpdateStrategy - - -
-

ConfigUpdateStrategy determines how the configuration change is applied to the cluster. -UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the -cluster component is needed to reload the configuration change. -UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the -related components to use the new ConfigMap, that is, the new configuration will be applied automatically.

-
enablePVReclaim
bool @@ -4304,6 +4296,20 @@ Optional: Defaults to nil

+affinity
+ + +Kubernetes core/v1.Affinity + + +
+(Optional) +

Affinity of DM cluster Pods

+
nodeSelector
map[string]string @@ -4328,6 +4334,19 @@ map[string]string
+timezone
+ +string + +
+(Optional) +

Time zone of DM cluster Pods +Optional: Defaults to UTC

+
tolerations
@@ -4360,7 +4379,7 @@ map[string]string
-dm_master
+master
MasterStatus @@ -4372,7 +4391,7 @@ MasterStatus
-dm_worker
+worker
WorkerStatus @@ -4428,28 +4447,13 @@ TidbMonitorRef
-ResourceRequirements
- - -Kubernetes core/v1.ResourceRequirements - - -
-

-(Members of ResourceRequirements are embedded into this type.) -

-
-host
+address
string
-

Host indicates the existed TiDB discovery host. If not specified, dm cluster will start a new one

+

Address indicates the existed TiDB discovery address

+

+(Members of DMSecurityConfig are embedded into this type.) +

(Optional)

dm-master’s security config

+

MasterServiceSpec

+

+(Appears on: +MasterSpec) +

+

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ServiceSpec
+ + +ServiceSpec + + +
+
+externalTrafficPolicy
+ + +Kubernetes core/v1.ServiceExternalTrafficPolicyType + + +
+(Optional) +

ExternalTrafficPolicy of the service +Optional: Defaults to omitted

+
+masterNodePort
+ +int + +
+(Optional) +

Optional: Defaults to 0

+

MasterSpec

(Appears on: @@ -6206,16 +6269,15 @@ string (Optional) -

TODO: remove optional after defaulting introduced -Base image of the component, image tag is now allowed during validation

+

Base image of the component, image tag is now allowed during validation

service
- -ServiceSpec + +MasterServiceSpec @@ -10022,7 +10084,7 @@ string

(Appears on: GrafanaSpec, -MasterSpec, +MasterServiceSpec, PDSpec, PrometheusSpec, ReloaderSpec, @@ -18520,6 +18582,9 @@ DMSecurityConfig +

+(Members of DMSecurityConfig are embedded into this type.) +

(Optional)

dm-worker’s security config

@@ -18532,7 +18597,7 @@ DMSecurityConfig WorkerStatus)

-

WorkerMember is DM Worker status

+

WorkerMember is dm-Worker member status

@@ -18562,6 +18627,29 @@ string + + + + + + + +
+state
+ +string + +
+
+lastTransitionTime
+ + +Kubernetes meta/v1.Time + + +
+

Last time the health transitioned from one to another.

+

WorkerSpec

@@ -18630,8 +18718,7 @@ string (Optional) -

TODO: remove optional after defaulting introduced -Base image of the component, image tag is now allowed during validation

+

Base image of the component, image tag is now allowed during validation

diff --git a/pkg/apis/pingcap/v1alpha1/dm_config.go b/pkg/apis/pingcap/v1alpha1/dm_config.go index aa500942e0..1762ea8f16 100644 --- a/pkg/apis/pingcap/v1alpha1/dm_config.go +++ b/pkg/apis/pingcap/v1alpha1/dm_config.go @@ -31,30 +31,30 @@ type MasterConfig struct { // Log level. // Optional: Defaults to info // +optional - LogLevel *string `toml:"log-level" json:"log-level"` + LogLevel *string `toml:"log-level,omitempty" json:"log-level,omitempty"` // File log config. // +optional - LogFile *string `toml:"log-file" json:"log-file"` + LogFile *string `toml:"log-file,omitempty" json:"log-file,omitempty"` // Log format. one of json or text. // +optional - LogFormat *string `toml:"log-format" json:"log-format"` + LogFormat *string `toml:"log-format,omitempty" json:"log-format,omitempty"` // RPC timeout when dm-master request to dm-worker // Optional: Defaults to 30s // +optional - RPCTimeoutStr *string `toml:"rpc-timeout" json:"rpc-timeout"` + RPCTimeoutStr *string `toml:"rpc-timeout,omitempty" json:"rpc-timeout,omitempty"` // RPC agent rate limit when dm-master request to dm-worker // Optional: Defaults to 10 // +optional - RPCRateLimit *float64 `toml:"rpc-rate-limit" json:"rpc-rate-limit"` + RPCRateLimit *float64 `toml:"rpc-rate-limit,omitempty" json:"rpc-rate-limit,omitempty"` // RPC agent rate burst when dm-master request to dm-worker // Optional: Defaults to 40 // +optional - RPCRateBurst *int `toml:"rpc-rate-burst" json:"rpc-rate-burst"` + RPCRateBurst *int `toml:"rpc-rate-burst,omitempty" json:"rpc-rate-burst,omitempty"` // dm-master's security config // +optional // +k8s:openapi-gen=false - DMSecurityConfig + DMSecurityConfig `toml:",inline" json:",inline"` } // WorkerConfig is the configuration of dm-worker-server @@ -63,36 +63,35 @@ type WorkerConfig struct { // Log level. // Optional: Defaults to info // +optional - LogLevel *string `toml:"log-level" json:"log-level"` + LogLevel *string `toml:"log-level,omitempty" json:"log-level,omitempty"` // File log config. // +optional - LogFile *string `toml:"log-file" json:"log-file"` + LogFile *string `toml:"log-file,omitempty" json:"log-file,omitempty"` // Log format. one of json or text. // +optional - LogFormat *string `toml:"log-format" json:"log-format"` + LogFormat *string `toml:"log-format,omitempty" json:"log-format,omitempty"` // KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd // Optional: Defaults to 10 // +optional - KeepAliveTTL *int64 `toml:"keepalive-ttl" json:"keepalive-ttl"` + KeepAliveTTL *int64 `toml:"keepalive-ttl,omitempty" json:"keepalive-ttl,omitempty"` // dm-worker's security config // +optional - DMSecurityConfig + DMSecurityConfig `toml:",inline" json:",inline"` } // DM common security config type DMSecurityConfig struct { // SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty // +optional - SSLCA *string `toml:"ssl-ca" json:"ssl-ca" yaml:"ssl-ca"` + SSLCA *string `toml:"ssl-ca,omitempty" json:"ssl-ca,omitempty" yaml:"ssl-ca,omitempty"` // SSLCert is the path of file that contains X509 certificate in PEM format. // +optional - SSLCert *string `toml:"ssl-cert" json:"ssl-cert" yaml:"ssl-cert"` + SSLCert *string `toml:"ssl-cert,omitempty" json:"ssl-cert,omitempty" yaml:"ssl-cert,omitempty"` // SSLKey is the path of file that contains X509 key in PEM format. // +optional - SSLKey *string `toml:"ssl-key" json:"ssl-key" yaml:"ssl-key"` + SSLKey *string `toml:"ssl-key,omitempty" json:"ssl-key,omitempty" yaml:"ssl-key,omitempty"` // CertAllowedCN is the Common Name that allowed // +optional - // +k8s:openapi-gen=false - CertAllowedCN []string `toml:"cert-allowed-cn" json:"cert-allowed-cn" yaml:"cert-allowed-cn"` + CertAllowedCN []string `toml:"cert-allowed-cn,omitempty" json:"cert-allowed-cn,omitempty" yaml:"cert-allowed-cn,omitempty"` } diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index 850572d62d..90fc8591bb 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -1336,13 +1336,13 @@ func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec"), }, }, - "dm_master": { + "master": { SchemaProps: spec.SchemaProps{ Description: "dm-master cluster spec", Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterSpec"), }, }, - "dm_worker": { + "worker": { SchemaProps: spec.SchemaProps{ Description: "dm-worker cluster spec", Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerSpec"), @@ -1396,13 +1396,6 @@ func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback }, }, }, - "configUpdateStrategy": { - SchemaProps: spec.SchemaProps{ - Description: "ConfigUpdateStrategy determines how the configuration change is applied to the cluster. UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the cluster component is needed to reload the configuration change. UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the related components to use the new ConfigMap, that is, the new configuration will be applied automatically.", - Type: []string{"string"}, - Format: "", - }, - }, "enablePVReclaim": { SchemaProps: spec.SchemaProps{ Description: "Whether enable PVC reclaim for orphan PVC left by statefulset scale-in Optional: Defaults to false", @@ -1416,6 +1409,12 @@ func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TLSCluster"), }, }, + "affinity": { + SchemaProps: spec.SchemaProps{ + Description: "Affinity of DM cluster Pods", + Ref: ref("k8s.io/api/core/v1.Affinity"), + }, + }, "nodeSelector": { SchemaProps: spec.SchemaProps{ Description: "Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively", @@ -1446,6 +1445,13 @@ func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback }, }, }, + "timezone": { + SchemaProps: spec.SchemaProps{ + Description: "Time zone of DM cluster Pods Optional: Defaults to UTC", + Type: []string{"string"}, + Format: "", + }, + }, "tolerations": { SchemaProps: spec.SchemaProps{ Description: "Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively", @@ -1460,10 +1466,11 @@ func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback }, }, }, + Required: []string{"discovery"}, }, }, Dependencies: []string{ - "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterSpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TLSCluster", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerSpec", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.Toleration"}, + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterSpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TLSCluster", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.Toleration"}, } } @@ -1474,47 +1481,17 @@ func schema_pkg_apis_pingcap_v1alpha1_DMDiscoverySpec(ref common.ReferenceCallba Description: "DMDiscoverySpec contains details of Discovery members for dm", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "limits": { - SchemaProps: spec.SchemaProps{ - Description: "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", - Type: []string{"object"}, - AdditionalProperties: &spec.SchemaOrBool{ - Allows: true, - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), - }, - }, - }, - }, - }, - "requests": { - SchemaProps: spec.SchemaProps{ - Description: "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/", - Type: []string{"object"}, - AdditionalProperties: &spec.SchemaOrBool{ - Allows: true, - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), - }, - }, - }, - }, - }, - "host": { + "address": { SchemaProps: spec.SchemaProps{ - Description: "Host indicates the existed TiDB discovery host. If not specified, dm cluster will start a new one", + Description: "Address indicates the existed TiDB discovery address", Type: []string{"string"}, Format: "", }, }, }, - Required: []string{"host"}, + Required: []string{"address"}, }, }, - Dependencies: []string{ - "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } @@ -2537,7 +2514,7 @@ func schema_pkg_apis_pingcap_v1alpha1_MasterSpec(ref common.ReferenceCallback) c "service": { SchemaProps: spec.SchemaProps{ Description: "Service defines a Kubernetes service of Master cluster. Optional: Defaults to `.spec.services` in favor of backward compatibility", - Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ServiceSpec"), + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterServiceSpec"), }, }, "maxFailoverCount": { @@ -2572,7 +2549,7 @@ func schema_pkg_apis_pingcap_v1alpha1_MasterSpec(ref common.ReferenceCallback) c }, }, Dependencies: []string{ - "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterConfig", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ServiceSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterConfig", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.MasterServiceSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } @@ -10712,17 +10689,44 @@ func schema_pkg_apis_pingcap_v1alpha1_WorkerConfig(ref common.ReferenceCallback) Format: "int64", }, }, - "DMSecurityConfig": { + "ssl-ca": { + SchemaProps: spec.SchemaProps{ + Description: "SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty", + Type: []string{"string"}, + Format: "", + }, + }, + "ssl-cert": { SchemaProps: spec.SchemaProps{ - Description: "dm-worker's security config", - Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMSecurityConfig"), + Description: "SSLCert is the path of file that contains X509 certificate in PEM format.", + Type: []string{"string"}, + Format: "", + }, + }, + "ssl-key": { + SchemaProps: spec.SchemaProps{ + Description: "SSLKey is the path of file that contains X509 key in PEM format.", + Type: []string{"string"}, + Format: "", + }, + }, + "cert-allowed-cn": { + SchemaProps: spec.SchemaProps{ + Description: "CertAllowedCN is the Common Name that allowed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, }, }, }, }, }, - Dependencies: []string{ - "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMSecurityConfig"}, } } diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index d1fed75e7d..c25db44189 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -31,6 +31,13 @@ const ( TiKVStateOffline string = "Offline" // TiKVStateTombstone represents status of Tombstone of TiKV TiKVStateTombstone string = "Tombstone" + + // DMWorkerStateFree represents status of free of dm-worker + DMWorkerStateFree string = "free" + // DMWorkerStateBound represents status of bound of dm-worker + DMWorkerStateBound string = "bound" + // DMWorkerStateOffline represents status of offline of dm-worker + DMWorkerStateOffline string = "offline" ) // MemberType represents member type @@ -1460,24 +1467,23 @@ type DMCluster struct { // +k8s:openapi-gen=true // DMDiscoverySpec contains details of Discovery members for dm type DMDiscoverySpec struct { - corev1.ResourceRequirements `json:",inline"` - // Host indicates the existed TiDB discovery host. If not specified, dm cluster will start a new one - Host string `json:"host"` + // Address indicates the existed TiDB discovery address + Address string `json:"address"` } // +k8s:openapi-gen=true // DMClusterSpec describes the attributes that a user creates on a dm cluster type DMClusterSpec struct { // Discovery spec - Discovery DMDiscoverySpec `json:"discovery,omitempty"` + Discovery DMDiscoverySpec `json:"discovery"` // dm-master cluster spec // +optional - Master *MasterSpec `json:"dm_master,omitempty"` + Master *MasterSpec `json:"master,omitempty"` // dm-worker cluster spec // +optional - Worker *WorkerSpec `json:"dm_worker,omitempty"` + Worker *WorkerSpec `json:"worker,omitempty"` // Indicates that the dm cluster is paused and will not be processed by // the controller. @@ -1505,15 +1511,6 @@ type DMClusterSpec struct { // +optional ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` - // ConfigUpdateStrategy determines how the configuration change is applied to the cluster. - // UpdateStrategyInPlace will update the ConfigMap of configuration in-place and an extra rolling-update of the - // cluster component is needed to reload the configuration change. - // UpdateStrategyRollingUpdate will create a new ConfigMap with the new configuration and rolling-update the - // related components to use the new ConfigMap, that is, the new configuration will be applied automatically. - // +kubebuilder:validation:Enum=InPlace,RollingUpdate - // +kubebuilder:default=InPlacne - ConfigUpdateStrategy ConfigUpdateStrategy `json:"configUpdateStrategy,omitempty"` - // Whether enable PVC reclaim for orphan PVC left by statefulset scale-in // Optional: Defaults to false // +optional @@ -1524,6 +1521,10 @@ type DMClusterSpec struct { // +optional TLSCluster *TLSCluster `json:"tlsCluster,omitempty"` + // Affinity of DM cluster Pods + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + // Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively // +optional NodeSelector map[string]string `json:"nodeSelector,omitempty"` @@ -1532,6 +1533,11 @@ type DMClusterSpec struct { // +optional Annotations map[string]string `json:"annotations,omitempty"` + // Time zone of DM cluster Pods + // Optional: Defaults to UTC + // +optional + Timezone string `json:"timezone,omitempty"` + // Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively // +optional Tolerations []corev1.Toleration `json:"tolerations,omitempty"` @@ -1539,8 +1545,8 @@ type DMClusterSpec struct { // DMClusterStatus represents the current status of a dm cluster. type DMClusterStatus struct { - Master MasterStatus `json:"dm_master,omitempty"` - Worker WorkerStatus `json:"dm_worker,omitempty"` + Master MasterStatus `json:"master,omitempty"` + Worker WorkerStatus `json:"worker,omitempty"` Monitor *TidbMonitorRef `json:"monitor,omitempty"` // Represents the latest available observations of a dm cluster's state. @@ -1558,16 +1564,15 @@ type MasterSpec struct { // +kubebuilder:validation:Minimum=1 Replicas int32 `json:"replicas"` - // TODO: remove optional after defaulting introduced // Base image of the component, image tag is now allowed during validation - // +kubebuilder:default=pingcap/dm-master + // +kubebuilder:default=pingcap/dm // +optional - BaseImage string `json:"baseImage"` + BaseImage string `json:"baseImage,omitempty"` // Service defines a Kubernetes service of Master cluster. // Optional: Defaults to `.spec.services` in favor of backward compatibility // +optional - Service *ServiceSpec `json:"service,omitempty"` + Service *MasterServiceSpec `json:"service,omitempty"` // MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. // Optional: Defaults to 3 @@ -1596,6 +1601,20 @@ type MasterSpec struct { Config *MasterConfig `json:"config,omitempty"` } +type MasterServiceSpec struct { + // +k8s:openapi-gen=false + ServiceSpec + + // ExternalTrafficPolicy of the service + // Optional: Defaults to omitted + // +optional + ExternalTrafficPolicy *corev1.ServiceExternalTrafficPolicyType `json:"externalTrafficPolicy,omitempty"` // Expose the tidb cluster mysql port to MySQLNodePort + + // Optional: Defaults to 0 + // +optional + MasterNodePort *int `json:"masterNodePort,omitempty"` +} + // +k8s:openapi-gen=true // WorkerSpec contains details of dm-worker members type WorkerSpec struct { @@ -1606,11 +1625,10 @@ type WorkerSpec struct { // +kubebuilder:validation:Minimum=1 Replicas int32 `json:"replicas"` - // TODO: remove optional after defaulting introduced // Base image of the component, image tag is now allowed during validation - // +kubebuilder:default=pingcap/dm-wokrer + // +kubebuilder:default=pingcap/dm // +optional - BaseImage string `json:"baseImage"` + BaseImage string `json:"baseImage,omitempty"` // The storageClassName of the persistent volume for dm-worker data storage. // Defaults to Kubernetes default storage class. @@ -1705,8 +1723,11 @@ type WorkerStatus struct { Workers map[string]WorkerMember `json:"workers,omitempty"` } -// WorkerMember is DM Worker status +// WorkerMember is dm-Worker member status type WorkerMember struct { PodName string `json:"podName,omitempty"` ID string `json:"id,omitempty"` + State string `json:"state"` + // Last time the health transitioned from one to another. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` } diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index 3e48cfd693..89d928c3ba 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -876,7 +876,7 @@ func (in *DMClusterCondition) DeepCopy() *DMClusterCondition { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DMClusterSpec) DeepCopyInto(out *DMClusterSpec) { *out = *in - in.Discovery.DeepCopyInto(&out.Discovery) + out.Discovery = in.Discovery if in.Master != nil { in, out := &in.Master, &out.Master *out = new(MasterSpec) @@ -907,6 +907,11 @@ func (in *DMClusterSpec) DeepCopyInto(out *DMClusterSpec) { *out = new(TLSCluster) **out = **in } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = make(map[string]string, len(*in)) @@ -974,7 +979,6 @@ func (in *DMClusterStatus) DeepCopy() *DMClusterStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DMDiscoverySpec) DeepCopyInto(out *DMDiscoverySpec) { *out = *in - in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements) return } @@ -2104,6 +2108,33 @@ func (in *MasterMember) DeepCopy() *MasterMember { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MasterServiceSpec) DeepCopyInto(out *MasterServiceSpec) { + *out = *in + in.ServiceSpec.DeepCopyInto(&out.ServiceSpec) + if in.ExternalTrafficPolicy != nil { + in, out := &in.ExternalTrafficPolicy, &out.ExternalTrafficPolicy + *out = new(v1.ServiceExternalTrafficPolicyType) + **out = **in + } + if in.MasterNodePort != nil { + in, out := &in.MasterNodePort, &out.MasterNodePort + *out = new(int) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterServiceSpec. +func (in *MasterServiceSpec) DeepCopy() *MasterServiceSpec { + if in == nil { + return nil + } + out := new(MasterServiceSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MasterSpec) DeepCopyInto(out *MasterSpec) { *out = *in @@ -2111,7 +2142,7 @@ func (in *MasterSpec) DeepCopyInto(out *MasterSpec) { in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements) if in.Service != nil { in, out := &in.Service, &out.Service - *out = new(ServiceSpec) + *out = new(MasterServiceSpec) (*in).DeepCopyInto(*out) } if in.MaxFailoverCount != nil { @@ -7972,6 +8003,7 @@ func (in *WorkerConfig) DeepCopy() *WorkerConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkerMember) DeepCopyInto(out *WorkerMember) { *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) return } @@ -8025,7 +8057,7 @@ func (in *WorkerStatus) DeepCopyInto(out *WorkerStatus) { in, out := &in.Workers, &out.Workers *out = make(map[string]WorkerMember, len(*in)) for key, val := range *in { - (*out)[key] = val + (*out)[key] = *val.DeepCopy() } } return From 4f10a5155e09856d54fddeb09a8416f40dd085d1 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 6 Aug 2020 19:08:11 +0800 Subject: [PATCH 04/37] delete monitor ref --- docs/api-references/docs.md | 13 ------------- pkg/apis/pingcap/v1alpha1/types.go | 1 - pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go | 5 ----- 3 files changed, 19 deletions(-) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index ddc72e6101..0cc81469bc 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -4403,18 +4403,6 @@ WorkerStatus -monitor
- - -TidbMonitorRef - - - - - - - - conditions
@@ -17990,7 +17978,6 @@ InitializePhase

TidbMonitorRef

(Appears on: -DMClusterStatus, TidbClusterAutoScalerSpec, TidbClusterStatus)

diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index c25db44189..bdf698fa6f 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -1548,7 +1548,6 @@ type DMClusterStatus struct { Master MasterStatus `json:"master,omitempty"` Worker WorkerStatus `json:"worker,omitempty"` - Monitor *TidbMonitorRef `json:"monitor,omitempty"` // Represents the latest available observations of a dm cluster's state. // +optional Conditions []DMClusterCondition `json:"conditions,omitempty"` diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index 89d928c3ba..0fe7898077 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -951,11 +951,6 @@ func (in *DMClusterStatus) DeepCopyInto(out *DMClusterStatus) { *out = *in in.Master.DeepCopyInto(&out.Master) in.Worker.DeepCopyInto(&out.Worker) - if in.Monitor != nil { - in, out := &in.Monitor, &out.Monitor - *out = new(TidbMonitorRef) - **out = **in - } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]DMClusterCondition, len(*in)) From a020492edb66f2b6a20f0b237ba84805861cb958 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 6 Aug 2020 21:30:58 +0800 Subject: [PATCH 05/37] generate dmcluster client --- docs/api-references/docs.md | 1529 +++++++++-------- .../pingcap/v1alpha1/openapi_generated.go | 43 + pkg/apis/pingcap/v1alpha1/types.go | 19 +- .../pingcap/v1alpha1/zz_generated.deepcopy.go | 41 + .../typed/pingcap/v1alpha1/dmcluster.go | 188 ++ .../pingcap/v1alpha1/fake/fake_dmcluster.go | 137 ++ .../v1alpha1/fake/fake_pingcap_client.go | 4 + .../pingcap/v1alpha1/generated_expansion.go | 2 + .../typed/pingcap/v1alpha1/pingcap_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../pingcap/v1alpha1/dmcluster.go | 86 + .../pingcap/v1alpha1/interface.go | 7 + .../listers/pingcap/v1alpha1/dmcluster.go | 91 + .../pingcap/v1alpha1/expansion_generated.go | 8 + 14 files changed, 1405 insertions(+), 757 deletions(-) create mode 100644 pkg/client/clientset/versioned/typed/pingcap/v1alpha1/dmcluster.go create mode 100644 pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_dmcluster.go create mode 100644 pkg/client/informers/externalversions/pingcap/v1alpha1/dmcluster.go create mode 100644 pkg/client/listers/pingcap/v1alpha1/dmcluster.go diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 0cc81469bc..13802a534c 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -14,6 +14,8 @@ Resource Types:
  • BackupSchedule
  • +DMCluster +
  • Restore
  • TiDBGroup @@ -464,9 +466,9 @@ BackupScheduleStatus -

    Restore

    +

    DMCluster

    -

    Restore represents the restoration of backup of a tidb cluster.

    +

    DMCluster is the control script’s spec

    @@ -491,7 +493,7 @@ pingcap.com/v1alpha1 kind
    string - +
    RestoreDMCluster
    @@ -511,131 +513,160 @@ Refer to the Kubernetes API documentation for the fields of the spec
    - -RestoreSpec + +DMClusterSpec
    +

    Spec defines the behavior of a dm cluster



    + + + + + + + + @@ -649,43 +680,58 @@ Kubernetes core/v1.Affinity + + + +
    -resources
    +discovery
    - -Kubernetes core/v1.ResourceRequirements + +DMDiscoverySpec
    +

    Discovery spec

    -to
    +master
    - -TiDBAccessConfig + +MasterSpec
    -

    To is the tidb cluster that needs to restore.

    +(Optional) +

    dm-master cluster spec

    -backupType
    +worker
    - -BackupType + +WorkerSpec
    -

    Type is the backup type for tidb cluster.

    +(Optional) +

    dm-worker cluster spec

    -tikvGCLifeTime
    +paused
    -string +bool
    -

    TikvGCLifeTime is to specify the safe gc life time for restore. -The time limit during which data is retained for each GC, in the format of Go Duration. -When a GC happens, the current time minus this value is the safe point.

    +(Optional) +

    Indicates that the dm cluster is paused and will not be processed by +the controller.

    -StorageProvider
    +version
    - -StorageProvider - +string
    -

    -(Members of StorageProvider are embedded into this type.) -

    -

    StorageProvider configures where and how backups should be stored.

    +(Optional) +

    TODO: remove optional after defaulting logic introduced +dm cluster version

    -storageClassName
    +schedulerName
    string
    -(Optional) -

    The storageClassName of the persistent volume for Restore data storage. -Defaults to Kubernetes default storage class.

    +

    SchedulerName of DM cluster Pods

    -storageSize
    +pvReclaimPolicy
    -string + +Kubernetes core/v1.PersistentVolumeReclaimPolicy +
    -

    StorageSize is the request storage size for backup job

    +

    Persistent volume reclaim policy applied to the PVs that consumed by DM cluster

    -br
    +imagePullPolicy
    - -BRConfig + +Kubernetes core/v1.PullPolicy
    -

    BR is the configs for BR.

    +

    ImagePullPolicy of DM cluster Pods

    -tolerations
    +imagePullSecrets
    - -[]Kubernetes core/v1.Toleration + +[]Kubernetes core/v1.LocalObjectReference
    (Optional) -

    Base tolerations of restore Pods, components may add more tolerations upon this respectively

    +

    ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

    +
    +enablePVReclaim
    + +bool + +
    +(Optional) +

    Whether enable PVC reclaim for orphan PVC left by statefulset scale-in +Optional: Defaults to false

    +
    +tlsCluster
    + + +TLSCluster + + +
    +(Optional) +

    Whether enable the TLS connection between DM server components +Optional: Defaults to nil

    (Optional) -

    Affinity of restore Pods

    +

    Affinity of DM cluster Pods

    -useKMS
    +nodeSelector
    -bool +map[string]string
    -

    Use KMS to decrypt the secrets

    +(Optional) +

    Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively

    -serviceAccount
    +annotations
    + +map[string]string + +
    +(Optional) +

    Base annotations of DM cluster Pods, components may add or override selectors upon this respectively

    +
    +timezone
    string
    -

    Specify service account of restore

    +(Optional) +

    Time zone of DM cluster Pods +Optional: Defaults to UTC

    -imagePullSecrets
    +tolerations
    - -[]Kubernetes core/v1.LocalObjectReference + +[]Kubernetes core/v1.Toleration
    (Optional) -

    ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

    +

    Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively

    @@ -695,19 +741,20 @@ string
    status
    - -RestoreStatus + +DMClusterStatus
    +

    Most recently observed status of the dm cluster

    -

    TiDBGroup

    +

    Restore

    -

    TiDBGroup encode the spec and status of a Group of TiDB Instances

    +

    Restore represents the restoration of backup of a tidb cluster.

    @@ -732,7 +779,7 @@ pingcap.com/v1alpha1 kind
    string - + - -
    TiDBGroupRestore
    @@ -752,141 +799,181 @@ Refer to the Kubernetes API documentation for the fields of the spec
    - -TiDBGroupSpec + +RestoreSpec
    -

    Spec defines the desired state of TiDBGroup



    - -
    -TiDBSpec
    +resources
    - -TiDBSpec + +Kubernetes core/v1.ResourceRequirements
    -

    -(Members of TiDBSpec are embedded into this type.) -

    -clusterName
    +to
    -string + +TiDBAccessConfig +
    -

    ClusterName describe the target TidbCluster in the same namespace

    -
    +

    To is the tidb cluster that needs to restore.

    -status
    +backupType
    - -TiDBGroupStatus + +BackupType
    -

    Most recently observed status of the TiDBGroup

    +

    Type is the backup type for tidb cluster.

    -

    TiKVGroup

    -

    -

    TiKVGroup encode the spec and status of a Group of TiKV Instances

    -

    - - - - - - - - - - - -
    FieldDescription
    -apiVersion
    -string
    - -pingcap.com/v1alpha1 - +tikvGCLifeTime
    + +string +
    -kind
    -string +

    TikvGCLifeTime is to specify the safe gc life time for restore. +The time limit during which data is retained for each GC, in the format of Go Duration. +When a GC happens, the current time minus this value is the safe point.

    TiKVGroup
    -metadata
    +StorageProvider
    - -Kubernetes meta/v1.ObjectMeta + +StorageProvider
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. +

    +(Members of StorageProvider are embedded into this type.) +

    +

    StorageProvider configures where and how backups should be stored.

    -spec
    +storageClassName
    - -TiKVGroupSpec - +string
    -

    Spec defines the desired state of TiKVGroup

    -
    -
    - +(Optional) +

    The storageClassName of the persistent volume for Restore data storage. +Defaults to Kubernetes default storage class.

    + + + + + + + + + + + + + + + + + + + + + +
    -TiKVSpec
    +storageSize
    - -TiKVSpec +string + +
    +

    StorageSize is the request storage size for backup job

    +
    +br
    + + +BRConfig
    -

    -(Members of TiKVSpec are embedded into this type.) -

    +

    BR is the configs for BR.

    -clusterName
    +tolerations
    + + +[]Kubernetes core/v1.Toleration + + +
    +(Optional) +

    Base tolerations of restore Pods, components may add more tolerations upon this respectively

    +
    +affinity
    + + +Kubernetes core/v1.Affinity + + +
    +(Optional) +

    Affinity of restore Pods

    +
    +useKMS
    + +bool + +
    +

    Use KMS to decrypt the secrets

    +
    +serviceAccount
    string
    -

    ClusterName describe the target TidbCluster in the same namespace

    +

    Specify service account of restore

    +
    +imagePullSecrets
    + + +[]Kubernetes core/v1.LocalObjectReference + + +
    +(Optional) +

    ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

    @@ -896,20 +983,19 @@ string
    status
    - -TiKVGroupStatus + +RestoreStatus
    -

    Most recently observed status of the TiKVGroup

    -

    TidbCluster

    +

    TiDBGroup

    -

    TidbCluster is the control script’s spec

    +

    TiDBGroup encode the spec and status of a Group of TiDB Instances

    @@ -934,7 +1020,7 @@ pingcap.com/v1alpha1 kind
    string - + + +
    TidbClusterTiDBGroup
    @@ -954,170 +1040,372 @@ Refer to the Kubernetes API documentation for the fields of the spec
    - -TidbClusterSpec + +TiDBGroupSpec
    -

    Spec defines the behavior of a tidb cluster

    +

    Spec defines the desired state of TiDBGroup



    + +
    -discovery
    +TiDBSpec
    - -DiscoverySpec + +TiDBSpec
    -

    Discovery spec

    +

    +(Members of TiDBSpec are embedded into this type.) +

    -pd
    +clusterName
    - -PDSpec - +string
    -(Optional) -

    PD cluster spec

    +

    ClusterName describe the target TidbCluster in the same namespace

    +
    -tidb
    +status
    - -TiDBSpec + +TiDBGroupStatus
    -(Optional) -

    TiDB cluster spec

    +

    Most recently observed status of the TiDBGroup

    +

    TiKVGroup

    +

    +

    TiKVGroup encode the spec and status of a Group of TiKV Instances

    +

    + + + + + + + + + + + + - +

    Spec defines the desired state of TiKVGroup

    +
    +
    +
    FieldDescription
    -tikv
    - - -TiKVSpec - - +apiVersion
    +string
    + +pingcap.com/v1alpha1 +
    -(Optional) -

    TiKV cluster spec

    +kind
    +string
    TiKVGroup
    -tiflash
    +metadata
    - -TiFlashSpec + +Kubernetes meta/v1.ObjectMeta
    -(Optional) -

    TiFlash cluster spec

    +Refer to the Kubernetes API documentation for the fields of the +metadata field.
    -ticdc
    +spec
    - -TiCDCSpec + +TiKVGroupSpec
    -(Optional) -

    TiCDC cluster spec

    -
    + +
    -pump
    +TiKVSpec
    - -PumpSpec + +TiKVSpec
    -(Optional) -

    Pump cluster spec

    +

    +(Members of TiKVSpec are embedded into this type.) +

    -helper
    +clusterName
    - -HelperSpec - +string
    -(Optional) -

    Helper spec

    +

    ClusterName describe the target TidbCluster in the same namespace

    +
    -paused
    +status
    -bool + +TiKVGroupStatus + -(Optional) -

    Indicates that the tidb cluster is paused and will not be processed by -the controller.

    +

    Most recently observed status of the TiKVGroup

    + + +

    TidbCluster

    +

    +

    TidbCluster is the control script’s spec

    +

    + + + + + + + + +apiVersion
    +string - + + + + + + + + + + + + + + + + + +
    FieldDescription
    -version
    - -string - -
    -(Optional) -

    TODO: remove optional after defaulting logic introduced -TiDB cluster version

    + +pingcap.com/v1alpha1 +
    -schedulerName
    - +kind
    string -
    -
    -

    SchedulerName of TiDB cluster Pods

    TidbCluster
    -pvReclaimPolicy
    +metadata
    - -Kubernetes core/v1.PersistentVolumeReclaimPolicy + +Kubernetes meta/v1.ObjectMeta + + +
    +Refer to the Kubernetes API documentation for the fields of the +metadata field. +
    +spec
    + + +TidbClusterSpec + + +
    +

    Spec defines the behavior of a tidb cluster

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3093,336 +3381,16 @@ and component-level overrides

    (Appears on: MasterSpec, -PDSpec, -PumpSpec, -TiCDCSpec, -TiDBSpec, -TiFlashSpec, -TiKVSpec, -WorkerSpec) -

    -

    -

    ComponentSpec is the base spec of each component, the fields should always accessed by the BasicSpec() method to respect the cluster-level properties

    -

    -
    +discovery
    + + +DiscoverySpec + + +
    +

    Discovery spec

    +
    +pd
    + + +PDSpec + + +
    +(Optional) +

    PD cluster spec

    +
    +tidb
    + + +TiDBSpec + + +
    +(Optional) +

    TiDB cluster spec

    +
    +tikv
    + + +TiKVSpec + + +
    +(Optional) +

    TiKV cluster spec

    +
    +tiflash
    + + +TiFlashSpec + + +
    +(Optional) +

    TiFlash cluster spec

    +
    +ticdc
    + + +TiCDCSpec + + +
    +(Optional) +

    TiCDC cluster spec

    +
    +pump
    + + +PumpSpec + + +
    +(Optional) +

    Pump cluster spec

    +
    +helper
    + + +HelperSpec + + +
    +(Optional) +

    Helper spec

    +
    +paused
    + +bool + +
    +(Optional) +

    Indicates that the tidb cluster is paused and will not be processed by +the controller.

    +
    +version
    + +string + +
    +(Optional) +

    TODO: remove optional after defaulting logic introduced +TiDB cluster version

    +
    +schedulerName
    + +string + +
    +

    SchedulerName of TiDB cluster Pods

    +
    +pvReclaimPolicy
    + + +Kubernetes core/v1.PersistentVolumeReclaimPolicy
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -image
    - -string - -
    -

    Image of the component, override baseImage and version if present -Deprecated

    -
    -version
    - -string - -
    -(Optional) -

    Version of the component. Override the cluster-level version if non-empty -Optional: Defaults to cluster-level setting

    -
    -imagePullPolicy
    - - -Kubernetes core/v1.PullPolicy - - -
    -(Optional) -

    ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present -Optional: Defaults to cluster-level setting

    -
    -imagePullSecrets
    - - -[]Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

    -
    -hostNetwork
    - -bool - -
    -(Optional) -

    Whether Hostnetwork of the component is enabled. Override the cluster-level setting if present -Optional: Defaults to cluster-level setting

    -
    -affinity
    - - -Kubernetes core/v1.Affinity - - -
    -(Optional) -

    Affinity of the component. Override the cluster-level one if present -Optional: Defaults to cluster-level setting

    -
    -priorityClassName
    - -string - -
    -(Optional) -

    PriorityClassName of the component. Override the cluster-level one if present -Optional: Defaults to cluster-level setting

    -
    -schedulerName
    - -string - -
    -(Optional) -

    SchedulerName of the component. Override the cluster-level one if present -Optional: Defaults to cluster-level setting

    -
    -nodeSelector
    - -map[string]string - -
    -(Optional) -

    NodeSelector of the component. Merged into the cluster-level nodeSelector if non-empty -Optional: Defaults to cluster-level setting

    -
    -annotations
    - -map[string]string - -
    -(Optional) -

    Annotations of the component. Merged into the cluster-level annotations if non-empty -Optional: Defaults to cluster-level setting

    -
    -tolerations
    - - -[]Kubernetes core/v1.Toleration - - -
    -(Optional) -

    Tolerations of the component. Override the cluster-level tolerations if non-empty -Optional: Defaults to cluster-level setting

    -
    -podSecurityContext
    - - -Kubernetes core/v1.PodSecurityContext - - -
    -(Optional) -

    PodSecurityContext of the component

    -
    -configUpdateStrategy
    - - -ConfigUpdateStrategy - - -
    -(Optional) -

    ConfigUpdateStrategy of the component. Override the cluster-level updateStrategy if present -Optional: Defaults to cluster-level setting

    -
    -env
    - - -[]Kubernetes core/v1.EnvVar - - -
    -(Optional) -

    List of environment variables to set in the container, like -v1.Container.Env. -Note that following env names cannot be used and may be overrided by -tidb-operator built envs. -- NAMESPACE -- TZ -- SERVICE_NAME -- PEER_SERVICE_NAME -- HEADLESS_SERVICE_NAME -- SET_NAME -- HOSTNAME -- CLUSTER_NAME -- POD_NAME -- BINLOG_ENABLED -- SLOW_LOG_FILE

    -
    -additionalContainers
    - - -[]Kubernetes core/v1.Container - - -
    -(Optional) -

    Additional containers of the component.

    -
    -additionalVolumes
    - - -[]Kubernetes core/v1.Volume - - -
    -(Optional) -

    Additional volumes of component pod. Currently this only -supports additional volume mounts for sidecar containers.

    -
    -terminationGracePeriodSeconds
    - -int64 - -
    -(Optional) -

    Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. -Value must be non-negative integer. The value zero indicates delete immediately. -If this value is nil, the default grace period will be used instead. -The grace period is the duration in seconds after the processes running in the pod are sent -a termination signal and the time when the processes are forcibly halted with a kill signal. -Set this value longer than the expected cleanup time for your process. -Defaults to 30 seconds.

    -
    -

    ConfigMapRef

    -

    -(Appears on: -PrometheusConfiguration) -

    -

    -

    ConfigMapRef is the external configMap

    -

    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -
    -namespace
    - -string - -
    -(Optional) -

    if the namespace is omitted, the operator controller would use the Tidbmonitor’s namespace instead.

    -
    -

    ConfigUpdateStrategy

    -

    -(Appears on: -ComponentSpec, -TidbClusterSpec) -

    -

    -

    ConfigUpdateStrategy represents the strategy to update configuration

    -

    -

    CoprocessorCache

    -

    -(Appears on: -TiKVClient) +PDSpec, +PumpSpec, +TiCDCSpec, +TiDBSpec, +TiFlashSpec, +TiKVSpec, +WorkerSpec)

    -

    CoprocessorCache is the config for coprocessor cache.

    +

    ComponentSpec is the base spec of each component, the fields should always accessed by the BasicSpec() method to respect the cluster-level properties

    @@ -3434,246 +3402,280 @@ string - -
    -enabled
    +image
    -bool +string
    -(Optional) -

    Whether to enable the copr cache. The copr cache saves the result from TiKV Coprocessor in the memory and -reuses the result when corresponding data in TiKV is unchanged, on a region basis.

    +

    Image of the component, override baseImage and version if present +Deprecated

    -capacity-mb
    +version
    -float64 +string
    (Optional) -

    The capacity in MB of the cache.

    +

    Version of the component. Override the cluster-level version if non-empty +Optional: Defaults to cluster-level setting

    -admission-max-result-mb
    +imagePullPolicy
    -float64 + +Kubernetes core/v1.PullPolicy +
    (Optional) -

    Only cache requests whose result set is small.

    +

    ImagePullPolicy of the component. Override the cluster-level imagePullPolicy if present +Optional: Defaults to cluster-level setting

    -admission-min-process-ms
    +imagePullSecrets
    -uint64 + +[]Kubernetes core/v1.LocalObjectReference +
    (Optional) -

    Only cache requests takes notable time to process.

    +

    ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

    -

    CrdKind

    -

    -(Appears on: -CrdKinds) -

    -

    -

    - - - - - - - - - -
    FieldDescription
    -Kind
    +hostNetwork
    -string +bool
    +(Optional) +

    Whether Hostnetwork of the component is enabled. Override the cluster-level setting if present +Optional: Defaults to cluster-level setting

    -Plural
    +affinity
    -string + +Kubernetes core/v1.Affinity +
    +(Optional) +

    Affinity of the component. Override the cluster-level one if present +Optional: Defaults to cluster-level setting

    -SpecName
    +priorityClassName
    string
    +(Optional) +

    PriorityClassName of the component. Override the cluster-level one if present +Optional: Defaults to cluster-level setting

    -ShortNames
    +schedulerName
    -[]string +string
    +(Optional) +

    SchedulerName of the component. Override the cluster-level one if present +Optional: Defaults to cluster-level setting

    -AdditionalPrinterColums
    +nodeSelector
    -[]k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1.CustomResourceColumnDefinition +map[string]string
    +(Optional) +

    NodeSelector of the component. Merged into the cluster-level nodeSelector if non-empty +Optional: Defaults to cluster-level setting

    -

    CrdKinds

    -

    -

    - - - - - - - - + +
    FieldDescription
    -KindsString
    +annotations
    -string +map[string]string
    +(Optional) +

    Annotations of the component. Merged into the cluster-level annotations if non-empty +Optional: Defaults to cluster-level setting

    -TiDBCluster
    +tolerations
    - -CrdKind + +[]Kubernetes core/v1.Toleration
    +(Optional) +

    Tolerations of the component. Override the cluster-level tolerations if non-empty +Optional: Defaults to cluster-level setting

    -DMCluster
    +podSecurityContext
    - -CrdKind + +Kubernetes core/v1.PodSecurityContext
    +(Optional) +

    PodSecurityContext of the component

    -Backup
    +configUpdateStrategy
    - -CrdKind + +ConfigUpdateStrategy
    +(Optional) +

    ConfigUpdateStrategy of the component. Override the cluster-level updateStrategy if present +Optional: Defaults to cluster-level setting

    -Restore
    +env
    - -CrdKind + +[]Kubernetes core/v1.EnvVar
    +(Optional) +

    List of environment variables to set in the container, like +v1.Container.Env. +Note that following env names cannot be used and may be overrided by +tidb-operator built envs. +- NAMESPACE +- TZ +- SERVICE_NAME +- PEER_SERVICE_NAME +- HEADLESS_SERVICE_NAME +- SET_NAME +- HOSTNAME +- CLUSTER_NAME +- POD_NAME +- BINLOG_ENABLED +- SLOW_LOG_FILE

    -BackupSchedule
    +additionalContainers
    - -CrdKind + +[]Kubernetes core/v1.Container
    +(Optional) +

    Additional containers of the component.

    -TiDBMonitor
    +additionalVolumes
    - -CrdKind + +[]Kubernetes core/v1.Volume
    +(Optional) +

    Additional volumes of component pod. Currently this only +supports additional volume mounts for sidecar containers.

    -TiDBInitializer
    +terminationGracePeriodSeconds
    - -CrdKind - +int64
    +(Optional) +

    Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. +Value must be non-negative integer. The value zero indicates delete immediately. +If this value is nil, the default grace period will be used instead. +The grace period is the duration in seconds after the processes running in the pod are sent +a termination signal and the time when the processes are forcibly halted with a kill signal. +Set this value longer than the expected cleanup time for your process. +Defaults to 30 seconds.

    +

    ConfigMapRef

    +

    +(Appears on: +PrometheusConfiguration) +

    +

    +

    ConfigMapRef is the external configMap

    +

    + + - - + + + +
    -TidbClusterAutoScaler
    - - -CrdKind - - -
    -FieldDescription
    -TiKVGroup
    +name
    - -CrdKind - +string
    @@ -3681,24 +3683,34 @@ CrdKind
    -TiDBGroup
    +namespace
    - -CrdKind - +string
    +(Optional) +

    if the namespace is omitted, the operator controller would use the Tidbmonitor’s namespace instead.

    -

    CustomMetric

    +

    ConfigUpdateStrategy

    (Appears on: -BasicAutoScalerSpec) +ComponentSpec, +TidbClusterSpec) +

    +

    +

    ConfigUpdateStrategy represents the strategy to update configuration

    +

    +

    CoprocessorCache

    +

    +(Appears on: +TiKVClient)

    +

    CoprocessorCache is the config for coprocessor cache.

    @@ -3706,67 +3718,65 @@ CrdKind - - + + + + + +
    Field Description
    +enabled
    + +bool + +
    +(Optional) +

    Whether to enable the copr cache. The copr cache saves the result from TiKV Coprocessor in the memory and +reuses the result when corresponding data in TiKV is unchanged, on a region basis.

    +
    -MetricSpec
    +capacity-mb
    - -Kubernetes autoscaling/v2beta2.MetricSpec - +float64
    -

    -(Members of MetricSpec are embedded into this type.) -

    (Optional) -

    metrics contains the specifications for which to use to calculate the -desired replica count (the maximum replica count across all metrics will -be used). The desired replica count is calculated multiplying the -ratio between the target value and the current value by the current -number of pods. Ergo, metrics used must decrease as the pod count is -increased, and vice-versa. See the individual metric source types for -more information about how each type of metric must respond. -If not set, the auto-scaling won’t happen.

    +

    The capacity in MB of the cache.

    -leastStoragePressurePeriodSeconds
    +admission-max-result-mb
    -int64 +float64
    (Optional) -

    LeastStoragePressurePeriodSeconds is only for the storage auto-scaling case when the resource name in the metricSpec -is Storage. When the Storage metrics meet the pressure, Operator would wait -LeastStoragePressurePeriodSeconds duration then able to scale out. -If not set, the default value is 300

    +

    Only cache requests whose result set is small.

    -leastRemainAvailableStoragePercent
    +admission-min-process-ms
    -int64 +uint64
    (Optional) -

    LeastRemainAvailableStoragePercent indicates the least remaining available storage percent compare to -the capacity storage. If the available storage is lower than the capacity storage * LeastRemainAvailableStoragePercent, -the storage status will become storage pressure and ready to be scaled out. -LeastRemainAvailableStoragePercent should between 5 and 90. If not set, the default value would be 10

    +

    Only cache requests takes notable time to process.

    -

    DMCluster

    +

    CrdKind

    +

    +(Appears on: +CrdKinds) +

    -

    DMCluster is the control script’s spec

    @@ -3778,257 +3788,266 @@ LeastRemainAvailableStoragePercent should between 5 and 90. If not set, the defa diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index 90fc8591bb..f5c469dd24 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -41,6 +41,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ComponentSpec": schema_pkg_apis_pingcap_v1alpha1_ComponentSpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.ConfigMapRef": schema_pkg_apis_pingcap_v1alpha1_ConfigMapRef(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMCluster": schema_pkg_apis_pingcap_v1alpha1_DMCluster(ref), + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMClusterList": schema_pkg_apis_pingcap_v1alpha1_DMClusterList(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMClusterSpec": schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMDiscoverySpec": schema_pkg_apis_pingcap_v1alpha1_DMDiscoverySpec(ref), "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DashboardConfig": schema_pkg_apis_pingcap_v1alpha1_DashboardConfig(ref), @@ -1323,6 +1324,48 @@ func schema_pkg_apis_pingcap_v1alpha1_DMCluster(ref common.ReferenceCallback) co } } +func schema_pkg_apis_pingcap_v1alpha1_DMClusterList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DMClusterList is DMCluster list", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMCluster"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.DMCluster"}, + } +} + func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index bdf698fa6f..60af4a6197 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -1449,6 +1449,9 @@ type IngressSpec struct { TLS []extensionsv1beta1.IngressTLS `json:"tls,omitempty"` } +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + // +k8s:openapi-gen=true // DMCluster is the control script's spec type DMCluster struct { @@ -1464,6 +1467,18 @@ type DMCluster struct { Status DMClusterStatus `json:"status"` } +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// +k8s:openapi-gen=true +// DMClusterList is DMCluster list +type DMClusterList struct { + metav1.TypeMeta `json:",inline"` + // +k8s:openapi-gen=false + metav1.ListMeta `json:"metadata"` + + Items []DMCluster `json:"items"` +} + // +k8s:openapi-gen=true // DMDiscoverySpec contains details of Discovery members for dm type DMDiscoverySpec struct { @@ -1479,7 +1494,7 @@ type DMClusterSpec struct { // dm-master cluster spec // +optional - Master *MasterSpec `json:"master,omitempty"` + Master *MasterSpec `json:"master"` // dm-worker cluster spec // +optional @@ -1545,7 +1560,7 @@ type DMClusterSpec struct { // DMClusterStatus represents the current status of a dm cluster. type DMClusterStatus struct { - Master MasterStatus `json:"master,omitempty"` + Master MasterStatus `json:"master"` Worker WorkerStatus `json:"worker,omitempty"` // Represents the latest available observations of a dm cluster's state. diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index 0fe7898077..7f4404efbd 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -855,6 +855,14 @@ func (in *DMCluster) DeepCopy() *DMCluster { return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DMCluster) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DMClusterCondition) DeepCopyInto(out *DMClusterCondition) { *out = *in @@ -873,6 +881,39 @@ func (in *DMClusterCondition) DeepCopy() *DMClusterCondition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DMClusterList) DeepCopyInto(out *DMClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DMCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DMClusterList. +func (in *DMClusterList) DeepCopy() *DMClusterList { + if in == nil { + return nil + } + out := new(DMClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DMClusterList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DMClusterSpec) DeepCopyInto(out *DMClusterSpec) { *out = *in diff --git a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/dmcluster.go b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/dmcluster.go new file mode 100644 index 0000000000..ba84481c0e --- /dev/null +++ b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/dmcluster.go @@ -0,0 +1,188 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + scheme "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// DMClustersGetter has a method to return a DMClusterInterface. +// A group's client should implement this interface. +type DMClustersGetter interface { + DMClusters(namespace string) DMClusterInterface +} + +// DMClusterInterface has methods to work with DMCluster resources. +type DMClusterInterface interface { + Create(*v1alpha1.DMCluster) (*v1alpha1.DMCluster, error) + Update(*v1alpha1.DMCluster) (*v1alpha1.DMCluster, error) + UpdateStatus(*v1alpha1.DMCluster) (*v1alpha1.DMCluster, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.DMCluster, error) + List(opts v1.ListOptions) (*v1alpha1.DMClusterList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.DMCluster, err error) + DMClusterExpansion +} + +// dMClusters implements DMClusterInterface +type dMClusters struct { + client rest.Interface + ns string +} + +// newDMClusters returns a DMClusters +func newDMClusters(c *PingcapV1alpha1Client, namespace string) *dMClusters { + return &dMClusters{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the dMCluster, and returns the corresponding dMCluster object, and an error if there is any. +func (c *dMClusters) Get(name string, options v1.GetOptions) (result *v1alpha1.DMCluster, err error) { + result = &v1alpha1.DMCluster{} + err = c.client.Get(). + Namespace(c.ns). + Resource("dmclusters"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of DMClusters that match those selectors. +func (c *dMClusters) List(opts v1.ListOptions) (result *v1alpha1.DMClusterList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.DMClusterList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("dmclusters"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested dMClusters. +func (c *dMClusters) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("dmclusters"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a dMCluster and creates it. Returns the server's representation of the dMCluster, and an error, if there is any. +func (c *dMClusters) Create(dMCluster *v1alpha1.DMCluster) (result *v1alpha1.DMCluster, err error) { + result = &v1alpha1.DMCluster{} + err = c.client.Post(). + Namespace(c.ns). + Resource("dmclusters"). + Body(dMCluster). + Do(). + Into(result) + return +} + +// Update takes the representation of a dMCluster and updates it. Returns the server's representation of the dMCluster, and an error, if there is any. +func (c *dMClusters) Update(dMCluster *v1alpha1.DMCluster) (result *v1alpha1.DMCluster, err error) { + result = &v1alpha1.DMCluster{} + err = c.client.Put(). + Namespace(c.ns). + Resource("dmclusters"). + Name(dMCluster.Name). + Body(dMCluster). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *dMClusters) UpdateStatus(dMCluster *v1alpha1.DMCluster) (result *v1alpha1.DMCluster, err error) { + result = &v1alpha1.DMCluster{} + err = c.client.Put(). + Namespace(c.ns). + Resource("dmclusters"). + Name(dMCluster.Name). + SubResource("status"). + Body(dMCluster). + Do(). + Into(result) + return +} + +// Delete takes name of the dMCluster and deletes it. Returns an error if one occurs. +func (c *dMClusters) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("dmclusters"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *dMClusters) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("dmclusters"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched dMCluster. +func (c *dMClusters) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.DMCluster, err error) { + result = &v1alpha1.DMCluster{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("dmclusters"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_dmcluster.go b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_dmcluster.go new file mode 100644 index 0000000000..db4a56c12c --- /dev/null +++ b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_dmcluster.go @@ -0,0 +1,137 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeDMClusters implements DMClusterInterface +type FakeDMClusters struct { + Fake *FakePingcapV1alpha1 + ns string +} + +var dmclustersResource = schema.GroupVersionResource{Group: "pingcap.com", Version: "v1alpha1", Resource: "dmclusters"} + +var dmclustersKind = schema.GroupVersionKind{Group: "pingcap.com", Version: "v1alpha1", Kind: "DMCluster"} + +// Get takes name of the dMCluster, and returns the corresponding dMCluster object, and an error if there is any. +func (c *FakeDMClusters) Get(name string, options v1.GetOptions) (result *v1alpha1.DMCluster, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(dmclustersResource, c.ns, name), &v1alpha1.DMCluster{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.DMCluster), err +} + +// List takes label and field selectors, and returns the list of DMClusters that match those selectors. +func (c *FakeDMClusters) List(opts v1.ListOptions) (result *v1alpha1.DMClusterList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(dmclustersResource, dmclustersKind, c.ns, opts), &v1alpha1.DMClusterList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.DMClusterList{ListMeta: obj.(*v1alpha1.DMClusterList).ListMeta} + for _, item := range obj.(*v1alpha1.DMClusterList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested dMClusters. +func (c *FakeDMClusters) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(dmclustersResource, c.ns, opts)) + +} + +// Create takes the representation of a dMCluster and creates it. Returns the server's representation of the dMCluster, and an error, if there is any. +func (c *FakeDMClusters) Create(dMCluster *v1alpha1.DMCluster) (result *v1alpha1.DMCluster, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(dmclustersResource, c.ns, dMCluster), &v1alpha1.DMCluster{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.DMCluster), err +} + +// Update takes the representation of a dMCluster and updates it. Returns the server's representation of the dMCluster, and an error, if there is any. +func (c *FakeDMClusters) Update(dMCluster *v1alpha1.DMCluster) (result *v1alpha1.DMCluster, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(dmclustersResource, c.ns, dMCluster), &v1alpha1.DMCluster{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.DMCluster), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeDMClusters) UpdateStatus(dMCluster *v1alpha1.DMCluster) (*v1alpha1.DMCluster, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(dmclustersResource, "status", c.ns, dMCluster), &v1alpha1.DMCluster{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.DMCluster), err +} + +// Delete takes name of the dMCluster and deletes it. Returns an error if one occurs. +func (c *FakeDMClusters) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(dmclustersResource, c.ns, name), &v1alpha1.DMCluster{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeDMClusters) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(dmclustersResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.DMClusterList{}) + return err +} + +// Patch applies the patch and returns the patched dMCluster. +func (c *FakeDMClusters) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.DMCluster, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(dmclustersResource, c.ns, name, pt, data, subresources...), &v1alpha1.DMCluster{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.DMCluster), err +} diff --git a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go index f3c318238f..3900301a7b 100644 --- a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go +++ b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go @@ -33,6 +33,10 @@ func (c *FakePingcapV1alpha1) BackupSchedules(namespace string) v1alpha1.BackupS return &FakeBackupSchedules{c, namespace} } +func (c *FakePingcapV1alpha1) DMClusters(namespace string) v1alpha1.DMClusterInterface { + return &FakeDMClusters{c, namespace} +} + func (c *FakePingcapV1alpha1) DataResources(namespace string) v1alpha1.DataResourceInterface { return &FakeDataResources{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go index 5b29045b93..ee6b746696 100644 --- a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go @@ -19,6 +19,8 @@ type BackupExpansion interface{} type BackupScheduleExpansion interface{} +type DMClusterExpansion interface{} + type DataResourceExpansion interface{} type RestoreExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go index 4b3fde549b..b7b40ce754 100644 --- a/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go +++ b/pkg/client/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go @@ -25,6 +25,7 @@ type PingcapV1alpha1Interface interface { RESTClient() rest.Interface BackupsGetter BackupSchedulesGetter + DMClustersGetter DataResourcesGetter RestoresGetter TiDBGroupsGetter @@ -48,6 +49,10 @@ func (c *PingcapV1alpha1Client) BackupSchedules(namespace string) BackupSchedule return newBackupSchedules(c, namespace) } +func (c *PingcapV1alpha1Client) DMClusters(namespace string) DMClusterInterface { + return newDMClusters(c, namespace) +} + func (c *PingcapV1alpha1Client) DataResources(namespace string) DataResourceInterface { return newDataResources(c, namespace) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index ddc078867d..6cc0ecbbc6 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -54,6 +54,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Pingcap().V1alpha1().Backups().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("backupschedules"): return &genericInformer{resource: resource.GroupResource(), informer: f.Pingcap().V1alpha1().BackupSchedules().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("dmclusters"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Pingcap().V1alpha1().DMClusters().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("dataresources"): return &genericInformer{resource: resource.GroupResource(), informer: f.Pingcap().V1alpha1().DataResources().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("restores"): diff --git a/pkg/client/informers/externalversions/pingcap/v1alpha1/dmcluster.go b/pkg/client/informers/externalversions/pingcap/v1alpha1/dmcluster.go new file mode 100644 index 0000000000..3777584152 --- /dev/null +++ b/pkg/client/informers/externalversions/pingcap/v1alpha1/dmcluster.go @@ -0,0 +1,86 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + pingcapv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + versioned "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/pingcap/tidb-operator/pkg/client/listers/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// DMClusterInformer provides access to a shared informer and lister for +// DMClusters. +type DMClusterInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.DMClusterLister +} + +type dMClusterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewDMClusterInformer constructs a new informer for DMCluster type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewDMClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredDMClusterInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredDMClusterInformer constructs a new informer for DMCluster type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredDMClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.PingcapV1alpha1().DMClusters(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.PingcapV1alpha1().DMClusters(namespace).Watch(options) + }, + }, + &pingcapv1alpha1.DMCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *dMClusterInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredDMClusterInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *dMClusterInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&pingcapv1alpha1.DMCluster{}, f.defaultInformer) +} + +func (f *dMClusterInformer) Lister() v1alpha1.DMClusterLister { + return v1alpha1.NewDMClusterLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/pingcap/v1alpha1/interface.go b/pkg/client/informers/externalversions/pingcap/v1alpha1/interface.go index b78f208182..eeee742df7 100644 --- a/pkg/client/informers/externalversions/pingcap/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/pingcap/v1alpha1/interface.go @@ -25,6 +25,8 @@ type Interface interface { Backups() BackupInformer // BackupSchedules returns a BackupScheduleInformer. BackupSchedules() BackupScheduleInformer + // DMClusters returns a DMClusterInformer. + DMClusters() DMClusterInformer // DataResources returns a DataResourceInformer. DataResources() DataResourceInformer // Restores returns a RestoreInformer. @@ -64,6 +66,11 @@ func (v *version) BackupSchedules() BackupScheduleInformer { return &backupScheduleInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// DMClusters returns a DMClusterInformer. +func (v *version) DMClusters() DMClusterInformer { + return &dMClusterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // DataResources returns a DataResourceInformer. func (v *version) DataResources() DataResourceInformer { return &dataResourceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/listers/pingcap/v1alpha1/dmcluster.go b/pkg/client/listers/pingcap/v1alpha1/dmcluster.go new file mode 100644 index 0000000000..73eae1cf2b --- /dev/null +++ b/pkg/client/listers/pingcap/v1alpha1/dmcluster.go @@ -0,0 +1,91 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// DMClusterLister helps list DMClusters. +type DMClusterLister interface { + // List lists all DMClusters in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.DMCluster, err error) + // DMClusters returns an object that can list and get DMClusters. + DMClusters(namespace string) DMClusterNamespaceLister + DMClusterListerExpansion +} + +// dMClusterLister implements the DMClusterLister interface. +type dMClusterLister struct { + indexer cache.Indexer +} + +// NewDMClusterLister returns a new DMClusterLister. +func NewDMClusterLister(indexer cache.Indexer) DMClusterLister { + return &dMClusterLister{indexer: indexer} +} + +// List lists all DMClusters in the indexer. +func (s *dMClusterLister) List(selector labels.Selector) (ret []*v1alpha1.DMCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.DMCluster)) + }) + return ret, err +} + +// DMClusters returns an object that can list and get DMClusters. +func (s *dMClusterLister) DMClusters(namespace string) DMClusterNamespaceLister { + return dMClusterNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// DMClusterNamespaceLister helps list and get DMClusters. +type DMClusterNamespaceLister interface { + // List lists all DMClusters in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.DMCluster, err error) + // Get retrieves the DMCluster from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.DMCluster, error) + DMClusterNamespaceListerExpansion +} + +// dMClusterNamespaceLister implements the DMClusterNamespaceLister +// interface. +type dMClusterNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all DMClusters in the indexer for a given namespace. +func (s dMClusterNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.DMCluster, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.DMCluster)) + }) + return ret, err +} + +// Get retrieves the DMCluster from the indexer for a given namespace and name. +func (s dMClusterNamespaceLister) Get(name string) (*v1alpha1.DMCluster, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("dmcluster"), name) + } + return obj.(*v1alpha1.DMCluster), nil +} diff --git a/pkg/client/listers/pingcap/v1alpha1/expansion_generated.go b/pkg/client/listers/pingcap/v1alpha1/expansion_generated.go index ad226cc86a..f94a06d965 100644 --- a/pkg/client/listers/pingcap/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/pingcap/v1alpha1/expansion_generated.go @@ -31,6 +31,14 @@ type BackupScheduleListerExpansion interface{} // BackupScheduleNamespaceLister. type BackupScheduleNamespaceListerExpansion interface{} +// DMClusterListerExpansion allows custom methods to be added to +// DMClusterLister. +type DMClusterListerExpansion interface{} + +// DMClusterNamespaceListerExpansion allows custom methods to be added to +// DMClusterNamespaceLister. +type DMClusterNamespaceListerExpansion interface{} + // DataResourceListerExpansion allows custom methods to be added to // DataResourceLister. type DataResourceListerExpansion interface{} From 3edfaa2bea900dbf69ccc7b766ad9635d3bf36af Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 6 Aug 2020 23:02:23 +0800 Subject: [PATCH 06/37] address comments --- docs/api-references/docs.md | 6 +++--- pkg/apis/pingcap/v1alpha1/dm_config.go | 4 ++-- pkg/apis/pingcap/v1alpha1/openapi_generated.go | 6 +++--- pkg/apis/pingcap/v1alpha1/pd_config.go | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 13802a534c..66ac4b90cf 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -4491,7 +4491,7 @@ string @@ -8147,7 +8147,7 @@ string @@ -18574,7 +18574,7 @@ int64 diff --git a/pkg/apis/pingcap/v1alpha1/dm_config.go b/pkg/apis/pingcap/v1alpha1/dm_config.go index 1762ea8f16..73f7152a02 100644 --- a/pkg/apis/pingcap/v1alpha1/dm_config.go +++ b/pkg/apis/pingcap/v1alpha1/dm_config.go @@ -71,7 +71,7 @@ type WorkerConfig struct { // +optional LogFormat *string `toml:"log-format,omitempty" json:"log-format,omitempty"` - // KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd + // KeepAliveTTL is the keepalive TTL when dm-worker writes to the embedded etcd of dm-master // Optional: Defaults to 10 // +optional KeepAliveTTL *int64 `toml:"keepalive-ttl,omitempty" json:"keepalive-ttl,omitempty"` @@ -82,7 +82,7 @@ type WorkerConfig struct { // DM common security config type DMSecurityConfig struct { - // SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty + // SSLCA is the path of file that contains list of trusted SSL CAs. // +optional SSLCA *string `toml:"ssl-ca,omitempty" json:"ssl-ca,omitempty" yaml:"ssl-ca,omitempty"` // SSLCert is the path of file that contains X509 certificate in PEM format. diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index f5c469dd24..1f90a3caf7 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -3482,7 +3482,7 @@ func schema_pkg_apis_pingcap_v1alpha1_PDSecurityConfig(ref common.ReferenceCallb Properties: map[string]spec.Schema{ "cacert-path": { SchemaProps: spec.SchemaProps{ - Description: "CAPath is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty", + Description: "CAPath is the path of file that contains list of trusted SSL CAs.", Type: []string{"string"}, Format: "", }, @@ -10727,14 +10727,14 @@ func schema_pkg_apis_pingcap_v1alpha1_WorkerConfig(ref common.ReferenceCallback) }, "keepalive-ttl": { SchemaProps: spec.SchemaProps{ - Description: "KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd Optional: Defaults to 10", + Description: "KeepAliveTTL is the keepalive TTL when dm-worker writes to the embedded etcd of dm-master Optional: Defaults to 10", Type: []string{"integer"}, Format: "int64", }, }, "ssl-ca": { SchemaProps: spec.SchemaProps{ - Description: "SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty", + Description: "SSLCA is the path of file that contains list of trusted SSL CAs.", Type: []string{"string"}, Format: "", }, diff --git a/pkg/apis/pingcap/v1alpha1/pd_config.go b/pkg/apis/pingcap/v1alpha1/pd_config.go index 5514961232..42990975b6 100644 --- a/pkg/apis/pingcap/v1alpha1/pd_config.go +++ b/pkg/apis/pingcap/v1alpha1/pd_config.go @@ -414,7 +414,7 @@ type PDLabelPropertyConfig map[string]PDStoreLabels // PDSecurityConfig is the configuration for supporting tls. // +k8s:openapi-gen=true type PDSecurityConfig struct { - // CAPath is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty + // CAPath is the path of file that contains list of trusted SSL CAs. // +optional CAPath *string `toml:"cacert-path,omitempty" json:"cacert-path,omitempty"` // CertPath is the path of file that contains X509 certificate in PEM format. From 2c1bec54f13aa0e143ea7c7b258b66e6714ea3e5 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Fri, 7 Aug 2020 10:56:18 +0800 Subject: [PATCH 07/37] address comment --- docs/api-references/docs.md | 3 +++ pkg/apis/pingcap/v1alpha1/types.go | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 765c5dc1fd..393a0119be 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -6179,6 +6179,9 @@ ServiceSpec diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 60af4a6197..5d67cb8d76 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -1616,8 +1616,7 @@ type MasterSpec struct { } type MasterServiceSpec struct { - // +k8s:openapi-gen=false - ServiceSpec + ServiceSpec `json:",inline"` // ExternalTrafficPolicy of the service // Optional: Defaults to omitted From fbe26f3c1c1ce62a6ff054c4265d0d866c8850d6 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Fri, 7 Aug 2020 20:01:41 +0800 Subject: [PATCH 08/37] tmp commit --- cmd/discovery/main.go | 4 +- go.mod | 50 +-- go.sum | 538 +++++++++++++++++++++++++ pkg/apis/pingcap/v1alpha1/dmcluster.go | 25 ++ pkg/discovery/discovery.go | 77 +++- pkg/discovery/discovery_test.go | 387 +++++++++++++++++- pkg/discovery/server/server.go | 34 +- pkg/discovery/server/server_test.go | 4 +- pkg/dmapi/dmapi.go | 106 +++++ pkg/dmapi/fake_dmapi.go | 84 ++++ pkg/dmapi/master_control.go | 101 +++++ 11 files changed, 1365 insertions(+), 45 deletions(-) create mode 100644 pkg/apis/pingcap/v1alpha1/dmcluster.go create mode 100644 pkg/dmapi/dmapi.go create mode 100644 pkg/dmapi/fake_dmapi.go create mode 100644 pkg/dmapi/master_control.go diff --git a/cmd/discovery/main.go b/cmd/discovery/main.go index 6a0136b6fc..97d15dc524 100644 --- a/cmd/discovery/main.go +++ b/cmd/discovery/main.go @@ -22,6 +22,8 @@ import ( "strconv" "time" + "github.com/pingcap/tidb-operator/pkg/dmapi" + "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" "github.com/pingcap/tidb-operator/pkg/discovery/server" "github.com/pingcap/tidb-operator/pkg/pdapi" @@ -87,7 +89,7 @@ func main() { go wait.Forever(func() { addr := fmt.Sprintf("0.0.0.0:%d", port) klog.Infof("starting TiDB Discovery server, listening on %s", addr) - discoveryServer := server.NewServer(pdapi.NewDefaultPDControl(kubeCli), cli, kubeCli) + discoveryServer := server.NewServer(pdapi.NewDefaultPDControl(kubeCli), dmapi.NewDefaultMasterControl(kubeCli), cli, kubeCli) discoveryServer.ListenAndServe(addr) }, 5*time.Second) go wait.Forever(func() { diff --git a/go.mod b/go.mod index 3ac43dbca4..0e3368cd29 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,11 @@ require ( github.com/Azure/go-autorest/autorest/mocks v0.3.0 // indirect github.com/BurntSushi/toml v0.3.1 github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect - github.com/Masterminds/semver v1.4.2 + github.com/Masterminds/semver v1.5.0 github.com/Microsoft/go-winio v0.4.12 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/aws/aws-sdk-go v1.30.9 + github.com/aws/aws-sdk-go v1.30.24 github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect - github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect github.com/coreos/etcd v3.3.15+incompatible github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 github.com/docker/go-connections v0.4.0 // indirect @@ -25,59 +24,46 @@ require ( github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect; indirectload github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect github.com/emicklei/go-restful v2.9.5+incompatible - github.com/fatih/color v1.7.0 + github.com/fatih/color v1.9.0 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-openapi/loads v0.19.4 - github.com/go-openapi/spec v0.19.3 + github.com/go-openapi/spec v0.19.7 github.com/go-sql-driver/mysql v1.5.0 github.com/gogo/protobuf v1.3.1 - github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect - github.com/golang/snappy v0.0.1 // indirect - github.com/google/go-cmp v0.3.1 + github.com/google/go-cmp v0.4.0 github.com/gophercloud/gophercloud v0.3.0 // indirect github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.13.0 // indirect github.com/imdario/mergo v0.3.7 // indirect - github.com/juju/errors v0.0.0-20180806074554-22422dad46e1 + github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 github.com/juju/loggo v0.0.0-20180524022052-584905176618 // indirect - github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 // indirect github.com/mholt/archiver v3.1.1+incompatible github.com/minio/minio-go/v6 v6.0.55 github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb github.com/nwaples/rardecode v1.0.0 // indirect - github.com/onsi/ginkgo v1.10.3 - github.com/onsi/gomega v1.5.0 + github.com/onsi/ginkgo v1.11.0 + github.com/onsi/gomega v1.8.1 github.com/openshift/generic-admission-server v1.14.0 - github.com/opentracing/opentracing-go v1.1.0 // indirect - github.com/pierrec/lz4 v2.0.5+incompatible // indirect github.com/pingcap/advanced-statefulset/client v1.16.0 - github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 // indirect - github.com/pingcap/errors v0.11.0 - github.com/pingcap/kvproto v0.0.0-20191217072959-393e6c0fd4b7 + github.com/pingcap/dm v1.1.0-alpha.0.20200806100226-77bbd6b052b4 + github.com/pingcap/errors v0.11.5-0.20190809092503-95897b64e011 + github.com/pingcap/kvproto v0.0.0-20200706115936-1e0910aabe6c github.com/pingcap/pd v2.1.17+incompatible github.com/pingcap/tidb v2.1.0-beta+incompatible - github.com/prometheus/client_golang v0.9.2 - github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 + github.com/prometheus/client_golang v1.5.1 + github.com/prometheus/common v0.9.1 github.com/prometheus/prometheus v1.8.2 github.com/robfig/cron v1.1.0 - github.com/sirupsen/logrus v1.5.0 - github.com/soheilhy/cmux v0.1.4 // indirect - github.com/spf13/cobra v0.0.5 - github.com/spf13/pflag v1.0.3 - github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect - github.com/uber-go/atomic v0.0.0-00010101000000-000000000000 // indirect - github.com/uber/jaeger-client-go v2.19.0+incompatible // indirect - github.com/uber/jaeger-lib v2.2.0+incompatible // indirect - github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 + github.com/sirupsen/logrus v1.6.0 + github.com/spf13/cobra v1.0.0 + github.com/spf13/pflag v1.0.5 + github.com/ugorji/go/codec v1.1.7 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/yisaer/crd-validation v0.0.3 gocloud.dev v0.18.0 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e gomodules.xyz/jsonpatch/v2 v2.0.1 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect - gopkg.in/yaml.v2 v2.2.4 + gopkg.in/yaml.v2 v2.2.8 k8s.io/api v0.0.0 k8s.io/apiextensions-apiserver v0.0.0 k8s.io/apimachinery v0.0.0 diff --git a/go.sum b/go.sum index 06acb3dc4e..6466652ba0 100644 --- a/go.sum +++ b/go.sum @@ -5,11 +5,25 @@ cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.39.0 h1:UgQP9na6OTfp4dsAiz/eFpFA1C6tPdH5wiRdi19tuMw= cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= +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/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/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +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/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.4.0/go.mod h1:ZusYJWlOshgSBGbt6K3GnB3MT3H1xs2id9+TCl4fDBA= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= @@ -44,15 +58,20 @@ github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190605020000-c4ba1fdf4d36/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534 h1:N7lSsF+R7wSulUADi36SInSQA3RvfO/XclHQfedr0qk= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= +github.com/Jeffail/gabs/v2 v2.5.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e h1:eb0Pzkt15Bm7f2FFYv7sjY7NPFi3cPkS3tv1CcrFBWA= github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -60,6 +79,7 @@ github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXn github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -68,8 +88,16 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Rican7/retry v0.1.0/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg= +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +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 v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/appleboy/gin-jwt/v2 v2.6.3/go.mod h1:MfPYA4ogzvOcVkRwAxT7quHOtQmVKDpTwxyUrC2DNw0= +github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -81,30 +109,47 @@ github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.19.45 h1:jAxmC8qqa7mW531FDgM8Ahbqlb3zmiHgTpJU6fY3vJ0= github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.26.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.9 h1:DntpBUKkchINPDbhEzDRin1eEn1TG9TZFlzWPf0i8to= github.com/aws/aws-sdk-go v1.30.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.30.24/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/bazelbuild/bazel-gazelle v0.0.0-20181012220611-c728ce9f663e/go.mod h1:uHBSeeATKpVazAACZBDPL/Nk/UhQDDsJWDlqYJo8/Us= github.com/bazelbuild/buildtools v0.0.0-20180226164855-80c7f0d45d7e/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= 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/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= +github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU= github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY= +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/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho= github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/cheggaaa/pb/v3 v3.0.1/go.mod h1:SqqeMF/pMOIu3xgGoxtPYhMNQP258xE4x/XRTYua+KU= +github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cfssl v0.0.0-20180726162950-56268a613adf/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= @@ -113,9 +158,14 @@ github.com/containerd/console v0.0.0-20170925154832-84eeaae905fa/go.mod h1:Tj/on github.com/containerd/containerd v1.0.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/coocood/badger v1.5.1-0.20200515070411-e02af0688441/go.mod h1:klY8SfH2lNZ/23/SIxwHoJw+T6wYGB12YPCF9MUoiu0= +github.com/coocood/badger v1.5.1-0.20200528065104-c02ac3616d04/go.mod h1:klY8SfH2lNZ/23/SIxwHoJw+T6wYGB12YPCF9MUoiu0= +github.com/coocood/bbloom v0.0.0-20190830030839-58deb6228d64/go.mod h1:F86k/6c7aDUdwSUevnLpHS/3Q9hzYCE99jGk2xsHnt0= +github.com/coocood/rtutil v0.0.0-20190304133409-c84515f646f2/go.mod h1:7qG7YFnOALvsx6tKTNmQot8d7cGFXM9TidzvRFLWYwM= github.com/coredns/corefile-migration v1.0.2/go.mod h1:OFwBp/Wc9dJt5cAZzHWMNhK1r5L0p0jDwIBc6j8NC8E= github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A= github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE= github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -126,19 +176,42 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea h1:n2Ltr3SrfQlf/9nOna1DoGKxLx3qTSI8Ttl6Xrqp6mw= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/rkt v1.30.0/go.mod h1:O634mlH6U7qk87poQifK6M2rsFNt+FyUTWNMnP1hF1U= +github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cznic/golex v0.0.0-20181122101858-9c343928389c/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= +github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM= +github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= +github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= +github.com/cznic/y v0.0.0-20170802143616-045f81c6662a/go.mod h1:1rk5VM7oSnA4vjp+hrLQ3HWHa+Y4yPCa3/CsJrcNnvs= +github.com/danjacques/gofslock v0.0.0-20191023191349-0a45f885bc37/go.mod h1:DC3JtzuG7kxMvJ6dZmf2ymjNyoXwgtklr7FN+Um2B0U= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= +github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= @@ -150,6 +223,7 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s= @@ -158,9 +232,13 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs= github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -169,6 +247,10 @@ github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -181,27 +263,48 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 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/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsouza/fake-gcs-server v1.15.0/go.mod h1:HNxAJ/+FY/XSsxuwz8iIYdp2GtMmPbJ8WQjjGMxd6Qk= +github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= +github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w= +github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= +github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= +github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +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-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +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-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -221,8 +324,11 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -234,9 +340,13 @@ github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.7 h1:0xWSeMd35y5avQAThZR2PkEuqSosoS5t6gDH4L8n11M= +github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= @@ -248,9 +358,16 @@ github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.8 h1:vfK6jLhs7OI4tAXkvkooviaE1JEPcw3mutyegLHHjmk= +github.com/go-openapi/swag v0.19.8/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= +github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/overalls v0.0.0-20180201144345-22ec1a223b7c/go.mod h1:UqxAgEOt89sCiXlrc/ycnx00LVvUO/eS8tMUkWX4R7w= +github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= @@ -377,21 +494,33 @@ github.com/gobuffalo/uuid v2.0.5+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw github.com/gobuffalo/validate v2.0.3+incompatible/go.mod h1:N+EtDe0J8252BgfzQUChBgfd6L93m9weay53EWFVsMM= github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOreDJznWevcn8NTmQEW5STSBgIkpkjzqXc= github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY= +github.com/goccy/go-graphviz v0.0.5/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= github.com/gogo/protobuf v0.0.0-20180717141946-636bf0302bc9/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff h1:kOkM9whyQYodu09SJ6W3NCsHG7crFaJILQ22Gozp3lg= github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/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 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= 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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -401,6 +530,9 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= @@ -408,12 +540,15 @@ github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkY github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= 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/cadvisor v0.34.0/go.mod h1:1nql6U13uTHaLYB8rLS5x9IJc2qT6Xd/Tr1sTX6NE48= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= 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 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-replayers/grpcreplay v0.1.0 h1:eNb1y9rZFmY4ax45uEEECSa8fsxGRU+8Bil52ASAwic= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0 h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk= @@ -425,7 +560,11 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 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-20190930153522-6ce02741cba3/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20200407044318-7d83b28da2e9/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -436,6 +575,7 @@ github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= 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/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= @@ -445,29 +585,42 @@ github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEo 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/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.1.2/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q= github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.2 h1:S+ef0492XaIknb8LMjcwgW2i3cNTzDYMmDrOThOJNWc= github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI= github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= +github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= +github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= +github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69/go.mod h1:YLEMZOtU+AZ7dhN9T/IpGhXVGly2bvkJQ+zxj3WeVQo= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -481,6 +634,9 @@ github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7U github.com/heketi/utils v0.0.0-20170317161834-435bc5bdfa64/go.mod h1:RYlF4ghFZPPmk2TC5REt5OFwvfb6lzxFWrTWB+qs28s= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hypnoglow/gormzap v0.3.0/go.mod h1:5Wom8B7Jl2oK0Im9hs6KQ+Kl92w4Y7gKCrj66rhyvw0= +github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= @@ -489,7 +645,11 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= +github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -500,30 +660,54 @@ github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/joomcode/errorx v1.0.1/go.mod h1:kgco15ekB6cs+4Xjzo7SPeXzx38PbJzBwbnu9qfVNHQ= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/juju/clock v0.0.0-20180524022203-d293bb356ca4/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= +github.com/juju/errors v0.0.0-20150916125642-1b5e39b83d18/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/errors v0.0.0-20180806074554-22422dad46e1 h1:wnhMXidtb70kDZCeLt/EfsVtkXS5c8zLnE9y/6DIRAU= github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 h1:rhqTjzJlm7EbkELJDKMTU7udov+Se0xZkWmugr6zGok= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8= github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= +github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 h1:WQM1NildKThwdP7qWrNAFGzp4ijNLw8RlgENkaI4MJs= github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/juju/testing v0.0.0-20200510222523-6c8c298c77a0/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo= +github.com/juju/testing v0.0.0-20200608005635-e4eedbc6f7aa/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo= +github.com/juju/utils v0.0.0-20180808125547-9dfc6dbfb02b/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= +github.com/juju/version v0.0.0-20161031051906-1f41e27e54f2/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kevinburke/go-bindata v3.18.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -532,6 +716,9 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/lance6716/retool v1.3.7/go.mod h1:9nFHbMjlFhh2msJ6vuHgpz7OM7G9RO0wSLO/w1u2nhM= +github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= @@ -552,6 +739,8 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8= +github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c= @@ -574,18 +763,30 @@ github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRU github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +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-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mesos/mesos-go v0.0.9/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= +github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.0.2/go.mod h1:rb0dQy1LVAxW9SWy5R3LPUjevzUbUS316U5MFySA2lo= github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= @@ -616,27 +817,45 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb h1:e+l77LJOEqXTIQihQJVkA6ZxPOUmfPM5e4H7rcpgtSk= github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q= +github.com/montanaflynn/stats v0.0.0-20151014174947-eeaced052adb/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.0.0-20180911141734-db72e6cae808/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d h1:7PxY7LVfSZm7PEeBTyK1rj1gABdCO2mbri6GKO1cMDs= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mvdan/xurls v1.1.0/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8= github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/ncw/directio v1.0.4/go.mod h1:CKGdcN7StAaqjT7Qack3lAXeX4pjnyc46YeqZH1yWVY= +github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7/go.mod h1:iWMfgwqYW+e8n5lC/jjNEhwcjbRDpl5NT7n2h+4UNcI= +github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef/go.mod h1:7WjlapSfwQyo6LNmIvEWzsW1hbBQfpUO4JWnuQRmva8= +github.com/ngaut/unistore v0.0.0-20200521040325-2af94f1b0c83/go.mod h1:odn0MiR+DNxnxOiCskG4wWacBIW2GBmJOf/TAnMZfWE= +github.com/ngaut/unistore v0.0.0-20200603091253-e0b717679796/go.mod h1:9mpqZeS1CkNlgZwJ0LZXb+Qd7xVO5o55ngys7T1/oH8= +github.com/ngaut/unistore v0.0.0-20200604043635-5004cdad650f/go.mod h1:5Vec+R2BwOyugVQ8Id8uDmlIYbqodCvykM50IpaAjk4= +github.com/ngaut/unistore v0.0.0-20200604061006-d8e9dc0ad154/go.mod h1:YGQzxn9cVy0q2puXVt1X8l5OohRHv2djR/ziz1k14XQ= +github.com/ngaut/unistore v0.0.0-20200630072006-0c4035925f69/go.mod h1:Hxlp5VAoPOHwcXLUw/E+P3XjJX1EP38NWjXPpc4nuOE= github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs= github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -644,6 +863,8 @@ github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -653,6 +874,8 @@ github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= github.com/openshift/generic-admission-server v1.14.0 h1:GAQy5JNVcbmUuIpPvLd39+2rPecxEm7WQ2sP7ACrse4= github.com/openshift/generic-admission-server v1.14.0/go.mod h1:GD9KN/W4KxqRQGVMbqQHpHzb2XcQVvLCaBaSciqXvfM= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= @@ -660,22 +883,103 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/phf/go-queue v0.0.0-20170504031614-9abe38d0371d/go.mod h1:lXfE4PvvTW5xOjO6Mba8zDPyw8M93B6AQ7frTGnMlA8= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pingcap-incubator/tidb-dashboard v0.0.0-20200407064406-b2b8ad403d01/go.mod h1:77fCh8d3oKzC5ceOJWeZXAS/mLzVgdZ7rKniwmOyFuo= +github.com/pingcap-incubator/tidb-dashboard v0.0.0-20200514075710-eecc9a4525b5/go.mod h1:8q+yDx0STBPri8xS4A2duS1dAf+xO0cMtjwe0t6MWJk= +github.com/pingcap-incubator/tidb-dashboard v0.0.0-20200710045508-523e95bc5ec9/go.mod h1:9yaAM77sPfa5/f6sdxr3jSkKfIz463KRHyiFHiGjdes= github.com/pingcap/advanced-statefulset/client v1.16.0 h1:Wit+eYaXhKz0pIG6jixvyYxCVnQoZtpGzN9pXizkB9Y= github.com/pingcap/advanced-statefulset/client v1.16.0/go.mod h1:2IzDKzJxCHnrl3twx7yBnFX5csMeiBJFjlkUn0z0gZE= +github.com/pingcap/badger v1.5.1-0.20200604041313-19c397305fcc/go.mod h1:LyrqUOHZrUDf9oGi1yoz1+qw9ckSIhQb5eMa1acOLNQ= +github.com/pingcap/br v0.0.0-20200426093517-dd11ae28b885/go.mod h1:4w3meMnk7HDNpNgjuRAxavruTeKJvUiXxoEWTjzXPnA= +github.com/pingcap/br v0.0.0-20200521085655-53201addd4ad/go.mod h1:SlSUHWY7QUoooiYxOKuJ8kUh2KjI29ogBh89YXz2dLA= +github.com/pingcap/br v0.0.0-20200610051721-b057d65ff579/go.mod h1:Gq6o66nDReG0fMxqSdl8JHLZhMnxKhVxtHxqubUWAyg= +github.com/pingcap/br v0.0.0-20200617120402-56e151ad8b67/go.mod h1:/3QzpDG7YTPrDsrg8i1lwdYUrplJ0jVD+9pxhh19+k4= +github.com/pingcap/br v0.0.0-20200723130425-d904ae3349a1/go.mod h1:4iTqZAMbEPmjBggYixqIg2FwIHBQtyImTM/QYlpTBGk= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 h1:USx2/E1bX46VG32FIw034Au6seQ2fY9NEILmNh/UlQg= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= +github.com/pingcap/check v0.0.0-20191107115940-caf2b9e6ccf4/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= +github.com/pingcap/check v0.0.0-20191216031241-8a5a85928f12/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= +github.com/pingcap/check v0.0.0-20200212061837-5e12011dc712/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= +github.com/pingcap/dm v1.0.6 h1:jJrkgRtnJ2cVXCEVoPNMAlSaWxTnD5tH2l+ux/0sBHs= +github.com/pingcap/dm v1.1.0-alpha.0.20200806100226-77bbd6b052b4 h1:62ie/18pg0OISH9sCZFZ1/uMJeyUV36wWDR9ICmTW/c= +github.com/pingcap/dm v1.1.0-alpha.0.20200806100226-77bbd6b052b4/go.mod h1:d1f60ViWD81R6cl78GMGT2ZJksMrPfMS9yYB3mxYDjM= +github.com/pingcap/dumpling v0.0.0-20200605144140-0175843056a6/go.mod h1:LHCdb+QdDdRugY50HhbWtIYUG4qD1PIRqCB9JVYr9F4= +github.com/pingcap/errcode v0.0.0-20180921232412-a1a7271709d9/go.mod h1:4b2X8xSqxIroj/IZ9MX/VGZhAwc11wB9wRIzHvz6SeM= +github.com/pingcap/errcode v0.3.0/go.mod h1:4b2X8xSqxIroj/IZ9MX/VGZhAwc11wB9wRIzHvz6SeM= github.com/pingcap/errors v0.11.0 h1:DCJQB8jrHbQ1VVlMFIrbj2ApScNNotVmkSNplu2yUt4= github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pingcap/errors v0.11.5-0.20190809092503-95897b64e011/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pingcap/failpoint v0.0.0-20191029060244-12f4ac2fd11d/go.mod h1:DNS3Qg7bEDhU6EXNHF+XSv/PGznQaMJ5FWvctpm6pQI= +github.com/pingcap/failpoint v0.0.0-20200210140405-f8f9fb234798/go.mod h1:DNS3Qg7bEDhU6EXNHF+XSv/PGznQaMJ5FWvctpm6pQI= +github.com/pingcap/failpoint v0.0.0-20200506114213-c17f16071c53/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk= +github.com/pingcap/failpoint v0.0.0-20200603062251-b230c36c413c/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk= +github.com/pingcap/fn v0.0.0-20191016082858-07623b84a47d/go.mod h1:fMRU1BA1y+r89AxUoaAar4JjrhUkVDt0o0Np6V8XbDQ= +github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= +github.com/pingcap/kvproto v0.0.0-20190227013052-e71ca0165a5f/go.mod h1:QMdbTAXCHzzygQzqcG9uVUgU2fKeSN1GmfMiykdSzzY= +github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/kvproto v0.0.0-20191217072959-393e6c0fd4b7 h1:thLL2vFObG8vxBCkAmfAbLVBPfXUkBSXaVxppStCrL0= github.com/pingcap/kvproto v0.0.0-20191217072959-393e6c0fd4b7/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= +github.com/pingcap/kvproto v0.0.0-20200214064158-62d31900d88e/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200411081810-b85805c9476c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200417092353-efbe03bcffbd/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200420075417-e0c6e8842f22/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200423020121-038e31959c2a/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200424032552-6650270c39c3/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200428135407-0f5ffe459677/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200518112156-d4aeb467de29/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200608081027-d02a6f65e956/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200701055533-4ef28cac01f8/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20200706115936-1e0910aabe6c h1:VnLpCAxMAeDxc7HXTetwDQB+/MtDQjHAOBsd4QnGVwA= +github.com/pingcap/kvproto v0.0.0-20200706115936-1e0910aabe6c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= +github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= +github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= +github.com/pingcap/parser v0.0.0-20190506092653-e336082eb825/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/parser v0.0.0-20200424075042-8222d8b724a4/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= +github.com/pingcap/parser v0.0.0-20200507022230-f3bf29096657/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= +github.com/pingcap/parser v0.0.0-20200518090819-ec1e13b948b1/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= +github.com/pingcap/parser v0.0.0-20200522094936-3b720a0512a6/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= +github.com/pingcap/parser v0.0.0-20200609110328-c65941b9fbb3/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= +github.com/pingcap/parser v0.0.0-20200623082809-b74301ac298b/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= +github.com/pingcap/parser v0.0.0-20200717054943-cd445b0c607b/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= github.com/pingcap/pd v2.1.17+incompatible h1:mpfJYffRC14jeAfiq0jbHkqXVc8ZGNV0Lr2xG1sJslw= github.com/pingcap/pd v2.1.17+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= +github.com/pingcap/pd/v4 v4.0.0-rc.1.0.20200422143320-428acd53eba2/go.mod h1:s+utZtXDznOiL24VK0qGmtoHjjXNsscJx3m1n8cC56s= +github.com/pingcap/pd/v4 v4.0.0-rc.2.0.20200520083007-2c251bd8f181/go.mod h1:q4HTx/bA8aKBa4S7L+SQKHvjRPXCRV0tA0yRw0qkZSA= +github.com/pingcap/pd/v4 v4.0.0-rc.2.0.20200714122454-1a64f969cb3c/go.mod h1:v/dY4mVkt3dh/Liphhk0E4ScOkZpIk0m0GvWJ9FapDs= +github.com/pingcap/sysutil v0.0.0-20200206130906-2bfa6dc40bcd/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= +github.com/pingcap/sysutil v0.0.0-20200408114249-ed3bd6f7fdb1/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= +github.com/pingcap/sysutil v0.0.0-20200715082929-4c47bcac246a/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= +github.com/pingcap/tidb v1.1.0-beta.0.20200424154252-5ede18f10eed/go.mod h1:m2VDlJDbUeHPCXAfKPajqLmB1uLvWpkKk3zALNqDYdw= +github.com/pingcap/tidb v1.1.0-beta.0.20200509133407-a9dc72cf2558/go.mod h1:cXNbVSQAkwwmjFQmEnEPI00Z2/Y/KOhouttUPERiInE= +github.com/pingcap/tidb v1.1.0-beta.0.20200513065557-5a0787dfa915/go.mod h1:khS9Z9YlbtxsaZsSsSahelgh5L16EtP30QADFmPiI/I= +github.com/pingcap/tidb v1.1.0-beta.0.20200521154755-134e691d6f5f/go.mod h1:HobvT8ySGq9gkwPoyz/+V6TKWMRGEzFQobJOvLc2Oy8= +github.com/pingcap/tidb v1.1.0-beta.0.20200603101356-552e7709de0d/go.mod h1:wgu4vP3wq+x/l1X3ckOZFvyGKcVIBkq30NQVh0Y+qYA= +github.com/pingcap/tidb v1.1.0-beta.0.20200604055950-efc1c154d098/go.mod h1:UMxsNE326wyfgFJCx6aerPRLj1/tGPYDBKS9T9NOHI8= +github.com/pingcap/tidb v1.1.0-beta.0.20200610060912-f12cdc42010f/go.mod h1:jyXOvS9k0PTxYHju2OgySOe9FtydA52TiQ5bXAaKyQE= +github.com/pingcap/tidb v1.1.0-beta.0.20200721005019-f5c6e59f0daf/go.mod h1:dYCOFXJsoqBumpxAyBqCG3WZriIY7JgeBZHgvfARDa8= +github.com/pingcap/tidb v1.1.0-beta.0.20200728020902-472acf7b85b3/go.mod h1:533tLZJJQhCw7CuuYNJYMdd8aJxZXR+6TWMu3PJHIX4= github.com/pingcap/tidb v2.1.0-beta+incompatible h1:SQUmscnvvjHLjaIycQqtHujBahUnlKwTz6dQQhqgGSc= github.com/pingcap/tidb v2.1.0-beta+incompatible/go.mod h1:I8C6jrPINP2rrVunTRd7C9fRRhQrtR43S1/CL5ix/yQ= +github.com/pingcap/tidb-tools v4.0.0-beta.1.0.20200306084441-875bd09aa3d5+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v4.0.0-rc.1.0.20200421113014-507d2bb3a15e+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v4.0.0-rc.1.0.20200514040632-f76b3e428e19+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v4.0.0-rc.2.0.20200521050818-6dd445d83fe0+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v4.0.0+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v4.0.1+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v4.0.3-0.20200717061805-6483ba1f6311+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tipb v0.0.0-20190428032612-535e1abaa330/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= +github.com/pingcap/tipb v0.0.0-20200417094153-7316d94df1ee/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= +github.com/pingcap/tipb v0.0.0-20200604070248-508f03b0b342/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= +github.com/pingcap/tipb v0.0.0-20200615034523-dcfcea0b5965/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= +github.com/pingcap/tipb v0.0.0-20200618092958-4fad48b4c8c3/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -686,18 +990,38 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/ffjson v0.0.0-20180717144149-af8b230fcd20/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= +github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= 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.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +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.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +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/prometheus/prometheus v1.8.2 h1:PAL466mnJw1VolZPm1OarpdUpqukUy/eX4tagia17DM= github.com/prometheus/prometheus v1.8.2/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= +github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron v1.1.0 h1:jk4/Hud3TTdcrJgUOBgsqrZBarcxl6ADIjSC2iniwLY= github.com/robfig/cron v1.1.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -706,30 +1030,49 @@ github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYe github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.0.1-alpha.3/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v2.19.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v0.0.0-20191125035519-b054a8dfd10d/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= github.com/shurcooL/highlight_go v0.0.0-20170515013102-78fb10f4a5f8/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= github.com/shurcooL/octicon v0.0.0-20180602230221-c42b0e3b24d9/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= +github.com/siddontang/go-log v0.0.0-20180807004314-8d05993dda07/go.mod h1:yFdBgwXP24JziuRl2NMUahT7nGLNOKi1SIiFxMttVD4= +github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed/go.mod h1:yFdBgwXP24JziuRl2NMUahT7nGLNOKi1SIiFxMttVD4= +github.com/siddontang/go-mysql v0.0.0-20200222075837-12e89848f047/go.mod h1:+W4RCzesQDI11HvIkaDjS8yM36SpAnGNQ7jmTLn5BnU= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= @@ -739,6 +1082,8 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -748,6 +1093,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -756,9 +1102,12 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/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.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= 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= @@ -768,28 +1117,61 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 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 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E= +github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI= +github.com/swaggo/http-swagger v0.0.0-20200103000832-0e9263c4b516/go.mod h1:O1lAbCgAAX/KZ80LM/OXwtWFI/5TvZlwxSg8Cq08PV0= +github.com/swaggo/http-swagger v0.0.0-20200308142732-58ac5e232fba/go.mod h1:O1lAbCgAAX/KZ80LM/OXwtWFI/5TvZlwxSg8Cq08PV0= +github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y= +github.com/swaggo/swag v1.6.3/go.mod h1:wcc83tB4Mb2aNiL/HP4MFeQdpHUrca+Rp/DRNgWAUio= +github.com/swaggo/swag v1.6.5/go.mod h1:Y7ZLSS0d0DdxhWGVhQdu+Bu1QhaF5k0RD7FKdiAykeY= +github.com/swaggo/swag v1.6.6-0.20200323071853-8e21f4cefeea/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= +github.com/swaggo/swag v1.6.6-0.20200529100950-7c765ddd0476/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/goleveldb v0.0.0-20180815032940-ae2bd5eed72d/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/syndtr/goleveldb v1.0.1-0.20190625010220-02440ea7a285/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM= +github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2/go.mod h1:2PfKggNGDuadAa0LElHrByyrz4JPZ9fFx6Gs7nx7ZZU= +github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 h1:lYIiVDtZnyTWlNwiAxLj0bbpTcx1BWCFhXjfsvmPdNc= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.19.0+incompatible h1:pbwbYfHUoaase0oPQOdZ1GcaUjImYGimUXSQ/+8+Z8Q= github.com/uber/jaeger-client-go v2.19.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM= +github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA= github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= +github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg= +github.com/unrolled/render v1.0.1/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/negroni v0.3.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= @@ -803,6 +1185,15 @@ github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSf github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yisaer/crd-validation v0.0.3 h1:PmhrjDQbdkZOYz/1iVnK1UlY8q8Uw7hn1rlGm575sL8= github.com/yisaer/crd-validation v0.0.3/go.mod h1:aWBclg0rUEvCnOnRZGDF6oC9Ljni2s17G/YVdYuTTww= +github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zhangjinpeng1987/raft v0.0.0-20190624145930-deeb32d6553d/go.mod h1:1KDQ09J8MRHEtHze4at7BJZDW/doUAgkJ8w9KjEUhSo= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1 h1:Sq1fR+0c58RME5EoqKdjkiQAmPjmfHlZOoRI6fTUOcs= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -810,19 +1201,41 @@ go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU= +go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= +go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= gocloud.dev v0.18.0 h1:HX6uFZYZs9tUP87jzoWgB8dl4ihsRpiAsBDKTthiApY= gocloud.dev v0.18.0/go.mod h1:lhLOb91+9tKB8RnNlsx+weJGEd0AHM94huK1bmrhPwM= +golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -841,28 +1254,50 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w= +golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk= golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +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/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/image v0.0.0-20200119044424-58c23975cae1/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 h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 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-20200302205851-738671d3881b/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 h1:JgcxKXxCjrA2tyDP/aNU9K0Ck5Czfk6C7e2tMw7+bSI= 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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -889,21 +1324,31 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/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-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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= @@ -931,7 +1376,9 @@ golang.org/x/sys v0.0.0-20181026064943-731415f00dce/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181106135930-3a76605856fd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -944,19 +1391,40 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/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-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190620070143-6f217b454f45 h1:Dl2hc890lrizvUppGbRWhnIh2f8jOTCQpY5IKWRS0oM= golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/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-20191128015809-6d18c012aee9/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-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/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.20171227012246-e19ae1496984/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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= 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 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20170824195420-5d2fd3ccab98/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181006002542-f60d9635b16a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -980,15 +1448,42 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 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-20190422233926-fe54fb35175b/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-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/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-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-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191107010934-f79515f33823/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-20191114200427-caa0b0f7d508/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-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200325203130-f53864d0dba1/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= 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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= @@ -1001,6 +1496,13 @@ google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.6.1-0.20190607001116-5213b8090861 h1:ppLucX0K/60T3t6LPZQzTOkt5PytkEbQLIaSteq+TpE= google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= +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.15.1/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1008,6 +1510,7 @@ google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1019,30 +1522,52 @@ google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 h1:9VBRTdmgQxbs6HE0sUnMrSWNePppAJU07NYvX5dIB04= google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +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-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/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 h1:ADPHZzpzM4tk4V4S5cnCrr5SwzvlrPRmqqCuJDB8UTs= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/grpc v0.0.0-20180607172857-7a6a684ca69e/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/gometalinter.v2 v2.0.12/go.mod h1:NDRytsqEZyolNuAgTzJkZMkSQM7FIKyzVzGhjB/qfYo= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.0 h1:0HIbH907iBTAntm+88IJV2qmJALDAh8sPekI9Vc1fm0= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -1051,6 +1576,7 @@ gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= +gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= @@ -1062,6 +1588,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.1 h1:XM28wIgFzaBmeZ5dNHIpWLQpt/9DGKxk+rCg/22nnYE= gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170712054546-1be3d31502d6/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1069,6 +1596,10 @@ 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 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.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= @@ -1078,6 +1609,9 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh 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.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +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= k8s.io/api v0.0.0-20190918155943-95b840bb6a1f h1:8FRUST8oUkEI45WYKyD8ed7Ad0Kg5v11zHyPkEVb2xo= k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783 h1:V6ndwCPoao1yZ52agqOKaUAl7DYWVGiXjV7ePA2i610= @@ -1140,6 +1674,7 @@ modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-builder-alpha v0.0.0-20191113095113-4493943d2568 h1:3xmk5xge937C5x9PGatobpFlJG9hqI+sXS908bunuOQ= sigs.k8s.io/apiserver-builder-alpha v0.0.0-20191113095113-4493943d2568/go.mod h1:p0w5ou+8SCTGiaMD9cWxOWOn0Xl84wS8AQ3a7lCll7M= sigs.k8s.io/apiserver-builder-alpha/cmd v0.0.0-20191113095113-4493943d2568 h1:+m4eqp4ZKgZmcp9dn6le1u3HMxjUig3kflg3gUZbbK8= @@ -1157,4 +1692,7 @@ sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20180531100431-4c381bd170b4/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go new file mode 100644 index 0000000000..7b8ec54993 --- /dev/null +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -0,0 +1,25 @@ +// Copyright 2018 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +func (dc *DMCluster) Scheme() string { + if dc.IsTLSClusterEnabled() { + return "https" + } + return "http" +} + +func (dc *DMCluster) IsTLSClusterEnabled() bool { + return dc.Spec.TLSCluster != nil && dc.Spec.TLSCluster.Enabled +} diff --git a/pkg/discovery/discovery.go b/pkg/discovery/discovery.go index 5de6c307bd..034cfbb45d 100644 --- a/pkg/discovery/discovery.go +++ b/pkg/discovery/discovery.go @@ -20,6 +20,7 @@ import ( "sync" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" + "github.com/pingcap/tidb-operator/pkg/dmapi" "github.com/pingcap/tidb-operator/pkg/pdapi" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -29,13 +30,16 @@ import ( // TiDBDiscovery helps new PD member to discover all other members in cluster bootstrap phase. type TiDBDiscovery interface { Discover(string) (string, error) + DiscoverDM(string) (string, error) } type tidbDiscovery struct { - cli versioned.Interface - lock sync.Mutex - clusters map[string]*clusterInfo - pdControl pdapi.PDControlInterface + cli versioned.Interface + lock sync.Mutex + clusters map[string]*clusterInfo + dmClusters map[string]*clusterInfo + pdControl pdapi.PDControlInterface + masterControl dmapi.MasterControlInterface } type clusterInfo struct { @@ -44,11 +48,12 @@ type clusterInfo struct { } // NewTiDBDiscovery returns a TiDBDiscovery -func NewTiDBDiscovery(pdControl pdapi.PDControlInterface, cli versioned.Interface, kubeCli kubernetes.Interface) TiDBDiscovery { +func NewTiDBDiscovery(pdControl pdapi.PDControlInterface, masterControl dmapi.MasterControlInterface, cli versioned.Interface, kubeCli kubernetes.Interface) TiDBDiscovery { return &tidbDiscovery{ - cli: cli, - pdControl: pdControl, - clusters: map[string]*clusterInfo{}, + cli: cli, + pdControl: pdControl, + masterControl: masterControl, + clusters: map[string]*clusterInfo{}, } } @@ -108,3 +113,59 @@ func (td *tidbDiscovery) Discover(advertisePeerUrl string) (string, error) { delete(currentCluster.peers, podName) return fmt.Sprintf("--join=%s", strings.Join(membersArr, ",")), nil } + +func (td *tidbDiscovery) DiscoverDM(advertisePeerUrl string) (string, error) { + td.lock.Lock() + defer td.lock.Unlock() + + if advertisePeerUrl == "" { + return "", fmt.Errorf("dm advertisePeerUrl is empty") + } + klog.Infof("dm advertisePeerUrl is: %s", advertisePeerUrl) + strArr := strings.Split(advertisePeerUrl, ".") + if len(strArr) != 4 { + return "", fmt.Errorf("dm advertisePeerUrl format is wrong: %s", advertisePeerUrl) + } + + podName, peerServiceName, ns := strArr[0], strArr[1], strArr[2] + dcName := strings.TrimSuffix(peerServiceName, "-master-peer") + podNamespace := os.Getenv("MY_POD_NAMESPACE") + if ns != podNamespace { + return "", fmt.Errorf("dm the peer's namespace: %s is not equal to discovery namespace: %s", ns, podNamespace) + } + dc, err := td.cli.PingcapV1alpha1().DMClusters(ns).Get(dcName, metav1.GetOptions{}) + if err != nil { + return "", err + } + keyName := fmt.Sprintf("%s/%s", ns, dcName) + // TODO: the replicas should be the total replicas of pd sets. + replicas := dc.Spec.Master.Replicas + + currentCluster := td.dmClusters[keyName] + if currentCluster == nil || currentCluster.resourceVersion != dc.ResourceVersion { + td.clusters[keyName] = &clusterInfo{ + resourceVersion: dc.ResourceVersion, + peers: map[string]struct{}{}, + } + } + currentCluster = td.dmClusters[keyName] + currentCluster.peers[podName] = struct{}{} + + if len(currentCluster.peers) == int(replicas) { + delete(currentCluster.peers, podName) + return fmt.Sprintf("--initial-cluster=%s=%s://%s", podName, dc.Scheme(), advertisePeerUrl), nil + } + + masterClient := td.masterControl.GetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), dc.IsTLSClusterEnabled()) + membersInfo, err := masterClient.GetMasters() + if err != nil { + return "", err + } + + membersArr := make([]string, 0) + for _, member := range membersInfo.Masters { + membersArr = append(membersArr, member.ClientURLs[0]) + } + delete(currentCluster.peers, podName) + return fmt.Sprintf("--join=%s", strings.Join(membersArr, ",")), nil +} diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go index fd018ca9a9..6652176f8d 100644 --- a/pkg/discovery/discovery_test.go +++ b/pkg/discovery/discovery_test.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/kvproto/pkg/pdpb" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned/fake" + "github.com/pingcap/tidb-operator/pkg/dmapi" "github.com/pingcap/tidb-operator/pkg/pdapi" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +46,7 @@ func TestDiscoveryDiscovery(t *testing.T) { cli := fake.NewSimpleClientset() kubeCli := kubefake.NewSimpleClientset() fakePDControl := pdapi.NewFakePDControl(kubeCli) + fakeMasterControl := dmapi.NewFakeMasterControl(kubeCli) pdClient := pdapi.NewFakePDClient() if test.tc != nil { cli.PingcapV1alpha1().TidbClusters(test.tc.Namespace).Create(test.tc) @@ -54,7 +56,7 @@ func TestDiscoveryDiscovery(t *testing.T) { return test.getMembersFn() }) - td := NewTiDBDiscovery(fakePDControl, cli, kubeCli) + td := NewTiDBDiscovery(fakePDControl, fakeMasterControl, cli, kubeCli) td.(*tidbDiscovery).clusters = test.clusters os.Setenv("MY_POD_NAMESPACE", test.ns) @@ -397,6 +399,375 @@ func TestDiscoveryDiscovery(t *testing.T) { } } +func TestDiscoveryDMDiscovery(t *testing.T) { + g := NewGomegaWithT(t) + + type testcase struct { + name string + ns string + url string + dmClusters map[string]*clusterInfo + dc *v1alpha1.DMCluster + getMastersFn func() (*dmapi.MembersInfo, error) + expectFn func(*GomegaWithT, *tidbDiscovery, string, error) + } + testFn := func(test testcase, t *testing.T) { + cli := fake.NewSimpleClientset() + kubeCli := kubefake.NewSimpleClientset() + fakePDControl := pdapi.NewFakePDControl(kubeCli) + fakeMasterControl := dmapi.NewFakeMasterControl(kubeCli) + masterClient := dmapi.NewFakeMasterClient() + if test.dc != nil { + cli.PingcapV1alpha1().DMClusters(test.dc.Namespace).Create(test.dc) + fakeMasterControl.SetMasterClient(dmapi.Namespace(test.dc.GetNamespace()), test.dc.GetName(), masterClient) + } + masterClient.AddReaction(dmapi.GetMastersActionType, func(action *dmapi.Action) (interface{}, error) { + return test.getMastersFn() + }) + + td := NewTiDBDiscovery(fakePDControl, fakeMasterControl, cli, kubeCli) + td.(*tidbDiscovery).dmClusters = test.dmClusters + + os.Setenv("MY_POD_NAMESPACE", test.ns) + re, err := td.Discover(test.url) + test.expectFn(g, td.(*tidbDiscovery), re, err) + } + tests := []testcase{ + { + name: "advertisePeerUrl is empty", + ns: "default", + url: "", + dmClusters: map[string]*clusterInfo{}, + dc: newDC(), + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "advertisePeerUrl is empty")).To(BeTrue()) + g.Expect(len(td.clusters)).To(BeZero()) + }, + }, + { + name: "advertisePeerUrl is wrong", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default:2380", + dmClusters: map[string]*clusterInfo{}, + dc: newTC(), + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "advertisePeerUrl format is wrong: ")).To(BeTrue()) + g.Expect(len(td.clusters)).To(BeZero()) + }, + }, + { + name: "namespace is wrong", + ns: "default1", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dmClusters: map[string]*clusterInfo{}, + dc: newTC(), + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "is not equal to discovery namespace:")).To(BeTrue()) + g.Expect(len(td.clusters)).To(BeZero()) + }, + }, + { + name: "failed to get tidbcluster", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dmClusters: map[string]*clusterInfo{}, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(apierrors.IsNotFound(err)).To(BeTrue()) + g.Expect(len(td.clusters)).To(BeZero()) + }, + }, + { + name: "failed to get members", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dmClusters: map[string]*clusterInfo{}, + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return nil, fmt.Errorf("get members failed") + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "get members failed")).To(BeTrue()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-0"]).To(Equal(struct{}{})) + }, + }, + { + name: "resourceVersion changed", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return nil, fmt.Errorf("getMembers failed") + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "2", + peers: map[string]struct{}{ + "demo-pd-0": {}, + "demo-pd-1": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "getMembers failed")).To(BeTrue()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-0"]).To(Equal(struct{}{})) + }, + }, + { + name: "1 cluster, first ordinal, there are no pd members", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dmClusters: map[string]*clusterInfo{}, + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return nil, fmt.Errorf("there are no pd members") + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "there are no pd members")).To(BeTrue()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-0"]).To(Equal(struct{}{})) + }, + }, + { + name: "1 cluster, second ordinal, there are no pd members", + ns: "default", + url: "demo-pd-1.demo-pd-peer.default.svc:2380", + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return nil, fmt.Errorf("there are no pd members 2") + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{ + "demo-pd-0": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "there are no pd members 2")).To(BeTrue()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(2)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-0"]).To(Equal(struct{}{})) + g.Expect(td.clusters["default/demo"].peers["demo-pd-1"]).To(Equal(struct{}{})) + }, + }, + { + name: "1 cluster, third ordinal, return the initial-cluster args", + ns: "default", + url: "demo-pd-2.demo-pd-peer.default.svc:2380", + dc: newTC(), + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{ + "demo-pd-0": {}, + "demo-pd-1": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(2)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-0"]).To(Equal(struct{}{})) + g.Expect(td.clusters["default/demo"].peers["demo-pd-1"]).To(Equal(struct{}{})) + g.Expect(s).To(Equal("--initial-cluster=demo-pd-2=http://demo-pd-2.demo-pd-peer.default.svc:2380")) + }, + }, + { + name: "1 cluster, the first ordinal second request, get members failed", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return nil, fmt.Errorf("there are no pd members 3") + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{ + "demo-pd-0": {}, + "demo-pd-1": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).To(HaveOccurred()) + g.Expect(strings.Contains(err.Error(), "there are no pd members 3")).To(BeTrue()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(2)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-0"]).To(Equal(struct{}{})) + g.Expect(td.clusters["default/demo"].peers["demo-pd-1"]).To(Equal(struct{}{})) + }, + }, + { + name: "1 cluster, the first ordinal third request, get members success", + ns: "default", + url: "demo-pd-0.demo-pd-peer.default.svc:2380", + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return &pdapi.MembersInfo{ + Members: []*pdpb.Member{ + { + PeerUrls: []string{"demo-pd-2.demo-pd-peer.default.svc:2380"}, + }, + }, + }, nil + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{ + "demo-pd-0": {}, + "demo-pd-1": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.clusters["default/demo"].peers["demo-pd-1"]).To(Equal(struct{}{})) + g.Expect(s).To(Equal("--join=demo-pd-2.demo-pd-peer.default.svc:2379")) + }, + }, + { + name: "1 cluster, the second ordinal second request, get members success", + ns: "default", + url: "demo-pd-1.demo-pd-peer.default.svc:2380", + dc: newTC(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return &pdapi.MembersInfo{ + Members: []*pdpb.Member{ + { + PeerUrls: []string{"demo-pd-0.demo-pd-peer.default.svc:2380"}, + }, + { + PeerUrls: []string{"demo-pd-2.demo-pd-peer.default.svc:2380"}, + }, + }, + }, nil + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{ + "demo-pd-1": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(0)) + g.Expect(s).To(Equal("--join=demo-pd-0.demo-pd-peer.default.svc:2379,demo-pd-2.demo-pd-peer.default.svc:2379")) + }, + }, + { + name: "1 cluster, the fourth ordinal request, get members success", + ns: "default", + url: "demo-pd-3.demo-pd-peer.default.svc:2380", + dc: func() *v1alpha1.TidbCluster { + tc := newTC() + tc.Spec.PD.Replicas = 5 + return tc + }(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return &pdapi.MembersInfo{ + Members: []*pdpb.Member{ + { + PeerUrls: []string{"demo-pd-0.demo-pd-peer.default.svc:2380"}, + }, + { + PeerUrls: []string{"demo-pd-1.demo-pd-peer.default.svc:2380"}, + }, + { + PeerUrls: []string{"demo-pd-2.demo-pd-peer.default.svc:2380"}, + }, + }, + }, nil + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{}, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(len(td.clusters)).To(Equal(1)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(0)) + g.Expect(s).To(Equal("--join=demo-pd-0.demo-pd-peer.default.svc:2379,demo-pd-1.demo-pd-peer.default.svc:2379,demo-pd-2.demo-pd-peer.default.svc:2379")) + }, + }, + { + name: "2 clusters, the five ordinal request, get members success", + ns: "default", + url: "demo-pd-3.demo-pd-peer.default.svc:2380", + dc: func() *v1alpha1.TidbCluster { + tc := newTC() + tc.Spec.PD.Replicas = 5 + return tc + }(), + getMastersFn: func() (*pdapi.MembersInfo, error) { + return &pdapi.MembersInfo{ + Members: []*pdpb.Member{ + { + PeerUrls: []string{"demo-pd-0.demo-pd-peer.default.svc:2380"}, + }, + { + PeerUrls: []string{"demo-pd-1.demo-pd-peer.default.svc:2380"}, + }, + { + PeerUrls: []string{"demo-pd-2.demo-pd-peer.default.svc:2380"}, + }, + { + PeerUrls: []string{"demo-pd-3.demo-pd-peer.default.svc:2380"}, + }, + }, + }, nil + }, + dmClusters: map[string]*clusterInfo{ + "default/demo": { + resourceVersion: "1", + peers: map[string]struct{}{}, + }, + "default/demo-1": { + peers: map[string]struct{}{ + "demo-1-pd-0": {}, + "demo-1-pd-1": {}, + "demo-1-pd-2": {}, + }, + }, + }, + expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(len(td.clusters)).To(Equal(2)) + g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(0)) + g.Expect(len(td.clusters["default/demo-1"].peers)).To(Equal(3)) + g.Expect(s).To(Equal("--join=demo-pd-0.demo-pd-peer.default.svc:2379,demo-pd-1.demo-pd-peer.default.svc:2379,demo-pd-2.demo-pd-peer.default.svc:2379,demo-pd-3.demo-pd-peer.default.svc:2379")) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testFn(tt, t) + }) + } +} + func newTC() *v1alpha1.TidbCluster { return &v1alpha1.TidbCluster{ TypeMeta: metav1.TypeMeta{Kind: "TidbCluster", APIVersion: "v1alpha1"}, @@ -410,3 +781,17 @@ func newTC() *v1alpha1.TidbCluster { }, } } + +func newDC() *v1alpha1.DMCluster { + return &v1alpha1.DMCluster{ + TypeMeta: metav1.TypeMeta{Kind: "DmCluster", APIVersion: "v1alpha1"}, + ObjectMeta: metav1.ObjectMeta{ + Name: "demo", + Namespace: metav1.NamespaceDefault, + ResourceVersion: "1", + }, + Spec: v1alpha1.DMClusterSpec{ + Master: &v1alpha1.MasterSpec{Replicas: 3}, + }, + } +} diff --git a/pkg/discovery/server/server.go b/pkg/discovery/server/server.go index 696f12b6b3..f270ff86b9 100644 --- a/pkg/discovery/server/server.go +++ b/pkg/discovery/server/server.go @@ -18,6 +18,8 @@ import ( "io" "net/http" + "github.com/pingcap/tidb-operator/pkg/dmapi" + restful "github.com/emicklei/go-restful" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" "github.com/pingcap/tidb-operator/pkg/discovery" @@ -32,9 +34,9 @@ type server struct { } // NewServer creates a new server. -func NewServer(pdControl pdapi.PDControlInterface, cli versioned.Interface, kubeCli kubernetes.Interface) Server { +func NewServer(pdControl pdapi.PDControlInterface, masterControl dmapi.MasterControlInterface, cli versioned.Interface, kubeCli kubernetes.Interface) Server { s := &server{ - discovery: discovery.NewTiDBDiscovery(pdControl, cli, kubeCli), + discovery: discovery.NewTiDBDiscovery(pdControl, masterControl, cli, kubeCli), container: restful.NewContainer(), } s.registerHandlers() @@ -44,6 +46,7 @@ func NewServer(pdControl pdapi.PDControlInterface, cli versioned.Interface, kube func (s *server) registerHandlers() { ws := new(restful.WebService) ws.Route(ws.GET("/new/{advertise-peer-url}").To(s.newHandler)) + ws.Route(ws.GET("/newdm/{advertise-peer-url}").To(s.newHandler)) s.container.Add(ws) } @@ -77,3 +80,30 @@ func (s *server) newHandler(req *restful.Request, resp *restful.Response) { klog.Errorf("failed to writeString: %s, %v", result, err) } } + +func (s *server) newDMHandler(req *restful.Request, resp *restful.Response) { + encodedAdvertisePeerURL := req.PathParameter("advertise-peer-url") + data, err := base64.StdEncoding.DecodeString(encodedAdvertisePeerURL) + if err != nil { + klog.Errorf("failed to decode dm advertise-peer-url: %s", encodedAdvertisePeerURL) + if err := resp.WriteError(http.StatusInternalServerError, err); err != nil { + klog.Errorf("failed to writeError: %v", err) + } + return + } + advertisePeerURL := string(data) + + result, err := s.discovery.DiscoverDM(advertisePeerURL) + if err != nil { + klog.Errorf("failed to discover DM: %s, %v", advertisePeerURL, err) + if err := resp.WriteError(http.StatusInternalServerError, err); err != nil { + klog.Errorf("failed to writeError for dm: %v", err) + } + return + } + + klog.Infof("generated args for dm %s: %s", advertisePeerURL, result) + if _, err := io.WriteString(resp, result); err != nil { + klog.Errorf("failed to writeString for dm: %s, %v", result, err) + } +} diff --git a/pkg/discovery/server/server_test.go b/pkg/discovery/server/server_test.go index 860392ebf4..323574d757 100644 --- a/pkg/discovery/server/server_test.go +++ b/pkg/discovery/server/server_test.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/kvproto/pkg/pdpb" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned/fake" + "github.com/pingcap/tidb-operator/pkg/dmapi" "github.com/pingcap/tidb-operator/pkg/pdapi" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubefake "k8s.io/client-go/kubernetes/fake" @@ -53,8 +54,9 @@ func TestServer(t *testing.T) { cli := fake.NewSimpleClientset() kubeCli := kubefake.NewSimpleClientset() fakePDControl := pdapi.NewFakePDControl(kubeCli) + faleMasterControl := dmapi.NewFakeMasterControl(kubeCli) pdClient := pdapi.NewFakePDClient() - s := NewServer(fakePDControl, cli, kubeCli) + s := NewServer(fakePDControl, faleMasterControl, cli, kubeCli) httpServer := httptest.NewServer(s.(*server).container.ServeMux) defer httpServer.Close() diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go new file mode 100644 index 0000000000..8e0658b4b7 --- /dev/null +++ b/pkg/dmapi/dmapi.go @@ -0,0 +1,106 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmapi + +import ( + "crypto/tls" + "fmt" + "net/http" + "strings" + "time" + + "github.com/gogo/protobuf/jsonpb" + dmpb "github.com/pingcap/dm/dm/pb" + httputil "github.com/pingcap/tidb-operator/pkg/util/http" +) + +const ( + DefaultTimeout = 5 * time.Second +) + +// MasterClient provides master server's api +type MasterClient interface { + // GetMasters returns all master members from cluster + GetMembers(string) (*MembersInfo, error) + // GetMasters returns all master members from cluster + GetMasters() (*MembersInfo, error) +} + +var ( + membersPrefix = "apis/v1alpha1/members" +) + +// MembersInfo is master members info returned from dm-master RESTful interface +//type Members map[string][]*pdpb.Member +type MembersInfo struct { + Masters []*dmpb.MasterInfo + Workers []*dmpb.WorkerInfo + Leader *dmpb.ListLeaderMember +} + +// masterClient is default implementation of MasterClient +type masterClient struct { + url string + httpClient *http.Client +} + +func (mc *masterClient) GetMembers(apiURL string) (*MembersInfo, error) { + body, err := httputil.GetBodyOK(mc.httpClient, apiURL) + if err != nil { + return nil, err + } + listMemberResp := &dmpb.ListMemberResponse{} + err = jsonpb.Unmarshal(strings.NewReader(string(body)), listMemberResp) + if err != nil { + return nil, err + } + if !listMemberResp.Result { + return nil, fmt.Errorf("unable to list members info from dm-master, err: %s", listMemberResp.Msg) + } + membersInfo := &MembersInfo{ + Masters: make([]*dmpb.MasterInfo, 0), + Workers: make([]*dmpb.WorkerInfo, 0), + } + for _, member := range listMemberResp.GetMembers() { + if leader := member.GetLeader(); leader != nil { + membersInfo.Leader = leader + } else if masters := member.GetMaster(); masters != nil { + membersInfo.Masters = append(membersInfo.Masters, masters.Masters...) + } else if workers := member.GetWorker(); workers != nil { + membersInfo.Workers = append(membersInfo.Workers, workers.Workers...) + } + } + return membersInfo, nil +} + +func (mc *masterClient) GetMasters() (*MembersInfo, error) { + query := "?leader=true&master=true" + apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) + return mc.GetMembers(apiURL) +} + +// NewMasterClient returns a new MasterClient +func NewMasterClient(url string, timeout time.Duration, tlsConfig *tls.Config) MasterClient { + var disableKeepalive bool + if tlsConfig != nil { + disableKeepalive = true + } + return &masterClient{ + url: url, + httpClient: &http.Client{ + Timeout: timeout, + Transport: &http.Transport{TLSClientConfig: tlsConfig, DisableKeepAlives: disableKeepalive}, + }, + } +} diff --git a/pkg/dmapi/fake_dmapi.go b/pkg/dmapi/fake_dmapi.go new file mode 100644 index 0000000000..6478866773 --- /dev/null +++ b/pkg/dmapi/fake_dmapi.go @@ -0,0 +1,84 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmapi + +import ( + "fmt" +) + +type ActionType string + +const ( + GetMembersActionType ActionType = "GetMembers" + GetMastersActionType ActionType = "GetMasters" +) + +type NotFoundReaction struct { + actionType ActionType +} + +func (nfr *NotFoundReaction) Error() string { + return fmt.Sprintf("not found %s reaction. Please add the reaction", nfr.actionType) +} + +type Action struct { + ID uint64 + Name string + Labels map[string]string +} + +type Reaction func(action *Action) (interface{}, error) + +// FakeMasterClient implements a fake version of PDClient. +type FakeMasterClient struct { + reactions map[ActionType]Reaction +} + +func NewFakeMasterClient() *FakeMasterClient { + return &FakeMasterClient{reactions: map[ActionType]Reaction{}} +} + +func (pc *FakeMasterClient) AddReaction(actionType ActionType, reaction Reaction) { + pc.reactions[actionType] = reaction +} + +// fakeAPI is a small helper for fake API calls +func (pc *FakeMasterClient) fakeAPI(actionType ActionType, action *Action) (interface{}, error) { + if reaction, ok := pc.reactions[actionType]; ok { + result, err := reaction(action) + if err != nil { + return nil, err + } + return result, nil + } + return nil, &NotFoundReaction{actionType} +} + +func (pc *FakeMasterClient) GetMembers(_ string) (*MembersInfo, error) { + action := &Action{} + result, err := pc.fakeAPI(GetMembersActionType, action) + if err != nil { + return nil, err + } + return result.(*MembersInfo), nil +} + +func (pc *FakeMasterClient) GetMasters() (*MembersInfo, error) { + action := &Action{} + result, err := pc.fakeAPI(GetMastersActionType, action) + if err != nil { + return nil, err + } + return result.(*MembersInfo), nil +} diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go new file mode 100644 index 0000000000..15fbd7558c --- /dev/null +++ b/pkg/dmapi/master_control.go @@ -0,0 +1,101 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmapi + +import ( + "crypto/tls" + "fmt" + "net/http" + "sync" + + "github.com/pingcap/tidb-operator/pkg/pdapi" + + "github.com/pingcap/tidb-operator/pkg/util" + "k8s.io/klog" + + "k8s.io/client-go/kubernetes" +) + +// Namespace is a newtype of a string +type Namespace pdapi.Namespace + +// MasterControlInterface is an interface that knows how to manage and get dm cluster's master client +type MasterControlInterface interface { + // GetMasterClient provides MasterClient of the dm cluster. + GetMasterClient(namespace Namespace, tcName string, tlsEnabled bool) MasterClient +} + +// defaultMasterControl is the default implementation of MasterControlInterface. +type defaultMasterControl struct { + mutex sync.Mutex + kubeCli kubernetes.Interface + masterClients map[string]MasterClient +} + +// NewDefaultMasterControl returns a defaultMasterControl instance +func NewDefaultMasterControl(kubeCli kubernetes.Interface) MasterControlInterface { + return &defaultMasterControl{kubeCli: kubeCli, masterClients: map[string]MasterClient{}} +} + +// GetPDClient provides a PDClient of real pd cluster,if the PDClient not existing, it will create new one. +func (mc *defaultMasterControl) GetMasterClient(namespace Namespace, dcName string, tlsEnabled bool) MasterClient { + mc.mutex.Lock() + defer mc.mutex.Unlock() + + var tlsConfig *tls.Config + var err error + var scheme = "http" + + if tlsEnabled { + scheme = "https" + tlsConfig, err = pdapi.GetTLSConfig(mc.kubeCli, pdapi.Namespace(namespace), dcName, util.ClusterClientTLSSecretName(dcName)) + if err != nil { + klog.Errorf("Unable to get tls config for dm cluster %q, master client may not work: %v", dcName, err) + return &masterClient{url: MasterClientURL(namespace, dcName, scheme), httpClient: &http.Client{Timeout: DefaultTimeout}} + } + + return NewMasterClient(MasterClientURL(namespace, dcName, scheme), DefaultTimeout, tlsConfig) + } + + key := masterClientKey(scheme, namespace, dcName) + if _, ok := mc.masterClients[key]; !ok { + mc.masterClients[key] = NewMasterClient(MasterClientURL(namespace, dcName, scheme), DefaultTimeout, nil) + } + return mc.masterClients[key] +} + +// masterClientKey returns the master client key +func masterClientKey(scheme string, namespace Namespace, clusterName string) string { + return fmt.Sprintf("%s.%s.%s", scheme, clusterName, string(namespace)) +} + +// MasterClientURL builds the url of master client +func MasterClientURL(namespace Namespace, clusterName string, scheme string) string { + return fmt.Sprintf("%s://%s-master.%s:2379", scheme, clusterName, string(namespace)) +} + +// FakeMasterControl implements a fake version of MasterControlInterface. +type FakeMasterControl struct { + defaultMasterControl +} + +func NewFakeMasterControl(kubeCli kubernetes.Interface) *FakeMasterControl { + return &FakeMasterControl{ + defaultMasterControl{kubeCli: kubeCli, masterClients: map[string]MasterClient{}}, + } +} + +func (fmc *FakeMasterControl) SetMasterClient(namespace Namespace, tcName string, masterClient MasterClient) { + fmc.defaultMasterControl.masterClients[masterClientKey("http", namespace, tcName)] = masterClient +} From ba0f5185488990a428b79322c25b0f5d4cf2f8a5 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 12 Aug 2020 13:01:22 +0800 Subject: [PATCH 09/37] remove dm package --- cmd/discovery/main.go | 3 +- pkg/discovery/discovery_test.go | 89 +++++++++++++++------------------ pkg/dmapi/dmapi.go | 69 +++++++++++++------------ pkg/dmapi/fake_dmapi.go | 14 +----- 4 files changed, 79 insertions(+), 96 deletions(-) diff --git a/cmd/discovery/main.go b/cmd/discovery/main.go index 97d15dc524..381ce40dd9 100644 --- a/cmd/discovery/main.go +++ b/cmd/discovery/main.go @@ -22,10 +22,9 @@ import ( "strconv" "time" - "github.com/pingcap/tidb-operator/pkg/dmapi" - "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" "github.com/pingcap/tidb-operator/pkg/discovery/server" + "github.com/pingcap/tidb-operator/pkg/dmapi" "github.com/pingcap/tidb-operator/pkg/pdapi" "github.com/pingcap/tidb-operator/pkg/version" "k8s.io/apimachinery/pkg/util/wait" diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go index 3986227d69..d6ce98784e 100644 --- a/pkg/discovery/discovery_test.go +++ b/pkg/discovery/discovery_test.go @@ -20,7 +20,6 @@ import ( "testing" . "github.com/onsi/gomega" - dmpb "github.com/pingcap/dm/dm/pb" "github.com/pingcap/kvproto/pkg/pdpb" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned/fake" @@ -409,7 +408,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { url string dmClusters map[string]*clusterInfo dc *v1alpha1.DMCluster - getMastersFn func() (*dmapi.MembersInfo, error) + getMastersFn func() ([]*dmapi.MastersInfo, error) expectFn func(*GomegaWithT, *tidbDiscovery, string, error) } testFn := func(test testcase, t *testing.T) { @@ -486,7 +485,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", dmClusters: map[string]*clusterInfo{}, dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { + getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("get members failed") }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { @@ -502,7 +501,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { ns: "default", url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { + getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("getMembers failed") }, dmClusters: map[string]*clusterInfo{ @@ -528,7 +527,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", dmClusters: map[string]*clusterInfo{}, dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { + getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("there are no dm-master members") }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { @@ -544,7 +543,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { ns: "default", url: "demo-dm-master-1.demo-dm-master-peer.default.svc:2380", dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { + getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("there are no dm-master members 2") }, dmClusters: map[string]*clusterInfo{ @@ -592,7 +591,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { ns: "default", url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { + getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("there are no dm-master members 3") }, dmClusters: map[string]*clusterInfo{ @@ -618,12 +617,10 @@ func TestDiscoveryDMDiscovery(t *testing.T) { ns: "default", url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { - return &dmapi.MembersInfo{ - Masters: []*dmpb.MasterInfo{ - { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, - }, + getMastersFn: func() ([]*dmapi.MastersInfo, error) { + return []*dmapi.MastersInfo{ + { + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, }, }, nil }, @@ -649,15 +646,13 @@ func TestDiscoveryDMDiscovery(t *testing.T) { ns: "default", url: "demo-dm-master-1.demo-dm-master-peer.default.svc:2380", dc: newDC(), - getMastersFn: func() (*dmapi.MembersInfo, error) { - return &dmapi.MembersInfo{ - Masters: []*dmpb.MasterInfo{ - { - PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, - }, - { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, - }, + getMastersFn: func() ([]*dmapi.MastersInfo, error) { + return []*dmapi.MastersInfo{ + { + PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, + }, + { + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, }, }, nil }, @@ -685,18 +680,16 @@ func TestDiscoveryDMDiscovery(t *testing.T) { dc.Spec.Master.Replicas = 5 return dc }(), - getMastersFn: func() (*dmapi.MembersInfo, error) { - return &dmapi.MembersInfo{ - Masters: []*dmpb.MasterInfo{ - { - PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, - }, - { - PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:2380"}, - }, - { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, - }, + getMastersFn: func() ([]*dmapi.MastersInfo, error) { + return []*dmapi.MastersInfo{ + { + PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, + }, + { + PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:2380"}, + }, + { + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, }, }, nil }, @@ -722,21 +715,19 @@ func TestDiscoveryDMDiscovery(t *testing.T) { dc.Spec.Master.Replicas = 5 return dc }(), - getMastersFn: func() (*dmapi.MembersInfo, error) { - return &dmapi.MembersInfo{ - Masters: []*dmpb.MasterInfo{ - { - PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, - }, - { - PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:2380"}, - }, - { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, - }, - { - PeerURLs: []string{"demo-dm-master-3.demo-dm-master-peer.default.svc:2380"}, - }, + getMastersFn: func() ([]*dmapi.MastersInfo, error) { + return []*dmapi.MastersInfo{ + { + PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, + }, + { + PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:2380"}, + }, + { + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, + }, + { + PeerURLs: []string{"demo-dm-master-3.demo-dm-master-peer.default.svc:2380"}, }, }, nil }, diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index 8e0658b4b7..19abdf8d79 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -15,13 +15,11 @@ package dmapi import ( "crypto/tls" + "encoding/json" "fmt" "net/http" - "strings" "time" - "github.com/gogo/protobuf/jsonpb" - dmpb "github.com/pingcap/dm/dm/pb" httputil "github.com/pingcap/tidb-operator/pkg/util/http" ) @@ -32,21 +30,39 @@ const ( // MasterClient provides master server's api type MasterClient interface { // GetMasters returns all master members from cluster - GetMembers(string) (*MembersInfo, error) - // GetMasters returns all master members from cluster - GetMasters() (*MembersInfo, error) + GetMasters() ([]*MastersInfo, error) } var ( membersPrefix = "apis/v1alpha1/members" ) -// MembersInfo is master members info returned from dm-master RESTful interface -//type Members map[string][]*pdpb.Member -type MembersInfo struct { - Masters []*dmpb.MasterInfo - Workers []*dmpb.WorkerInfo - Leader *dmpb.ListLeaderMember +type ListMemberRespHeader struct { + Result bool `json:"result,omitempty"` + Msg string `json:"msg,omitempty"` +} + +type MastersInfo struct { + Name string `json:"name,omitempty"` + MemberID uint64 `json:"memberID,omitempty"` + Alive bool `json:"alive,omitempty"` + PeerURLs []string `json:"peerURLs,omitempty"` + ClientURLs []string `json:"clientURLs,omitempty"` +} + +type MembersMaster struct { + Msg string `json:"msg,omitempty"` + Masters []*MastersInfo `json:"masters,omitempty"` +} + +type ListMemberMaster struct { + MembersMaster `json:"master,omitempty"` +} + +type MastersResp struct { + ListMemberRespHeader `json:",inline"` + + ListMemberResp []*ListMemberMaster `json:"members,omitempty"` } // masterClient is default implementation of MasterClient @@ -55,39 +71,26 @@ type masterClient struct { httpClient *http.Client } -func (mc *masterClient) GetMembers(apiURL string) (*MembersInfo, error) { +func (mc *masterClient) GetMasters() ([]*MastersInfo, error) { + query := "?master=true" + apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) body, err := httputil.GetBodyOK(mc.httpClient, apiURL) if err != nil { return nil, err } - listMemberResp := &dmpb.ListMemberResponse{} - err = jsonpb.Unmarshal(strings.NewReader(string(body)), listMemberResp) + listMemberResp := &MastersResp{} + err = json.Unmarshal(body, listMemberResp) if err != nil { return nil, err } if !listMemberResp.Result { return nil, fmt.Errorf("unable to list members info from dm-master, err: %s", listMemberResp.Msg) } - membersInfo := &MembersInfo{ - Masters: make([]*dmpb.MasterInfo, 0), - Workers: make([]*dmpb.WorkerInfo, 0), + if len(listMemberResp.ListMemberResp) != 1 { + return nil, fmt.Errorf("invalid list members resp: %s", body) } - for _, member := range listMemberResp.GetMembers() { - if leader := member.GetLeader(); leader != nil { - membersInfo.Leader = leader - } else if masters := member.GetMaster(); masters != nil { - membersInfo.Masters = append(membersInfo.Masters, masters.Masters...) - } else if workers := member.GetWorker(); workers != nil { - membersInfo.Workers = append(membersInfo.Workers, workers.Workers...) - } - } - return membersInfo, nil -} -func (mc *masterClient) GetMasters() (*MembersInfo, error) { - query := "?leader=true&master=true" - apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) - return mc.GetMembers(apiURL) + return listMemberResp.ListMemberResp[0].Masters, nil } // NewMasterClient returns a new MasterClient diff --git a/pkg/dmapi/fake_dmapi.go b/pkg/dmapi/fake_dmapi.go index 6478866773..9af8ee2c4f 100644 --- a/pkg/dmapi/fake_dmapi.go +++ b/pkg/dmapi/fake_dmapi.go @@ -20,7 +20,6 @@ import ( type ActionType string const ( - GetMembersActionType ActionType = "GetMembers" GetMastersActionType ActionType = "GetMasters" ) @@ -65,20 +64,11 @@ func (pc *FakeMasterClient) fakeAPI(actionType ActionType, action *Action) (inte return nil, &NotFoundReaction{actionType} } -func (pc *FakeMasterClient) GetMembers(_ string) (*MembersInfo, error) { - action := &Action{} - result, err := pc.fakeAPI(GetMembersActionType, action) - if err != nil { - return nil, err - } - return result.(*MembersInfo), nil -} - -func (pc *FakeMasterClient) GetMasters() (*MembersInfo, error) { +func (pc *FakeMasterClient) GetMasters() ([]*MastersInfo, error) { action := &Action{} result, err := pc.fakeAPI(GetMastersActionType, action) if err != nil { return nil, err } - return result.(*MembersInfo), nil + return result.([]*MastersInfo), nil } From 7a51c077e02ad9a182aaad6898d937b2604b7a9a Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 12 Aug 2020 13:55:51 +0800 Subject: [PATCH 10/37] fix bugs --- go.mod | 50 ++- go.sum | 602 +------------------------------- pkg/discovery/discovery.go | 14 +- pkg/discovery/discovery_test.go | 120 +++---- 4 files changed, 117 insertions(+), 669 deletions(-) diff --git a/go.mod b/go.mod index 0e3368cd29..3ac43dbca4 100644 --- a/go.mod +++ b/go.mod @@ -10,11 +10,12 @@ require ( github.com/Azure/go-autorest/autorest/mocks v0.3.0 // indirect github.com/BurntSushi/toml v0.3.1 github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect - github.com/Masterminds/semver v1.5.0 + github.com/Masterminds/semver v1.4.2 github.com/Microsoft/go-winio v0.4.12 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/aws/aws-sdk-go v1.30.24 + github.com/aws/aws-sdk-go v1.30.9 github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect + github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect github.com/coreos/etcd v3.3.15+incompatible github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 github.com/docker/go-connections v0.4.0 // indirect @@ -24,46 +25,59 @@ require ( github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect; indirectload github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect github.com/emicklei/go-restful v2.9.5+incompatible - github.com/fatih/color v1.9.0 + github.com/fatih/color v1.7.0 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-openapi/loads v0.19.4 - github.com/go-openapi/spec v0.19.7 + github.com/go-openapi/spec v0.19.3 github.com/go-sql-driver/mysql v1.5.0 github.com/gogo/protobuf v1.3.1 - github.com/google/go-cmp v0.4.0 + github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect + github.com/golang/snappy v0.0.1 // indirect + github.com/google/go-cmp v0.3.1 github.com/gophercloud/gophercloud v0.3.0 // indirect github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.13.0 // indirect github.com/imdario/mergo v0.3.7 // indirect - github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 + github.com/juju/errors v0.0.0-20180806074554-22422dad46e1 github.com/juju/loggo v0.0.0-20180524022052-584905176618 // indirect + github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 // indirect github.com/mholt/archiver v3.1.1+incompatible github.com/minio/minio-go/v6 v6.0.55 github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb github.com/nwaples/rardecode v1.0.0 // indirect - github.com/onsi/ginkgo v1.11.0 - github.com/onsi/gomega v1.8.1 + github.com/onsi/ginkgo v1.10.3 + github.com/onsi/gomega v1.5.0 github.com/openshift/generic-admission-server v1.14.0 + github.com/opentracing/opentracing-go v1.1.0 // indirect + github.com/pierrec/lz4 v2.0.5+incompatible // indirect github.com/pingcap/advanced-statefulset/client v1.16.0 - github.com/pingcap/dm v1.1.0-alpha.0.20200806100226-77bbd6b052b4 - github.com/pingcap/errors v0.11.5-0.20190809092503-95897b64e011 - github.com/pingcap/kvproto v0.0.0-20200706115936-1e0910aabe6c + github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 // indirect + github.com/pingcap/errors v0.11.0 + github.com/pingcap/kvproto v0.0.0-20191217072959-393e6c0fd4b7 github.com/pingcap/pd v2.1.17+incompatible github.com/pingcap/tidb v2.1.0-beta+incompatible - github.com/prometheus/client_golang v1.5.1 - github.com/prometheus/common v0.9.1 + github.com/prometheus/client_golang v0.9.2 + github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 github.com/prometheus/prometheus v1.8.2 github.com/robfig/cron v1.1.0 - github.com/sirupsen/logrus v1.6.0 - github.com/spf13/cobra v1.0.0 - github.com/spf13/pflag v1.0.5 - github.com/ugorji/go/codec v1.1.7 + github.com/sirupsen/logrus v1.5.0 + github.com/soheilhy/cmux v0.1.4 // indirect + github.com/spf13/cobra v0.0.5 + github.com/spf13/pflag v1.0.3 + github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect + github.com/uber-go/atomic v0.0.0-00010101000000-000000000000 // indirect + github.com/uber/jaeger-client-go v2.19.0+incompatible // indirect + github.com/uber/jaeger-lib v2.2.0+incompatible // indirect + github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/yisaer/crd-validation v0.0.3 gocloud.dev v0.18.0 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e gomodules.xyz/jsonpatch/v2 v2.0.1 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect - gopkg.in/yaml.v2 v2.2.8 + gopkg.in/yaml.v2 v2.2.4 k8s.io/api v0.0.0 k8s.io/apiextensions-apiserver v0.0.0 k8s.io/apimachinery v0.0.0 diff --git a/go.sum b/go.sum index 2bc7d7e7be..06acb3dc4e 100644 --- a/go.sum +++ b/go.sum @@ -5,30 +5,11 @@ cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.39.0 h1:UgQP9na6OTfp4dsAiz/eFpFA1C6tPdH5wiRdi19tuMw= cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= -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 h1:0E3eE8MX426vUOs7aHfI7aN1BrIzzzf4ccKCSfSjGmc= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0 h1:sAbMqjY1PEQKZBWfbu6Y6bsupJ9c4QdHnzg/VvYTLcE= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/datastore v1.0.0 h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0 h1:9/vpR43S4aJaROxqQHQ3nH9lfyKKV0dC3vOmnw8ebQQ= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.4.0/go.mod h1:ZusYJWlOshgSBGbt6K3GnB3MT3H1xs2id9+TCl4fDBA= -cloud.google.com/go/storage v1.5.0 h1:RPUcBvDeYgQFMfQu1eBMq6piD1SXmLH+vK3qjewZPus= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= @@ -63,20 +44,15 @@ github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190605020000-c4ba1fdf4d36/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534 h1:N7lSsF+R7wSulUADi36SInSQA3RvfO/XclHQfedr0qk= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= -github.com/Jeffail/gabs/v2 v2.5.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI= -github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e h1:eb0Pzkt15Bm7f2FFYv7sjY7NPFi3cPkS3tv1CcrFBWA= github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -84,7 +60,6 @@ github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXn github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -93,16 +68,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Rican7/retry v0.1.0/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -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 v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -github.com/appleboy/gin-jwt/v2 v2.6.3/go.mod h1:MfPYA4ogzvOcVkRwAxT7quHOtQmVKDpTwxyUrC2DNw0= -github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -114,49 +81,30 @@ github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.19.45 h1:jAxmC8qqa7mW531FDgM8Ahbqlb3zmiHgTpJU6fY3vJ0= github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.26.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.30.24 h1:y3JPD51VuEmVqN3BEDVm4amGpDma2cKJcDPuAU1OR58= -github.com/aws/aws-sdk-go v1.30.24/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.30.9 h1:DntpBUKkchINPDbhEzDRin1eEn1TG9TZFlzWPf0i8to= +github.com/aws/aws-sdk-go v1.30.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/bazelbuild/bazel-gazelle v0.0.0-20181012220611-c728ce9f663e/go.mod h1:uHBSeeATKpVazAACZBDPL/Nk/UhQDDsJWDlqYJo8/Us= github.com/bazelbuild/buildtools v0.0.0-20180226164855-80c7f0d45d7e/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= 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 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -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/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= -github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU= github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho= github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/cheggaaa/pb/v3 v3.0.1/go.mod h1:SqqeMF/pMOIu3xgGoxtPYhMNQP258xE4x/XRTYua+KU= -github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cfssl v0.0.0-20180726162950-56268a613adf/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= @@ -165,15 +113,9 @@ github.com/containerd/console v0.0.0-20170925154832-84eeaae905fa/go.mod h1:Tj/on github.com/containerd/containerd v1.0.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/coocood/badger v1.5.1-0.20200515070411-e02af0688441/go.mod h1:klY8SfH2lNZ/23/SIxwHoJw+T6wYGB12YPCF9MUoiu0= -github.com/coocood/badger v1.5.1-0.20200528065104-c02ac3616d04/go.mod h1:klY8SfH2lNZ/23/SIxwHoJw+T6wYGB12YPCF9MUoiu0= -github.com/coocood/bbloom v0.0.0-20190830030839-58deb6228d64/go.mod h1:F86k/6c7aDUdwSUevnLpHS/3Q9hzYCE99jGk2xsHnt0= -github.com/coocood/rtutil v0.0.0-20190304133409-c84515f646f2/go.mod h1:7qG7YFnOALvsx6tKTNmQot8d7cGFXM9TidzvRFLWYwM= github.com/coredns/corefile-migration v1.0.2/go.mod h1:OFwBp/Wc9dJt5cAZzHWMNhK1r5L0p0jDwIBc6j8NC8E= github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A= github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE= github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -184,42 +126,19 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea h1:n2Ltr3SrfQlf/9nOna1DoGKxLx3qTSI8Ttl6Xrqp6mw= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/rkt v1.30.0/go.mod h1:O634mlH6U7qk87poQifK6M2rsFNt+FyUTWNMnP1hF1U= -github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/cznic/golex v0.0.0-20181122101858-9c343928389c/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= -github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= -github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM= -github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= -github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= -github.com/cznic/y v0.0.0-20170802143616-045f81c6662a/go.mod h1:1rk5VM7oSnA4vjp+hrLQ3HWHa+Y4yPCa3/CsJrcNnvs= -github.com/danjacques/gofslock v0.0.0-20191023191349-0a45f885bc37/go.mod h1:DC3JtzuG7kxMvJ6dZmf2ymjNyoXwgtklr7FN+Um2B0U= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= -github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= @@ -231,8 +150,6 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s= @@ -241,13 +158,9 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs= github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -256,10 +169,6 @@ github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -272,49 +181,27 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsouza/fake-gcs-server v1.15.0/go.mod h1:HNxAJ/+FY/XSsxuwz8iIYdp2GtMmPbJ8WQjjGMxd6Qk= -github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= -github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w= -github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= -github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= -github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -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-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -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-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -334,11 +221,8 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -350,13 +234,9 @@ github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.7 h1:0xWSeMd35y5avQAThZR2PkEuqSosoS5t6gDH4L8n11M= -github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= @@ -368,16 +248,9 @@ github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.8 h1:vfK6jLhs7OI4tAXkvkooviaE1JEPcw3mutyegLHHjmk= -github.com/go-openapi/swag v0.19.8/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/overalls v0.0.0-20180201144345-22ec1a223b7c/go.mod h1:UqxAgEOt89sCiXlrc/ycnx00LVvUO/eS8tMUkWX4R7w= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= @@ -504,34 +377,21 @@ github.com/gobuffalo/uuid v2.0.5+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw github.com/gobuffalo/validate v2.0.3+incompatible/go.mod h1:N+EtDe0J8252BgfzQUChBgfd6L93m9weay53EWFVsMM= github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOreDJznWevcn8NTmQEW5STSBgIkpkjzqXc= github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY= -github.com/goccy/go-graphviz v0.0.5/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= github.com/gogo/protobuf v0.0.0-20180717141946-636bf0302bc9/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff h1:kOkM9whyQYodu09SJ6W3NCsHG7crFaJILQ22Gozp3lg= github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/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 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -541,9 +401,6 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= @@ -551,16 +408,12 @@ github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkY github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/cadvisor v0.34.0/go.mod h1:1nql6U13uTHaLYB8rLS5x9IJc2qT6Xd/Tr1sTX6NE48= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= 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 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-replayers/grpcreplay v0.1.0 h1:eNb1y9rZFmY4ax45uEEECSa8fsxGRU+8Bil52ASAwic= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0 h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk= @@ -572,11 +425,7 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 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-20190930153522-6ce02741cba3/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20200407044318-7d83b28da2e9/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -587,8 +436,6 @@ github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= @@ -598,43 +445,29 @@ github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEo 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/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.1.2/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q= github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.2 h1:S+ef0492XaIknb8LMjcwgW2i3cNTzDYMmDrOThOJNWc= github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= -github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= -github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69/go.mod h1:YLEMZOtU+AZ7dhN9T/IpGhXVGly2bvkJQ+zxj3WeVQo= +github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI= +github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -648,9 +481,6 @@ github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7U github.com/heketi/utils v0.0.0-20170317161834-435bc5bdfa64/go.mod h1:RYlF4ghFZPPmk2TC5REt5OFwvfb6lzxFWrTWB+qs28s= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hypnoglow/gormzap v0.3.0/go.mod h1:5Wom8B7Jl2oK0Im9hs6KQ+Kl92w4Y7gKCrj66rhyvw0= -github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= @@ -659,11 +489,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= -github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -674,53 +500,30 @@ github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/joomcode/errorx v1.0.1/go.mod h1:kgco15ekB6cs+4Xjzo7SPeXzx38PbJzBwbnu9qfVNHQ= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -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/juju/clock v0.0.0-20180524022203-d293bb356ca4/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= -github.com/juju/errors v0.0.0-20150916125642-1b5e39b83d18/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 h1:rhqTjzJlm7EbkELJDKMTU7udov+Se0xZkWmugr6zGok= -github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/errors v0.0.0-20180806074554-22422dad46e1 h1:wnhMXidtb70kDZCeLt/EfsVtkXS5c8zLnE9y/6DIRAU= +github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8= github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= -github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= -github.com/juju/testing v0.0.0-20200510222523-6c8c298c77a0/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo= -github.com/juju/testing v0.0.0-20200608005635-e4eedbc6f7aa h1:v1ZEHRVaUgTIkxzYaT78fJ+3bV3vjxj9jfNJcYzi9pY= -github.com/juju/testing v0.0.0-20200608005635-e4eedbc6f7aa/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo= -github.com/juju/utils v0.0.0-20180808125547-9dfc6dbfb02b/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= -github.com/juju/version v0.0.0-20161031051906-1f41e27e54f2/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 h1:WQM1NildKThwdP7qWrNAFGzp4ijNLw8RlgENkaI4MJs= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kevinburke/go-bindata v3.18.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -729,9 +532,6 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/lance6716/retool v1.3.7/go.mod h1:9nFHbMjlFhh2msJ6vuHgpz7OM7G9RO0wSLO/w1u2nhM= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= @@ -752,8 +552,6 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8= -github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c= @@ -776,32 +574,18 @@ github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRU github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mesos/mesos-go v0.0.9/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= -github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= -github.com/mgechev/revive v1.0.2/go.mod h1:rb0dQy1LVAxW9SWy5R3LPUjevzUbUS316U5MFySA2lo= github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= @@ -832,44 +616,27 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb h1:e+l77LJOEqXTIQihQJVkA6ZxPOUmfPM5e4H7rcpgtSk= github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q= -github.com/montanaflynn/stats v0.0.0-20151014174947-eeaced052adb/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.0.0-20180911141734-db72e6cae808/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d h1:7PxY7LVfSZm7PEeBTyK1rj1gABdCO2mbri6GKO1cMDs= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mvdan/xurls v1.1.0/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8= github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= -github.com/ncw/directio v1.0.4/go.mod h1:CKGdcN7StAaqjT7Qack3lAXeX4pjnyc46YeqZH1yWVY= -github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7/go.mod h1:iWMfgwqYW+e8n5lC/jjNEhwcjbRDpl5NT7n2h+4UNcI= -github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef/go.mod h1:7WjlapSfwQyo6LNmIvEWzsW1hbBQfpUO4JWnuQRmva8= -github.com/ngaut/unistore v0.0.0-20200521040325-2af94f1b0c83/go.mod h1:odn0MiR+DNxnxOiCskG4wWacBIW2GBmJOf/TAnMZfWE= -github.com/ngaut/unistore v0.0.0-20200603091253-e0b717679796/go.mod h1:9mpqZeS1CkNlgZwJ0LZXb+Qd7xVO5o55ngys7T1/oH8= -github.com/ngaut/unistore v0.0.0-20200604043635-5004cdad650f/go.mod h1:5Vec+R2BwOyugVQ8Id8uDmlIYbqodCvykM50IpaAjk4= -github.com/ngaut/unistore v0.0.0-20200604061006-d8e9dc0ad154/go.mod h1:YGQzxn9cVy0q2puXVt1X8l5OohRHv2djR/ziz1k14XQ= -github.com/ngaut/unistore v0.0.0-20200630072006-0c4035925f69/go.mod h1:Hxlp5VAoPOHwcXLUw/E+P3XjJX1EP38NWjXPpc4nuOE= github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs= github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -877,8 +644,6 @@ github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= -github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -888,8 +653,6 @@ github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= github.com/openshift/generic-admission-server v1.14.0 h1:GAQy5JNVcbmUuIpPvLd39+2rPecxEm7WQ2sP7ACrse4= github.com/openshift/generic-admission-server v1.14.0/go.mod h1:GD9KN/W4KxqRQGVMbqQHpHzb2XcQVvLCaBaSciqXvfM= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= @@ -897,104 +660,22 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.3.0 h1:e5+lF2E4Y2WCIxBefVowBuB0iHrUH4HZ8q+6mGF7fJc= -github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/phf/go-queue v0.0.0-20170504031614-9abe38d0371d/go.mod h1:lXfE4PvvTW5xOjO6Mba8zDPyw8M93B6AQ7frTGnMlA8= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pingcap-incubator/tidb-dashboard v0.0.0-20200407064406-b2b8ad403d01/go.mod h1:77fCh8d3oKzC5ceOJWeZXAS/mLzVgdZ7rKniwmOyFuo= -github.com/pingcap-incubator/tidb-dashboard v0.0.0-20200514075710-eecc9a4525b5/go.mod h1:8q+yDx0STBPri8xS4A2duS1dAf+xO0cMtjwe0t6MWJk= -github.com/pingcap-incubator/tidb-dashboard v0.0.0-20200710045508-523e95bc5ec9/go.mod h1:9yaAM77sPfa5/f6sdxr3jSkKfIz463KRHyiFHiGjdes= github.com/pingcap/advanced-statefulset/client v1.16.0 h1:Wit+eYaXhKz0pIG6jixvyYxCVnQoZtpGzN9pXizkB9Y= github.com/pingcap/advanced-statefulset/client v1.16.0/go.mod h1:2IzDKzJxCHnrl3twx7yBnFX5csMeiBJFjlkUn0z0gZE= -github.com/pingcap/badger v1.5.1-0.20200604041313-19c397305fcc/go.mod h1:LyrqUOHZrUDf9oGi1yoz1+qw9ckSIhQb5eMa1acOLNQ= -github.com/pingcap/br v0.0.0-20200426093517-dd11ae28b885/go.mod h1:4w3meMnk7HDNpNgjuRAxavruTeKJvUiXxoEWTjzXPnA= -github.com/pingcap/br v0.0.0-20200521085655-53201addd4ad/go.mod h1:SlSUHWY7QUoooiYxOKuJ8kUh2KjI29ogBh89YXz2dLA= -github.com/pingcap/br v0.0.0-20200610051721-b057d65ff579/go.mod h1:Gq6o66nDReG0fMxqSdl8JHLZhMnxKhVxtHxqubUWAyg= -github.com/pingcap/br v0.0.0-20200617120402-56e151ad8b67/go.mod h1:/3QzpDG7YTPrDsrg8i1lwdYUrplJ0jVD+9pxhh19+k4= -github.com/pingcap/br v0.0.0-20200723130425-d904ae3349a1/go.mod h1:4iTqZAMbEPmjBggYixqIg2FwIHBQtyImTM/QYlpTBGk= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 h1:USx2/E1bX46VG32FIw034Au6seQ2fY9NEILmNh/UlQg= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= -github.com/pingcap/check v0.0.0-20191107115940-caf2b9e6ccf4/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= -github.com/pingcap/check v0.0.0-20191216031241-8a5a85928f12/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= -github.com/pingcap/check v0.0.0-20200212061837-5e12011dc712 h1:R8gStypOBmpnHEx1qi//SaqxJVI4inOqljg/Aj5/390= -github.com/pingcap/check v0.0.0-20200212061837-5e12011dc712/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= -github.com/pingcap/dm v1.1.0-alpha.0.20200806100226-77bbd6b052b4 h1:62ie/18pg0OISH9sCZFZ1/uMJeyUV36wWDR9ICmTW/c= -github.com/pingcap/dm v1.1.0-alpha.0.20200806100226-77bbd6b052b4/go.mod h1:d1f60ViWD81R6cl78GMGT2ZJksMrPfMS9yYB3mxYDjM= -github.com/pingcap/dumpling v0.0.0-20200605144140-0175843056a6/go.mod h1:LHCdb+QdDdRugY50HhbWtIYUG4qD1PIRqCB9JVYr9F4= -github.com/pingcap/errcode v0.0.0-20180921232412-a1a7271709d9/go.mod h1:4b2X8xSqxIroj/IZ9MX/VGZhAwc11wB9wRIzHvz6SeM= -github.com/pingcap/errcode v0.3.0/go.mod h1:4b2X8xSqxIroj/IZ9MX/VGZhAwc11wB9wRIzHvz6SeM= github.com/pingcap/errors v0.11.0 h1:DCJQB8jrHbQ1VVlMFIrbj2ApScNNotVmkSNplu2yUt4= github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pingcap/errors v0.11.5-0.20190809092503-95897b64e011 h1:58naV4XMEqm0hl9LcYo6cZoGBGiLtefMQMF/vo3XLgQ= -github.com/pingcap/errors v0.11.5-0.20190809092503-95897b64e011/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pingcap/failpoint v0.0.0-20191029060244-12f4ac2fd11d/go.mod h1:DNS3Qg7bEDhU6EXNHF+XSv/PGznQaMJ5FWvctpm6pQI= -github.com/pingcap/failpoint v0.0.0-20200210140405-f8f9fb234798/go.mod h1:DNS3Qg7bEDhU6EXNHF+XSv/PGznQaMJ5FWvctpm6pQI= -github.com/pingcap/failpoint v0.0.0-20200506114213-c17f16071c53/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk= -github.com/pingcap/failpoint v0.0.0-20200603062251-b230c36c413c/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk= -github.com/pingcap/fn v0.0.0-20191016082858-07623b84a47d/go.mod h1:fMRU1BA1y+r89AxUoaAar4JjrhUkVDt0o0Np6V8XbDQ= -github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= -github.com/pingcap/kvproto v0.0.0-20190227013052-e71ca0165a5f/go.mod h1:QMdbTAXCHzzygQzqcG9uVUgU2fKeSN1GmfMiykdSzzY= -github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= -github.com/pingcap/kvproto v0.0.0-20200214064158-62d31900d88e/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200411081810-b85805c9476c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200417092353-efbe03bcffbd/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200420075417-e0c6e8842f22/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200423020121-038e31959c2a/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200424032552-6650270c39c3/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200428135407-0f5ffe459677/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200518112156-d4aeb467de29/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200608081027-d02a6f65e956/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200701055533-4ef28cac01f8/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20200706115936-1e0910aabe6c h1:VnLpCAxMAeDxc7HXTetwDQB+/MtDQjHAOBsd4QnGVwA= -github.com/pingcap/kvproto v0.0.0-20200706115936-1e0910aabe6c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= -github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= -github.com/pingcap/log v0.0.0-20200511115504-543df19646ad h1:SveG82rmu/GFxYanffxsSF503SiQV+2JLnWEiGiF+Tc= -github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= -github.com/pingcap/parser v0.0.0-20190506092653-e336082eb825/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= -github.com/pingcap/parser v0.0.0-20200424075042-8222d8b724a4/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= -github.com/pingcap/parser v0.0.0-20200507022230-f3bf29096657/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= -github.com/pingcap/parser v0.0.0-20200518090819-ec1e13b948b1/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= -github.com/pingcap/parser v0.0.0-20200522094936-3b720a0512a6/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= -github.com/pingcap/parser v0.0.0-20200609110328-c65941b9fbb3/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= -github.com/pingcap/parser v0.0.0-20200623082809-b74301ac298b/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= -github.com/pingcap/parser v0.0.0-20200717054943-cd445b0c607b/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0= +github.com/pingcap/kvproto v0.0.0-20191217072959-393e6c0fd4b7 h1:thLL2vFObG8vxBCkAmfAbLVBPfXUkBSXaVxppStCrL0= +github.com/pingcap/kvproto v0.0.0-20191217072959-393e6c0fd4b7/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/pd v2.1.17+incompatible h1:mpfJYffRC14jeAfiq0jbHkqXVc8ZGNV0Lr2xG1sJslw= github.com/pingcap/pd v2.1.17+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= -github.com/pingcap/pd/v4 v4.0.0-rc.1.0.20200422143320-428acd53eba2/go.mod h1:s+utZtXDznOiL24VK0qGmtoHjjXNsscJx3m1n8cC56s= -github.com/pingcap/pd/v4 v4.0.0-rc.2.0.20200520083007-2c251bd8f181/go.mod h1:q4HTx/bA8aKBa4S7L+SQKHvjRPXCRV0tA0yRw0qkZSA= -github.com/pingcap/pd/v4 v4.0.0-rc.2.0.20200714122454-1a64f969cb3c/go.mod h1:v/dY4mVkt3dh/Liphhk0E4ScOkZpIk0m0GvWJ9FapDs= -github.com/pingcap/sysutil v0.0.0-20200206130906-2bfa6dc40bcd/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= -github.com/pingcap/sysutil v0.0.0-20200408114249-ed3bd6f7fdb1/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= -github.com/pingcap/sysutil v0.0.0-20200715082929-4c47bcac246a/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= -github.com/pingcap/tidb v1.1.0-beta.0.20200424154252-5ede18f10eed/go.mod h1:m2VDlJDbUeHPCXAfKPajqLmB1uLvWpkKk3zALNqDYdw= -github.com/pingcap/tidb v1.1.0-beta.0.20200509133407-a9dc72cf2558/go.mod h1:cXNbVSQAkwwmjFQmEnEPI00Z2/Y/KOhouttUPERiInE= -github.com/pingcap/tidb v1.1.0-beta.0.20200513065557-5a0787dfa915/go.mod h1:khS9Z9YlbtxsaZsSsSahelgh5L16EtP30QADFmPiI/I= -github.com/pingcap/tidb v1.1.0-beta.0.20200521154755-134e691d6f5f/go.mod h1:HobvT8ySGq9gkwPoyz/+V6TKWMRGEzFQobJOvLc2Oy8= -github.com/pingcap/tidb v1.1.0-beta.0.20200603101356-552e7709de0d/go.mod h1:wgu4vP3wq+x/l1X3ckOZFvyGKcVIBkq30NQVh0Y+qYA= -github.com/pingcap/tidb v1.1.0-beta.0.20200604055950-efc1c154d098/go.mod h1:UMxsNE326wyfgFJCx6aerPRLj1/tGPYDBKS9T9NOHI8= -github.com/pingcap/tidb v1.1.0-beta.0.20200610060912-f12cdc42010f/go.mod h1:jyXOvS9k0PTxYHju2OgySOe9FtydA52TiQ5bXAaKyQE= -github.com/pingcap/tidb v1.1.0-beta.0.20200721005019-f5c6e59f0daf/go.mod h1:dYCOFXJsoqBumpxAyBqCG3WZriIY7JgeBZHgvfARDa8= -github.com/pingcap/tidb v1.1.0-beta.0.20200728020902-472acf7b85b3/go.mod h1:533tLZJJQhCw7CuuYNJYMdd8aJxZXR+6TWMu3PJHIX4= github.com/pingcap/tidb v2.1.0-beta+incompatible h1:SQUmscnvvjHLjaIycQqtHujBahUnlKwTz6dQQhqgGSc= github.com/pingcap/tidb v2.1.0-beta+incompatible/go.mod h1:I8C6jrPINP2rrVunTRd7C9fRRhQrtR43S1/CL5ix/yQ= -github.com/pingcap/tidb-tools v4.0.0-beta.1.0.20200306084441-875bd09aa3d5+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tidb-tools v4.0.0-rc.1.0.20200421113014-507d2bb3a15e+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tidb-tools v4.0.0-rc.1.0.20200514040632-f76b3e428e19+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tidb-tools v4.0.0-rc.2.0.20200521050818-6dd445d83fe0+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tidb-tools v4.0.0+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tidb-tools v4.0.1+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tidb-tools v4.0.3-0.20200717061805-6483ba1f6311+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tipb v0.0.0-20190428032612-535e1abaa330/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= -github.com/pingcap/tipb v0.0.0-20200417094153-7316d94df1ee/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= -github.com/pingcap/tipb v0.0.0-20200604070248-508f03b0b342/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= -github.com/pingcap/tipb v0.0.0-20200615034523-dcfcea0b5965/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= -github.com/pingcap/tipb v0.0.0-20200618092958-4fad48b4c8c3/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1005,42 +686,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/ffjson v0.0.0-20180717144149-af8b230fcd20/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= -github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= 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 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -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.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/prometheus v1.8.2 h1:PAL466mnJw1VolZPm1OarpdUpqukUy/eX4tagia17DM= github.com/prometheus/prometheus v1.8.2/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= -github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= -github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron v1.1.0 h1:jk4/Hud3TTdcrJgUOBgsqrZBarcxl6ADIjSC2iniwLY= github.com/robfig/cron v1.1.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -1049,49 +706,30 @@ github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYe github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.0.1-alpha.3/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v2.19.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20191125035519-b054a8dfd10d/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= github.com/shurcooL/highlight_go v0.0.0-20170515013102-78fb10f4a5f8/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= github.com/shurcooL/octicon v0.0.0-20180602230221-c42b0e3b24d9/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= -github.com/siddontang/go-log v0.0.0-20180807004314-8d05993dda07/go.mod h1:yFdBgwXP24JziuRl2NMUahT7nGLNOKi1SIiFxMttVD4= -github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed/go.mod h1:yFdBgwXP24JziuRl2NMUahT7nGLNOKi1SIiFxMttVD4= -github.com/siddontang/go-mysql v0.0.0-20200222075837-12e89848f047/go.mod h1:+W4RCzesQDI11HvIkaDjS8yM36SpAnGNQ7jmTLn5BnU= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= @@ -1101,8 +739,6 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -1112,8 +748,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1122,13 +756,9 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/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.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= 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= @@ -1138,58 +768,28 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 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 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E= -github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI= -github.com/swaggo/http-swagger v0.0.0-20200103000832-0e9263c4b516/go.mod h1:O1lAbCgAAX/KZ80LM/OXwtWFI/5TvZlwxSg8Cq08PV0= -github.com/swaggo/http-swagger v0.0.0-20200308142732-58ac5e232fba/go.mod h1:O1lAbCgAAX/KZ80LM/OXwtWFI/5TvZlwxSg8Cq08PV0= -github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y= -github.com/swaggo/swag v1.6.3/go.mod h1:wcc83tB4Mb2aNiL/HP4MFeQdpHUrca+Rp/DRNgWAUio= -github.com/swaggo/swag v1.6.5/go.mod h1:Y7ZLSS0d0DdxhWGVhQdu+Bu1QhaF5k0RD7FKdiAykeY= -github.com/swaggo/swag v1.6.6-0.20200323071853-8e21f4cefeea/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= -github.com/swaggo/swag v1.6.6-0.20200529100950-7c765ddd0476/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/goleveldb v0.0.0-20180815032940-ae2bd5eed72d/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= -github.com/syndtr/goleveldb v1.0.1-0.20190625010220-02440ea7a285/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM= -github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2/go.mod h1:2PfKggNGDuadAa0LElHrByyrz4JPZ9fFx6Gs7nx7ZZU= -github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 h1:lYIiVDtZnyTWlNwiAxLj0bbpTcx1BWCFhXjfsvmPdNc= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM= -github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uber/jaeger-client-go v2.19.0+incompatible h1:pbwbYfHUoaase0oPQOdZ1GcaUjImYGimUXSQ/+8+Z8Q= +github.com/uber/jaeger-client-go v2.19.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= -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 v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= +github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= -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/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA= +github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg= -github.com/unrolled/render v1.0.1/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/negroni v0.3.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= @@ -1203,16 +803,6 @@ github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSf github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yisaer/crd-validation v0.0.3 h1:PmhrjDQbdkZOYz/1iVnK1UlY8q8Uw7hn1rlGm575sL8= github.com/yisaer/crd-validation v0.0.3/go.mod h1:aWBclg0rUEvCnOnRZGDF6oC9Ljni2s17G/YVdYuTTww= -github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/zhangjinpeng1987/raft v0.0.0-20190624145930-deeb32d6553d/go.mod h1:1KDQ09J8MRHEtHze4at7BJZDW/doUAgkJ8w9KjEUhSo= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1 h1:Sq1fR+0c58RME5EoqKdjkiQAmPjmfHlZOoRI6fTUOcs= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -1220,43 +810,19 @@ go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU= -go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= -go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= gocloud.dev v0.18.0 h1:HX6uFZYZs9tUP87jzoWgB8dl4ihsRpiAsBDKTthiApY= gocloud.dev v0.18.0/go.mod h1:lhLOb91+9tKB8RnNlsx+weJGEd0AHM94huK1bmrhPwM= -golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1275,53 +841,28 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w= -golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk= golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -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 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 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/image v0.0.0-20200119044424-58c23975cae1/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 h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 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-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/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 h1:JgcxKXxCjrA2tyDP/aNU9K0Ck5Czfk6C7e2tMw7+bSI= 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.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1348,31 +889,21 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/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-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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= @@ -1400,9 +931,7 @@ golang.org/x/sys v0.0.0-20181026064943-731415f00dce/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181106135930-3a76605856fd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1415,40 +944,19 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/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-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190620070143-6f217b454f45 h1:Dl2hc890lrizvUppGbRWhnIh2f8jOTCQpY5IKWRS0oM= golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/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-20191128015809-6d18c012aee9/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-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/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.20171227012246-e19ae1496984/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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= 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 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20170824195420-5d2fd3ccab98/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181006002542-f60d9635b16a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1472,43 +980,15 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 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-20190422233926-fe54fb35175b/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-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/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-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-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191107010934-f79515f33823/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-20191114200427-caa0b0f7d508/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-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200325203130-f53864d0dba1/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d h1:SR+e35rACZFBohNb4Om1ibX6N3iO0FtdbwqGSuD9dBU= -golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= 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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= @@ -1521,14 +1001,6 @@ google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.6.1-0.20190607001116-5213b8090861 h1:ppLucX0K/60T3t6LPZQzTOkt5PytkEbQLIaSteq+TpE= google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= -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.15.1 h1:5mMS6mYvK5LVB8+ujVBC33Y8gltBo/kT6HBm6kU80G4= -google.golang.org/api v0.15.1/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1536,8 +1008,6 @@ google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= -google.golang.org/appengine v1.6.5/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-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1549,52 +1019,30 @@ google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 h1:9VBRTdmgQxbs6HE0sUnMrSWNePppAJU07NYvX5dIB04= google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -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-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/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 h1:ADPHZzpzM4tk4V4S5cnCrr5SwzvlrPRmqqCuJDB8UTs= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/grpc v0.0.0-20180607172857-7a6a684ca69e/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/gometalinter.v2 v2.0.12/go.mod h1:NDRytsqEZyolNuAgTzJkZMkSQM7FIKyzVzGhjB/qfYo= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.0 h1:0HIbH907iBTAntm+88IJV2qmJALDAh8sPekI9Vc1fm0= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= -gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -1603,7 +1051,6 @@ gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= -gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= @@ -1615,7 +1062,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.1 h1:XM28wIgFzaBmeZ5dNHIpWLQpt/9DGKxk+rCg/22nnYE= gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170712054546-1be3d31502d6/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1623,10 +1069,6 @@ 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 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.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= @@ -1636,10 +1078,6 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh 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.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -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 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.0.0-20190918155943-95b840bb6a1f h1:8FRUST8oUkEI45WYKyD8ed7Ad0Kg5v11zHyPkEVb2xo= k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783 h1:V6ndwCPoao1yZ52agqOKaUAl7DYWVGiXjV7ePA2i610= @@ -1702,7 +1140,6 @@ modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-builder-alpha v0.0.0-20191113095113-4493943d2568 h1:3xmk5xge937C5x9PGatobpFlJG9hqI+sXS908bunuOQ= sigs.k8s.io/apiserver-builder-alpha v0.0.0-20191113095113-4493943d2568/go.mod h1:p0w5ou+8SCTGiaMD9cWxOWOn0Xl84wS8AQ3a7lCll7M= sigs.k8s.io/apiserver-builder-alpha/cmd v0.0.0-20191113095113-4493943d2568 h1:+m4eqp4ZKgZmcp9dn6le1u3HMxjUig3kflg3gUZbbK8= @@ -1720,7 +1157,4 @@ sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20180531100431-4c381bd170b4/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/pkg/discovery/discovery.go b/pkg/discovery/discovery.go index f5eec1aed3..774195e2e1 100644 --- a/pkg/discovery/discovery.go +++ b/pkg/discovery/discovery.go @@ -134,7 +134,7 @@ func (td *tidbDiscovery) DiscoverDM(advertisePeerUrl string) (string, error) { } podName, peerServiceName, ns := strArr[0], strArr[1], strArr[2] - dcName := strings.TrimSuffix(peerServiceName, "-master-peer") + dcName := strings.TrimSuffix(peerServiceName, "-dm-master-peer") podNamespace := os.Getenv("MY_POD_NAMESPACE") if ns != podNamespace { return "", fmt.Errorf("dm the peer's namespace: %s is not equal to discovery namespace: %s", ns, podNamespace) @@ -149,7 +149,7 @@ func (td *tidbDiscovery) DiscoverDM(advertisePeerUrl string) (string, error) { currentCluster := td.dmClusters[keyName] if currentCluster == nil || currentCluster.resourceVersion != dc.ResourceVersion { - td.clusters[keyName] = &clusterInfo{ + td.dmClusters[keyName] = &clusterInfo{ resourceVersion: dc.ResourceVersion, peers: map[string]struct{}{}, } @@ -163,15 +163,15 @@ func (td *tidbDiscovery) DiscoverDM(advertisePeerUrl string) (string, error) { } masterClient := td.masterControl.GetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), dc.IsTLSClusterEnabled()) - membersInfo, err := masterClient.GetMasters() + mastersInfos, err := masterClient.GetMasters() if err != nil { return "", err } - membersArr := make([]string, 0) - for _, member := range membersInfo.Masters { - membersArr = append(membersArr, member.ClientURLs[0]) + mastersArr := make([]string, 0) + for _, master := range mastersInfos { + mastersArr = append(mastersArr, master.ClientURLs[0]) } delete(currentCluster.peers, podName) - return fmt.Sprintf("--join=%s", strings.Join(membersArr, ",")), nil + return fmt.Sprintf("--join=%s", strings.Join(mastersArr, ",")), nil } diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go index d6ce98784e..c736f6ed7b 100644 --- a/pkg/discovery/discovery_test.go +++ b/pkg/discovery/discovery_test.go @@ -429,7 +429,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { td.(*tidbDiscovery).dmClusters = test.dmClusters os.Setenv("MY_POD_NAMESPACE", test.ns) - re, err := td.Discover(test.url) + re, err := td.DiscoverDM(test.url) test.expectFn(g, td.(*tidbDiscovery), re, err) } tests := []testcase{ @@ -448,7 +448,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { { name: "advertisePeerUrl is wrong", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default:8291", dmClusters: map[string]*clusterInfo{}, dc: newDC(), expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { @@ -460,7 +460,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { { name: "namespace is wrong", ns: "default1", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dmClusters: map[string]*clusterInfo{}, dc: newDC(), expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { @@ -472,7 +472,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { { name: "failed to get tidbcluster", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dmClusters: map[string]*clusterInfo{}, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(apierrors.IsNotFound(err)).To(BeTrue()) @@ -482,7 +482,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { { name: "failed to get members", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dmClusters: map[string]*clusterInfo{}, dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { @@ -491,15 +491,15 @@ func TestDiscoveryDMDiscovery(t *testing.T) { expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).To(HaveOccurred()) g.Expect(strings.Contains(err.Error(), "get members failed")).To(BeTrue()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) }, }, { name: "resourceVersion changed", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("getMembers failed") @@ -516,15 +516,15 @@ func TestDiscoveryDMDiscovery(t *testing.T) { expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).To(HaveOccurred()) g.Expect(strings.Contains(err.Error(), "getMembers failed")).To(BeTrue()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) }, }, { name: "1 cluster, first ordinal, there are no dm-master members", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dmClusters: map[string]*clusterInfo{}, dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { @@ -533,15 +533,15 @@ func TestDiscoveryDMDiscovery(t *testing.T) { expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).To(HaveOccurred()) g.Expect(strings.Contains(err.Error(), "there are no dm-master members")).To(BeTrue()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) }, }, { name: "1 cluster, second ordinal, there are no dm-master members", ns: "default", - url: "demo-dm-master-1.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-1.demo-dm-master-peer.default.svc:8291", dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("there are no dm-master members 2") @@ -557,16 +557,16 @@ func TestDiscoveryDMDiscovery(t *testing.T) { expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).To(HaveOccurred()) g.Expect(strings.Contains(err.Error(), "there are no dm-master members 2")).To(BeTrue()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(2)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(2)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) }, }, { name: "1 cluster, third ordinal, return the initial-cluster args", ns: "default", - url: "demo-dm-master-2.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-2.demo-dm-master-peer.default.svc:8291", dc: newDC(), dmClusters: map[string]*clusterInfo{ "default/demo": { @@ -579,17 +579,17 @@ func TestDiscoveryDMDiscovery(t *testing.T) { }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).NotTo(HaveOccurred()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(2)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) - g.Expect(s).To(Equal("--initial-cluster=demo-dm-master-2=http://demo-dm-master-2.demo-dm-master-peer.default.svc:2380")) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(2)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) + g.Expect(s).To(Equal("--initial-cluster=demo-dm-master-2=http://demo-dm-master-2.demo-dm-master-peer.default.svc:8291")) }, }, { name: "1 cluster, the first ordinal second request, get members failed", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { return nil, fmt.Errorf("there are no dm-master members 3") @@ -606,21 +606,21 @@ func TestDiscoveryDMDiscovery(t *testing.T) { expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).To(HaveOccurred()) g.Expect(strings.Contains(err.Error(), "there are no dm-master members 3")).To(BeTrue()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(2)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(2)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-0"]).To(Equal(struct{}{})) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) }, }, { name: "1 cluster, the first ordinal third request, get members success", ns: "default", - url: "demo-dm-master-0.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-0.demo-dm-master-peer.default.svc:8291", dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:8261"}, }, }, nil }, @@ -635,24 +635,24 @@ func TestDiscoveryDMDiscovery(t *testing.T) { }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).NotTo(HaveOccurred()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(1)) - g.Expect(td.clusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) - g.Expect(s).To(Equal("--join=demo-dm-master-2.demo-dm-master-peer.default.svc:2379")) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(1)) + g.Expect(td.dmClusters["default/demo"].peers["demo-dm-master-1"]).To(Equal(struct{}{})) + g.Expect(s).To(Equal("--join=demo-dm-master-2.demo-dm-master-peer.default.svc:8261")) }, }, { name: "1 cluster, the second ordinal second request, get members success", ns: "default", - url: "demo-dm-master-1.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-1.demo-dm-master-peer.default.svc:8291", dc: newDC(), getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:8261"}, }, { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:8261"}, }, }, nil }, @@ -666,15 +666,15 @@ func TestDiscoveryDMDiscovery(t *testing.T) { }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).NotTo(HaveOccurred()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(0)) - g.Expect(s).To(Equal("--join=demo-dm-master-0.demo-dm-master-peer.default.svc:2379,demo-dm-master-2.demo-dm-master-peer.default.svc:2379")) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(0)) + g.Expect(s).To(Equal("--join=demo-dm-master-0.demo-dm-master-peer.default.svc:8261,demo-dm-master-2.demo-dm-master-peer.default.svc:8261")) }, }, { name: "1 cluster, the fourth ordinal request, get members success", ns: "default", - url: "demo-dm-master-3.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-3.demo-dm-master-peer.default.svc:8291", dc: func() *v1alpha1.DMCluster { dc := newDC() dc.Spec.Master.Replicas = 5 @@ -683,13 +683,13 @@ func TestDiscoveryDMDiscovery(t *testing.T) { getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:8261"}, }, { - PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:8261"}, }, { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:8261"}, }, }, nil }, @@ -701,15 +701,15 @@ func TestDiscoveryDMDiscovery(t *testing.T) { }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).NotTo(HaveOccurred()) - g.Expect(len(td.clusters)).To(Equal(1)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(0)) - g.Expect(s).To(Equal("--join=demo-dm-master-0.demo-dm-master-peer.default.svc:2379,demo-dm-master-1.demo-dm-master-peer.default.svc:2379,demo-dm-master-2.demo-dm-master-peer.default.svc:2379")) + g.Expect(len(td.dmClusters)).To(Equal(1)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(0)) + g.Expect(s).To(Equal("--join=demo-dm-master-0.demo-dm-master-peer.default.svc:8261,demo-dm-master-1.demo-dm-master-peer.default.svc:8261,demo-dm-master-2.demo-dm-master-peer.default.svc:8261")) }, }, { name: "2 clusters, the five ordinal request, get members success", ns: "default", - url: "demo-dm-master-3.demo-dm-master-peer.default.svc:2380", + url: "demo-dm-master-3.demo-dm-master-peer.default.svc:8291", dc: func() *v1alpha1.DMCluster { dc := newDC() dc.Spec.Master.Replicas = 5 @@ -718,16 +718,16 @@ func TestDiscoveryDMDiscovery(t *testing.T) { getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-0.demo-dm-master-peer.default.svc:8261"}, }, { - PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-1.demo-dm-master-peer.default.svc:8261"}, }, { - PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer.default.svc:8261"}, }, { - PeerURLs: []string{"demo-dm-master-3.demo-dm-master-peer.default.svc:2380"}, + ClientURLs: []string{"demo-dm-master-3.demo-dm-master-peer.default.svc:8261"}, }, }, nil }, @@ -746,10 +746,10 @@ func TestDiscoveryDMDiscovery(t *testing.T) { }, expectFn: func(g *GomegaWithT, td *tidbDiscovery, s string, err error) { g.Expect(err).NotTo(HaveOccurred()) - g.Expect(len(td.clusters)).To(Equal(2)) - g.Expect(len(td.clusters["default/demo"].peers)).To(Equal(0)) - g.Expect(len(td.clusters["default/demo-1"].peers)).To(Equal(3)) - g.Expect(s).To(Equal("--join=demo-dm-master-0.demo-dm-master-peer.default.svc:2379,demo-dm-master-1.demo-dm-master-peer.default.svc:2379,demo-dm-master-2.demo-dm-master-peer.default.svc:2379,demo-dm-master-3.demo-dm-master-peer.default.svc:2379")) + g.Expect(len(td.dmClusters)).To(Equal(2)) + g.Expect(len(td.dmClusters["default/demo"].peers)).To(Equal(0)) + g.Expect(len(td.dmClusters["default/demo-1"].peers)).To(Equal(3)) + g.Expect(s).To(Equal("--join=demo-dm-master-0.demo-dm-master-peer.default.svc:8261,demo-dm-master-1.demo-dm-master-peer.default.svc:8261,demo-dm-master-2.demo-dm-master-peer.default.svc:8261,demo-dm-master-3.demo-dm-master-peer.default.svc:8261")) }, }, } From 3ec6c86d742ba2f4523fa03b41b99c2ef7a5741d Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 12 Aug 2020 14:40:54 +0800 Subject: [PATCH 11/37] fix bug --- pkg/discovery/server/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/discovery/server/server.go b/pkg/discovery/server/server.go index f270ff86b9..a9277a5c24 100644 --- a/pkg/discovery/server/server.go +++ b/pkg/discovery/server/server.go @@ -46,7 +46,7 @@ func NewServer(pdControl pdapi.PDControlInterface, masterControl dmapi.MasterCon func (s *server) registerHandlers() { ws := new(restful.WebService) ws.Route(ws.GET("/new/{advertise-peer-url}").To(s.newHandler)) - ws.Route(ws.GET("/newdm/{advertise-peer-url}").To(s.newHandler)) + ws.Route(ws.GET("/newdm/{advertise-peer-url}").To(s.newDMHandler)) s.container.Add(ws) } From 8122c719dda967d27c5538b29ea2050d5a0cca5e Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 18 Aug 2020 16:41:51 +0800 Subject: [PATCH 12/37] support start dm-master and dm-worker in cluster --- cmd/controller-manager/main.go | 3 + docs/api-references/docs.md | 69 +- go.sum | 1 + .../pingcap/v1alpha1/defaulting/dmcluster.go | 70 ++ pkg/apis/pingcap/v1alpha1/dmcluster.go | 117 +++ pkg/apis/pingcap/v1alpha1/group_component.go | 2 +- .../pingcap/v1alpha1/openapi_generated.go | 14 + .../pingcap/v1alpha1/tidbcluster_component.go | 86 +- pkg/apis/pingcap/v1alpha1/types.go | 20 +- .../pingcap/v1alpha1/validation/validation.go | 36 + .../pingcap/v1alpha1/zz_generated.deepcopy.go | 14 +- pkg/controller/controller_utils.go | 29 + .../dmcluster/dm_cluster_condition_updater.go | 70 ++ .../dmcluster/dm_cluster_control.go | 197 +++++ .../dmcluster/dm_cluster_controller.go | 365 +++++++++ pkg/controller/dmcluster_control.go | 81 ++ pkg/controller/dmmaster_control.go | 31 + pkg/dmapi/dmapi.go | 87 +- pkg/dmapi/fake_dmapi.go | 20 + pkg/label/label.go | 25 + pkg/manager/manager.go | 5 + .../member/dm_master_member_manager.go | 770 ++++++++++++++++++ .../member/dm_worker_member_manager.go | 524 ++++++++++++ pkg/manager/member/pd_member_manager.go | 13 +- pkg/manager/member/template.go | 163 ++++ pkg/manager/member/ticdc_member_manager.go | 2 +- pkg/manager/member/tidb_member_manager.go | 2 +- pkg/manager/member/tiflash_member_manager.go | 2 +- pkg/manager/member/tikv_member_manager.go | 2 +- pkg/manager/member/utils.go | 22 +- pkg/manager/member/utils_test.go | 2 +- pkg/util/dmcluster/dmcluster.go | 87 ++ pkg/webhook/pod/pods.go | 2 +- 33 files changed, 2879 insertions(+), 54 deletions(-) create mode 100644 pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go create mode 100644 pkg/controller/dmcluster/dm_cluster_condition_updater.go create mode 100644 pkg/controller/dmcluster/dm_cluster_control.go create mode 100644 pkg/controller/dmcluster/dm_cluster_controller.go create mode 100644 pkg/controller/dmcluster_control.go create mode 100644 pkg/controller/dmmaster_control.go create mode 100644 pkg/manager/member/dm_master_member_manager.go create mode 100644 pkg/manager/member/dm_worker_member_manager.go create mode 100644 pkg/util/dmcluster/dmcluster.go diff --git a/cmd/controller-manager/main.go b/cmd/controller-manager/main.go index 896fb02ace..cde8648142 100644 --- a/cmd/controller-manager/main.go +++ b/cmd/controller-manager/main.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/tidb-operator/pkg/controller/autoscaler" "github.com/pingcap/tidb-operator/pkg/controller/backup" "github.com/pingcap/tidb-operator/pkg/controller/backupschedule" + "github.com/pingcap/tidb-operator/pkg/controller/dmcluster" "github.com/pingcap/tidb-operator/pkg/controller/periodicity" "github.com/pingcap/tidb-operator/pkg/controller/restore" "github.com/pingcap/tidb-operator/pkg/controller/tidbcluster" @@ -184,6 +185,7 @@ func main() { } tcController := tidbcluster.NewController(kubeCli, cli, genericCli, informerFactory, kubeInformerFactory, autoFailover, pdFailoverPeriod, tikvFailoverPeriod, tidbFailoverPeriod, tiflashFailoverPeriod) + dcController := dmcluster.NewController(kubeCli, cli, genericCli, informerFactory, kubeInformerFactory, autoFailover) backupController := backup.NewController(kubeCli, cli, informerFactory, kubeInformerFactory) restoreController := restore.NewController(kubeCli, cli, informerFactory, kubeInformerFactory) bsController := backupschedule.NewController(kubeCli, cli, informerFactory, kubeInformerFactory) @@ -218,6 +220,7 @@ func main() { } klog.Infof("cache of informer factories sync successfully") + go wait.Forever(func() { dcController.Run(workers, ctx.Done()) }, waitDuration) go wait.Forever(func() { backupController.Run(workers, ctx.Done()) }, waitDuration) go wait.Forever(func() { restoreController.Run(workers, ctx.Done()) }, waitDuration) go wait.Forever(func() { bsController.Run(workers, ctx.Done()) }, waitDuration) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 61dc934f69..b22c383b07 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -671,6 +671,19 @@ Optional: Defaults to nil

    + + + + + + + + @@ -4163,6 +4189,10 @@ string
    -metadata
    +Kind
    - -Kubernetes meta/v1.ObjectMeta - +string
    -Refer to the Kubernetes API documentation for the fields of the -metadata field.
    -spec
    +Plural
    - -DMClusterSpec - +string
    -

    Spec defines the behavior of a dm cluster

    -
    -
    - + + + +
    -discovery
    +SpecName
    - -DMDiscoverySpec - +string
    -

    Discovery spec

    -master
    +ShortNames
    - -MasterSpec - +[]string
    -(Optional) -

    dm-master cluster spec

    -worker
    +AdditionalPrinterColums
    - -WorkerSpec - +[]k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1.CustomResourceColumnDefinition
    -(Optional) -

    dm-worker cluster spec

    +

    CrdKinds

    +

    +

    + + + + + + + + + +
    FieldDescription
    -paused
    +KindsString
    -bool +string
    -(Optional) -

    Indicates that the dm cluster is paused and will not be processed by -the controller.

    -version
    +TiDBCluster
    -string + +CrdKind +
    -(Optional) -

    TODO: remove optional after defaulting logic introduced -dm cluster version

    -schedulerName
    +DMCluster
    -string + +CrdKind +
    -

    SchedulerName of DM cluster Pods

    -pvReclaimPolicy
    +Backup
    - -Kubernetes core/v1.PersistentVolumeReclaimPolicy + +CrdKind
    -

    Persistent volume reclaim policy applied to the PVs that consumed by DM cluster

    -imagePullPolicy
    +Restore
    - -Kubernetes core/v1.PullPolicy + +CrdKind
    -

    ImagePullPolicy of DM cluster Pods

    -imagePullSecrets
    +BackupSchedule
    - -[]Kubernetes core/v1.LocalObjectReference + +CrdKind
    -(Optional) -

    ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images.

    -enablePVReclaim
    +TiDBMonitor
    -bool + +CrdKind +
    -(Optional) -

    Whether enable PVC reclaim for orphan PVC left by statefulset scale-in -Optional: Defaults to false

    -tlsCluster
    +TiDBInitializer
    - -TLSCluster + +CrdKind
    -(Optional) -

    Whether enable the TLS connection between DM server components -Optional: Defaults to nil

    -affinity
    +TidbClusterAutoScaler
    - -Kubernetes core/v1.Affinity + +CrdKind
    -(Optional) -

    Affinity of DM cluster Pods

    -nodeSelector
    +TiKVGroup
    -map[string]string + +CrdKind +
    -(Optional) -

    Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively

    -annotations
    +TiDBGroup
    -map[string]string + +CrdKind +
    -(Optional) -

    Base annotations of DM cluster Pods, components may add or override selectors upon this respectively

    +

    CustomMetric

    +

    +(Appears on: +BasicAutoScalerSpec) +

    +

    +

    + + + + + + + + - -
    FieldDescription
    -timezone
    +MetricSpec
    -string + +Kubernetes autoscaling/v2beta2.MetricSpec +
    +

    +(Members of MetricSpec are embedded into this type.) +

    (Optional) -

    Time zone of DM cluster Pods -Optional: Defaults to UTC

    +

    metrics contains the specifications for which to use to calculate the +desired replica count (the maximum replica count across all metrics will +be used). The desired replica count is calculated multiplying the +ratio between the target value and the current value by the current +number of pods. Ergo, metrics used must decrease as the pod count is +increased, and vice-versa. See the individual metric source types for +more information about how each type of metric must respond. +If not set, the auto-scaling won’t happen.

    -tolerations
    +leastStoragePressurePeriodSeconds
    - -[]Kubernetes core/v1.Toleration - +int64
    (Optional) -

    Base tolerations of DM cluster Pods, components may add more tolerations upon this respectively

    -
    +

    LeastStoragePressurePeriodSeconds is only for the storage auto-scaling case when the resource name in the metricSpec +is Storage. When the Storage metrics meet the pressure, Operator would wait +LeastStoragePressurePeriodSeconds duration then able to scale out. +If not set, the default value is 300

    -status
    +leastRemainAvailableStoragePercent
    - -DMClusterStatus - +int64
    -

    Most recently observed status of the dm cluster

    +(Optional) +

    LeastRemainAvailableStoragePercent indicates the least remaining available storage percent compare to +the capacity storage. If the available storage is lower than the capacity storage * LeastRemainAvailableStoragePercent, +the storage status will become storage pressure and ready to be scaled out. +LeastRemainAvailableStoragePercent should between 5 and 90. If not set, the default value would be 10

    (Optional) -

    SSLCA is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn’t be empty

    +

    SSLCA is the path of file that contains list of trusted SSL CAs.

    (Optional) -

    CAPath is the path of file that contains list of trusted SSL CAs. if set, following four settings shouldn’t be empty

    +

    CAPath is the path of file that contains list of trusted SSL CAs.

    (Optional) -

    KeepAliveTTL is the keepalive ttl dm-worker write to dm-master embed etcd +

    KeepAliveTTL is the keepalive TTL when dm-worker writes to the embedded etcd of dm-master Optional: Defaults to 10

    +

    +(Members of ServiceSpec are embedded into this type.) +

    +hostNetwork
    + +bool + +
    +(Optional) +

    Whether Hostnetwork is enabled for DM cluster Pods +Optional: Defaults to false

    +
    affinity
    @@ -685,6 +698,19 @@ Kubernetes core/v1.Affinity
    +priorityClassName
    + +string + +
    +(Optional) +

    PriorityClassName of DM cluster Pods +Optional: Defaults to omitted

    +
    nodeSelector
    map[string]string @@ -4086,8 +4112,8 @@ LeastRemainAvailableStoragePercent should between 5 and 90. If not set, the defa
    type
    - -TidbClusterConditionType + +DMClusterConditionType

    DMClusterConditionType

    +(Appears on: +DMClusterCondition) +

    +

    DMClusterConditionType represents a dm cluster condition value.

    DMClusterSpec

    @@ -4329,6 +4359,19 @@ Optional: Defaults to nil

    +hostNetwork
    + +bool + +
    +(Optional) +

    Whether Hostnetwork is enabled for DM cluster Pods +Optional: Defaults to false

    +
    affinity
    @@ -4343,6 +4386,19 @@ Kubernetes core/v1.Affinity
    +priorityClassName
    + +string + +
    +(Optional) +

    PriorityClassName of DM cluster Pods +Optional: Defaults to omitted

    +
    nodeSelector
    map[string]string @@ -17252,7 +17308,6 @@ string

    TidbClusterConditionType

    (Appears on: -DMClusterCondition, TidbClusterCondition)

    @@ -18667,7 +18722,7 @@ DMSecurityConfig

    -podName
    +name
    string @@ -18677,7 +18732,7 @@ string
    -id
    +addr
    string @@ -18687,7 +18742,7 @@ string
    -state
    +stage
    string @@ -18879,7 +18934,7 @@ Kubernetes apps/v1.StatefulSetStatus
    -workers
    +members
    map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerMember diff --git a/go.sum b/go.sum index 06acb3dc4e..822605b80c 100644 --- a/go.sum +++ b/go.sum @@ -408,6 +408,7 @@ github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkY github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/cadvisor v0.34.0 h1:No7G6U/TasplR9uNqyc5Jj0Bet5VSYsK5xLygOf4pUw= github.com/google/cadvisor v0.34.0/go.mod h1:1nql6U13uTHaLYB8rLS5x9IJc2qT6Xd/Tr1sTX6NE48= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= diff --git a/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go b/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go new file mode 100644 index 0000000000..315af8388a --- /dev/null +++ b/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go @@ -0,0 +1,70 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package defaulting + +import ( + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" +) + +const ( + defaultMasterImage = "pingcap/dm" + defaultWorkerImage = "pingcap/dm" +) + +func SetDMClusterDefault(dc *v1alpha1.DMCluster) { + setDMClusterSpecDefault(dc) + setMasterSpecDefault(dc) + if dc.Spec.Worker != nil { + setWorkerSpecDefault(dc) + } +} + +// setDMClusterSpecDefault is only managed the property under Spec +func setDMClusterSpecDefault(dc *v1alpha1.DMCluster) { + if string(dc.Spec.ImagePullPolicy) == "" { + dc.Spec.ImagePullPolicy = corev1.PullIfNotPresent + } + if dc.Spec.TLSCluster == nil { + dc.Spec.TLSCluster = &v1alpha1.TLSCluster{Enabled: false} + } + if dc.Spec.EnablePVReclaim == nil { + d := false + dc.Spec.EnablePVReclaim = &d + } + retainPVP := corev1.PersistentVolumeReclaimRetain + if dc.Spec.PVReclaimPolicy == nil { + dc.Spec.PVReclaimPolicy = &retainPVP + } +} + +func setMasterSpecDefault(dc *v1alpha1.DMCluster) { + if len(dc.Spec.Version) > 0 || dc.Spec.Master.Version != nil { + if dc.Spec.Master.BaseImage == "" { + dc.Spec.Master.BaseImage = defaultMasterImage + } + } + if dc.Spec.Master.MaxFailoverCount == nil { + dc.Spec.Master.MaxFailoverCount = pointer.Int32Ptr(3) + } +} + +func setWorkerSpecDefault(dc *v1alpha1.DMCluster) { + if len(dc.Spec.Version) > 0 || dc.Spec.Worker.Version != nil { + if dc.Spec.Worker.BaseImage == "" { + dc.Spec.Worker.BaseImage = defaultWorkerImage + } + } +} diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go index 7b8ec54993..8fc4cc5abd 100644 --- a/pkg/apis/pingcap/v1alpha1/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -13,6 +13,13 @@ package v1alpha1 +import ( + "fmt" + "strings" + + "github.com/pingcap/tidb-operator/pkg/label" +) + func (dc *DMCluster) Scheme() string { if dc.IsTLSClusterEnabled() { return "https" @@ -23,3 +30,113 @@ func (dc *DMCluster) Scheme() string { func (dc *DMCluster) IsTLSClusterEnabled() bool { return dc.Spec.TLSCluster != nil && dc.Spec.TLSCluster.Enabled } + +func (dc *DMCluster) MasterAllMembersReady() bool { + if int(dc.MasterStsDesiredReplicas()) != len(dc.Status.Master.Members) { + return false + } + + for _, member := range dc.Status.Master.Members { + if !member.Health { + return false + } + } + return true +} + +func (dc *DMCluster) MasterStsDesiredReplicas() int32 { + return dc.Spec.Master.Replicas + int32(len(dc.Status.Master.FailureMembers)) +} + +func (dc *DMCluster) WorkerStsDesiredReplicas() int32 { + if dc.Spec.Worker == nil { + return 0 + } + + return dc.Spec.Worker.Replicas +} + +func (dc *DMCluster) GetInstanceName() string { + labels := dc.ObjectMeta.GetLabels() + // Keep backward compatibility for helm. + // This introduce a hidden danger that change this label will trigger rolling-update of most of the components + // TODO(aylei): disallow mutation of this label or adding this label with value other than the cluster name in ValidateUpdate() + if inst, ok := labels[label.InstanceLabelKey]; ok { + return inst + } + return dc.Name +} + +func (dc *DMCluster) MasterImage() string { + image := dc.Spec.Master.Image + baseImage := dc.Spec.Master.BaseImage + // base image takes higher priority + if baseImage != "" { + version := dc.Spec.Master.Version + if version == nil { + version = &dc.Spec.Version + } + image = fmt.Sprintf("%s:%s", baseImage, *version) + } + return image +} + +func (dc *DMCluster) WorkerImage() string { + image := dc.Spec.Worker.Image + baseImage := dc.Spec.Worker.BaseImage + // base image takes higher priority + if baseImage != "" { + version := dc.Spec.Worker.Version + if version == nil { + version = &dc.Spec.Version + } + image = fmt.Sprintf("%s:%s", baseImage, *version) + } + return image +} + +func (dc *DMCluster) MasterVersion() string { + image := dc.MasterImage() + colonIdx := strings.LastIndexByte(image, ':') + if colonIdx >= 0 { + return image[colonIdx+1:] + } + + return "latest" +} + +func (dc *DMCluster) MasterUpgrading() bool { + return dc.Status.Master.Phase == UpgradePhase +} + +func (dc *DMCluster) MasterIsAvailable() bool { + lowerLimit := dc.Spec.Master.Replicas/2 + 1 + if int32(len(dc.Status.Master.Members)) < lowerLimit { + return false + } + + var availableNum int32 + for _, masterMember := range dc.Status.Master.Members { + if masterMember.Health { + availableNum++ + } + } + + if availableNum < lowerLimit { + return false + } + + if dc.Status.Master.StatefulSet == nil || dc.Status.Master.StatefulSet.ReadyReplicas < lowerLimit { + return false + } + + return true +} + +func (masterSvc *MasterServiceSpec) GetMasterNodePort() int32 { + masterNodePortNodePort := masterSvc.MasterNodePort + if masterNodePortNodePort == nil { + return 0 + } + return int32(*masterNodePortNodePort) +} diff --git a/pkg/apis/pingcap/v1alpha1/group_component.go b/pkg/apis/pingcap/v1alpha1/group_component.go index 18cc084f39..dea535afe1 100644 --- a/pkg/apis/pingcap/v1alpha1/group_component.go +++ b/pkg/apis/pingcap/v1alpha1/group_component.go @@ -15,7 +15,7 @@ package v1alpha1 // BaseTiKVSpec returns the base spec of TiKV servers func (tg *TiKVGroup) BaseTiKVSpec(tc *TidbCluster) ComponentAccessor { - return &componentAccessorImpl{&tc.Spec, &tg.Spec.ComponentSpec} + return buildTidbClusterComponentAccessor(&tc.Spec, &tg.Spec.ComponentSpec) } func (tg *TiKVGroup) TiKVStsDesiredReplicas() int32 { diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index b7dd484db1..8625a7c9ec 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -1452,12 +1452,26 @@ func schema_pkg_apis_pingcap_v1alpha1_DMClusterSpec(ref common.ReferenceCallback Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TLSCluster"), }, }, + "hostNetwork": { + SchemaProps: spec.SchemaProps{ + Description: "Whether Hostnetwork is enabled for DM cluster Pods Optional: Defaults to false", + Type: []string{"boolean"}, + Format: "", + }, + }, "affinity": { SchemaProps: spec.SchemaProps{ Description: "Affinity of DM cluster Pods", Ref: ref("k8s.io/api/core/v1.Affinity"), }, }, + "priorityClassName": { + SchemaProps: spec.SchemaProps{ + Description: "PriorityClassName of DM cluster Pods Optional: Defaults to omitted", + Type: []string{"string"}, + Format: "", + }, + }, "nodeSelector": { SchemaProps: spec.SchemaProps{ Description: "Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively", diff --git a/pkg/apis/pingcap/v1alpha1/tidbcluster_component.go b/pkg/apis/pingcap/v1alpha1/tidbcluster_component.go index 9aaf3e4b9a..6bad6f7f1c 100644 --- a/pkg/apis/pingcap/v1alpha1/tidbcluster_component.go +++ b/pkg/apis/pingcap/v1alpha1/tidbcluster_component.go @@ -44,8 +44,16 @@ type ComponentAccessor interface { } type componentAccessorImpl struct { - // ClusterSpec is the TidbCluster Spec - ClusterSpec *TidbClusterSpec + imagePullPolicy corev1.PullPolicy + imagePullSecrets []corev1.LocalObjectReference + hostNetwork *bool + affinity *corev1.Affinity + priorityClassName *string + schedulerName string + clusterNodeSelector map[string]string + clusterAnnotations map[string]string + tolerations []corev1.Toleration + configUpdateStrategy ConfigUpdateStrategy // ComponentSpec is the Component Spec ComponentSpec *ComponentSpec @@ -58,7 +66,7 @@ func (a *componentAccessorImpl) PodSecurityContext() *corev1.PodSecurityContext func (a *componentAccessorImpl) ImagePullPolicy() corev1.PullPolicy { pp := a.ComponentSpec.ImagePullPolicy if pp == nil { - return a.ClusterSpec.ImagePullPolicy + return a.imagePullPolicy } return *pp } @@ -66,7 +74,7 @@ func (a *componentAccessorImpl) ImagePullPolicy() corev1.PullPolicy { func (a *componentAccessorImpl) ImagePullSecrets() []corev1.LocalObjectReference { ips := a.ComponentSpec.ImagePullSecrets if ips == nil { - return a.ClusterSpec.ImagePullSecrets + return a.imagePullSecrets } return ips } @@ -74,7 +82,7 @@ func (a *componentAccessorImpl) ImagePullSecrets() []corev1.LocalObjectReference func (a *componentAccessorImpl) HostNetwork() bool { hostNetwork := a.ComponentSpec.HostNetwork if hostNetwork == nil { - hostNetwork = a.ClusterSpec.HostNetwork + hostNetwork = a.hostNetwork } if hostNetwork == nil { return defaultHostNetwork @@ -85,7 +93,7 @@ func (a *componentAccessorImpl) HostNetwork() bool { func (a *componentAccessorImpl) Affinity() *corev1.Affinity { affi := a.ComponentSpec.Affinity if affi == nil { - affi = a.ClusterSpec.Affinity + affi = a.affinity } return affi } @@ -93,7 +101,7 @@ func (a *componentAccessorImpl) Affinity() *corev1.Affinity { func (a *componentAccessorImpl) PriorityClassName() *string { pcn := a.ComponentSpec.PriorityClassName if pcn == nil { - pcn = a.ClusterSpec.PriorityClassName + pcn = a.priorityClassName } return pcn } @@ -101,14 +109,14 @@ func (a *componentAccessorImpl) PriorityClassName() *string { func (a *componentAccessorImpl) SchedulerName() string { pcn := a.ComponentSpec.SchedulerName if pcn == nil { - pcn = &a.ClusterSpec.SchedulerName + pcn = &a.schedulerName } return *pcn } func (a *componentAccessorImpl) NodeSelector() map[string]string { sel := map[string]string{} - for k, v := range a.ClusterSpec.NodeSelector { + for k, v := range a.clusterNodeSelector { sel[k] = v } for k, v := range a.ComponentSpec.NodeSelector { @@ -119,7 +127,7 @@ func (a *componentAccessorImpl) NodeSelector() map[string]string { func (a *componentAccessorImpl) Annotations() map[string]string { anno := map[string]string{} - for k, v := range a.ClusterSpec.Annotations { + for k, v := range a.clusterAnnotations { anno[k] = v } for k, v := range a.ComponentSpec.Annotations { @@ -131,7 +139,7 @@ func (a *componentAccessorImpl) Annotations() map[string]string { func (a *componentAccessorImpl) Tolerations() []corev1.Toleration { tols := a.ComponentSpec.Tolerations if len(tols) == 0 { - tols = a.ClusterSpec.Tolerations + tols = a.tolerations } return tols } @@ -147,7 +155,7 @@ func (a *componentAccessorImpl) DnsPolicy() corev1.DNSPolicy { func (a *componentAccessorImpl) ConfigUpdateStrategy() ConfigUpdateStrategy { strategy := a.ComponentSpec.ConfigUpdateStrategy if strategy == nil { - strategy = &a.ClusterSpec.ConfigUpdateStrategy + strategy = &a.configUpdateStrategy } // defaulting logic will set a default value for configUpdateStrategy field, but if the // object is created in early version without this field being set, we should set a safe default @@ -195,29 +203,63 @@ func (a *componentAccessorImpl) TerminationGracePeriodSeconds() *int64 { return a.ComponentSpec.TerminationGracePeriodSeconds } +func buildTidbClusterComponentAccessor(spec *TidbClusterSpec, componentSpec *ComponentSpec) ComponentAccessor { + return &componentAccessorImpl{ + imagePullPolicy: spec.ImagePullPolicy, + imagePullSecrets: spec.ImagePullSecrets, + hostNetwork: spec.HostNetwork, + affinity: spec.Affinity, + priorityClassName: spec.PriorityClassName, + schedulerName: spec.SchedulerName, + clusterNodeSelector: spec.NodeSelector, + clusterAnnotations: spec.Annotations, + tolerations: spec.Tolerations, + configUpdateStrategy: spec.ConfigUpdateStrategy, + + ComponentSpec: componentSpec, + } +} + +func buildDMClusterComponentAccessor(spec *DMClusterSpec, componentSpec *ComponentSpec) ComponentAccessor { + return &componentAccessorImpl{ + imagePullPolicy: spec.ImagePullPolicy, + imagePullSecrets: spec.ImagePullSecrets, + hostNetwork: spec.HostNetwork, + affinity: spec.Affinity, + priorityClassName: spec.PriorityClassName, + schedulerName: spec.SchedulerName, + clusterNodeSelector: spec.NodeSelector, + clusterAnnotations: spec.Annotations, + tolerations: spec.Tolerations, + configUpdateStrategy: ConfigUpdateStrategyRollingUpdate, + + ComponentSpec: componentSpec, + } +} + // BaseTiDBSpec returns the base spec of TiDB servers func (tc *TidbCluster) BaseTiDBSpec() ComponentAccessor { - return &componentAccessorImpl{&tc.Spec, &tc.Spec.TiDB.ComponentSpec} + return buildTidbClusterComponentAccessor(&tc.Spec, &tc.Spec.TiDB.ComponentSpec) } // BaseTiKVSpec returns the base spec of TiKV servers func (tc *TidbCluster) BaseTiKVSpec() ComponentAccessor { - return &componentAccessorImpl{&tc.Spec, &tc.Spec.TiKV.ComponentSpec} + return buildTidbClusterComponentAccessor(&tc.Spec, &tc.Spec.TiKV.ComponentSpec) } // BaseTiFlashSpec returns the base spec of TiFlash servers func (tc *TidbCluster) BaseTiFlashSpec() ComponentAccessor { - return &componentAccessorImpl{&tc.Spec, &tc.Spec.TiFlash.ComponentSpec} + return buildTidbClusterComponentAccessor(&tc.Spec, &tc.Spec.TiFlash.ComponentSpec) } // BaseTiCDCSpec returns the base spec of TiCDC servers func (tc *TidbCluster) BaseTiCDCSpec() ComponentAccessor { - return &componentAccessorImpl{&tc.Spec, &tc.Spec.TiCDC.ComponentSpec} + return buildTidbClusterComponentAccessor(&tc.Spec, &tc.Spec.TiCDC.ComponentSpec) } // BasePDSpec returns the base spec of PD servers func (tc *TidbCluster) BasePDSpec() ComponentAccessor { - return &componentAccessorImpl{&tc.Spec, &tc.Spec.PD.ComponentSpec} + return buildTidbClusterComponentAccessor(&tc.Spec, &tc.Spec.PD.ComponentSpec) } // BasePumpSpec returns two results: @@ -227,5 +269,13 @@ func (tc *TidbCluster) BasePumpSpec() (ComponentAccessor, bool) { if tc.Spec.Pump == nil { return nil, false } - return &componentAccessorImpl{&tc.Spec, &tc.Spec.Pump.ComponentSpec}, true + return buildTidbClusterComponentAccessor(&tc.Spec, &tc.Spec.Pump.ComponentSpec), true +} + +func (dc *DMCluster) BaseMasterSpec() ComponentAccessor { + return buildDMClusterComponentAccessor(&dc.Spec, &dc.Spec.Master.ComponentSpec) +} + +func (dc *DMCluster) BaseWorkerSpec() ComponentAccessor { + return buildDMClusterComponentAccessor(&dc.Spec, &dc.Spec.Worker.ComponentSpec) } diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 1a36377965..3aa2b1723b 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -1540,10 +1540,20 @@ type DMClusterSpec struct { // +optional TLSCluster *TLSCluster `json:"tlsCluster,omitempty"` + // Whether Hostnetwork is enabled for DM cluster Pods + // Optional: Defaults to false + // +optional + HostNetwork *bool `json:"hostNetwork,omitempty"` + // Affinity of DM cluster Pods // +optional Affinity *corev1.Affinity `json:"affinity,omitempty"` + // PriorityClassName of DM cluster Pods + // Optional: Defaults to omitted + // +optional + PriorityClassName *string `json:"priorityClassName,omitempty"` + // Base node selectors of DM cluster Pods, components may add or override selectors upon this respectively // +optional NodeSelector map[string]string `json:"nodeSelector,omitempty"` @@ -1671,7 +1681,7 @@ type WorkerSpec struct { // DMClusterCondition is dm cluster condition type DMClusterCondition struct { // Type of the condition. - Type TidbClusterConditionType `json:"type"` + Type DMClusterConditionType `json:"type"` // Status of the condition, one of True, False, Unknown. Status corev1.ConditionStatus `json:"status"` // The last time this condition was updated. @@ -1737,14 +1747,14 @@ type WorkerStatus struct { Synced bool `json:"synced,omitempty"` Phase MemberPhase `json:"phase,omitempty"` StatefulSet *apps.StatefulSetStatus `json:"statefulSet,omitempty"` - Workers map[string]WorkerMember `json:"workers,omitempty"` + Members map[string]WorkerMember `json:"members,omitempty"` } // WorkerMember is dm-Worker member status type WorkerMember struct { - PodName string `json:"podName,omitempty"` - ID string `json:"id,omitempty"` - State string `json:"state"` + Name string `json:"name,omitempty"` + Addr string `json:"addr,omitempty"` + Stage string `json:"stage"` // Last time the health transitioned from one to another. LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` } diff --git a/pkg/apis/pingcap/v1alpha1/validation/validation.go b/pkg/apis/pingcap/v1alpha1/validation/validation.go index d9f99bad06..9ca665996a 100644 --- a/pkg/apis/pingcap/v1alpha1/validation/validation.go +++ b/pkg/apis/pingcap/v1alpha1/validation/validation.go @@ -44,6 +44,19 @@ func ValidateTidbCluster(tc *v1alpha1.TidbCluster) field.ErrorList { return allErrs } +// ValidateDMCluster validates a DMCluster, it performs basic validation for all DMClusters despite it is legacy +// or not +func ValidateDMCluster(dc *v1alpha1.DMCluster) field.ErrorList { + allErrs := field.ErrorList{} + // validate metadata + fldPath := field.NewPath("metadata") + // validate metadata/annotations + allErrs = append(allErrs, validateAnnotations(dc.ObjectMeta.Annotations, fldPath.Child("annotations"))...) + // validate spec + allErrs = append(allErrs, validateDMClusterSpec(&dc.Spec, field.NewPath("spec"))...) + return allErrs +} + func ValidateTidbMonitor(monitor *v1alpha1.TidbMonitor) field.ErrorList { allErrs := field.ErrorList{} // validate monitor service @@ -198,6 +211,29 @@ func validatePumpSpec(spec *v1alpha1.PumpSpec, fldPath *field.Path) field.ErrorL return allErrs } +func validateDMClusterSpec(spec *v1alpha1.DMClusterSpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, validateMasterSpec(&spec.Master, fldPath.Child("master"))...) + if spec.Worker != nil { + allErrs = append(allErrs, validateWorkerSpec(spec.Worker, fldPath.Child("worker"))...) + } + return allErrs +} + +func validateMasterSpec(spec *v1alpha1.MasterSpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, validateComponentSpec(&spec.ComponentSpec, fldPath)...) + allErrs = append(allErrs, validateRequestsStorage(spec.ResourceRequirements.Requests, fldPath)...) + return allErrs +} + +func validateWorkerSpec(spec *v1alpha1.WorkerSpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, validateComponentSpec(&spec.ComponentSpec, fldPath)...) + allErrs = append(allErrs, validateRequestsStorage(spec.ResourceRequirements.Requests, fldPath)...) + return allErrs +} + func validateComponentSpec(spec *v1alpha1.ComponentSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} // TODO validate other fields diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index d0a4a5ba92..6f0999cb82 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -944,11 +944,21 @@ func (in *DMClusterSpec) DeepCopyInto(out *DMClusterSpec) { *out = new(TLSCluster) **out = **in } + if in.HostNetwork != nil { + in, out := &in.HostNetwork, &out.HostNetwork + *out = new(bool) + **out = **in + } if in.Affinity != nil { in, out := &in.Affinity, &out.Affinity *out = new(v1.Affinity) (*in).DeepCopyInto(*out) } + if in.PriorityClassName != nil { + in, out := &in.PriorityClassName, &out.PriorityClassName + *out = new(string) + **out = **in + } if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = make(map[string]string, len(*in)) @@ -8095,8 +8105,8 @@ func (in *WorkerStatus) DeepCopyInto(out *WorkerStatus) { *out = new(appsv1.StatefulSetStatus) (*in).DeepCopyInto(*out) } - if in.Workers != nil { - in, out := &in.Workers, &out.Workers + if in.Members != nil { + in, out := &in.Members, &out.Members *out = make(map[string]WorkerMember, len(*in)) for key, val := range *in { (*out)[key] = *val.DeepCopy() diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index 59cb96bcfa..f3b41289c2 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -127,6 +127,20 @@ func GetOwnerRef(tc *v1alpha1.TidbCluster) metav1.OwnerReference { } } +// GetDMOwnerRef returns DMCluster's OwnerReference +func GetDMOwnerRef(dc *v1alpha1.DMCluster) metav1.OwnerReference { + controller := true + blockOwnerDeletion := true + return metav1.OwnerReference{ + APIVersion: ControllerKind.GroupVersion().String(), + Kind: ControllerKind.Kind, + Name: dc.GetName(), + UID: dc.GetUID(), + Controller: &controller, + BlockOwnerDeletion: &blockOwnerDeletion, + } +} + // GetBackupOwnerRef returns Backup's OwnerReference func GetBackupOwnerRef(backup *v1alpha1.Backup) metav1.OwnerReference { controller := true @@ -296,6 +310,21 @@ func DiscoveryMemberName(clusterName string) string { return fmt.Sprintf("%s-discovery", clusterName) } +// DMMasterMemberName returns dm-master member name +func DMMasterMemberName(clusterName string) string { + return fmt.Sprintf("%s-dm-master", clusterName) +} + +// DMMasterPeerMemberName returns dm-master peer service name +func DMMasterPeerMemberName(clusterName string) string { + return fmt.Sprintf("%s-dm-master-peer", clusterName) +} + +// DMWorkerPeerMemberName returns dm-worker peer service name +func DMWorkerPeerMemberName(clusterName string) string { + return fmt.Sprintf("%s-dm-worker-peer", clusterName) +} + // AnnProm adds annotations for prometheus scraping metrics func AnnProm(port int32) map[string]string { return map[string]string{ diff --git a/pkg/controller/dmcluster/dm_cluster_condition_updater.go b/pkg/controller/dmcluster/dm_cluster_condition_updater.go new file mode 100644 index 0000000000..be97cdf9f9 --- /dev/null +++ b/pkg/controller/dmcluster/dm_cluster_condition_updater.go @@ -0,0 +1,70 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmcluster + +import ( + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + utildmcluster "github.com/pingcap/tidb-operator/pkg/util/dmcluster" + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" +) + +// DMClusterConditionUpdater interface that translates cluster state into +// into dm cluster status conditions. +type DMClusterConditionUpdater interface { + Update(*v1alpha1.DMCluster) error +} + +type dmClusterConditionUpdater struct { +} + +var _ DMClusterConditionUpdater = &dmClusterConditionUpdater{} + +func (u *dmClusterConditionUpdater) Update(dc *v1alpha1.DMCluster) error { + u.updateReadyCondition(dc) + // in the future, we may return error when we need to Kubernetes API, etc. + return nil +} + +func allStatefulSetsAreUpToDate(dc *v1alpha1.DMCluster) bool { + isUpToDate := func(status *appsv1.StatefulSetStatus, requireExist bool) bool { + if status == nil { + return !requireExist + } + return status.CurrentRevision == status.UpdateRevision + } + return (isUpToDate(dc.Status.Master.StatefulSet, true)) && + (isUpToDate(dc.Status.Worker.StatefulSet, false)) +} + +func (u *dmClusterConditionUpdater) updateReadyCondition(dc *v1alpha1.DMCluster) { + status := v1.ConditionFalse + reason := "" + message := "" + + switch { + case !allStatefulSetsAreUpToDate(dc): + reason = utildmcluster.StatfulSetNotUpToDate + message = "Statefulset(s) are in progress" + case !dc.MasterAllMembersReady(): + reason = utildmcluster.MasterUnhealthy + message = "dm-master(s) are not healthy" + default: + status = v1.ConditionTrue + reason = utildmcluster.Ready + message = "DM cluster is fully up and running" + } + cond := utildmcluster.NewDMClusterCondition(v1alpha1.DMClusterReady, status, reason, message) + utildmcluster.SetDMClusterCondition(&dc.Status, *cond) +} diff --git a/pkg/controller/dmcluster/dm_cluster_control.go b/pkg/controller/dmcluster/dm_cluster_control.go new file mode 100644 index 0000000000..ea764cf13b --- /dev/null +++ b/pkg/controller/dmcluster/dm_cluster_control.go @@ -0,0 +1,197 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmcluster + +import ( + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1/defaulting" + v1alpha1validation "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1/validation" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/manager" + "github.com/pingcap/tidb-operator/pkg/manager/member" + v1 "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" + errorutils "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/tools/record" + "k8s.io/klog" +) + +// ControlInterface implements the control logic for updating DMClusters and their children StatefulSets. +// It is implemented as an interface to allow for extensions that provide different semantics. +// Currently, there is only one implementation. +type ControlInterface interface { + // UpdateDMCluster implements the control logic for StatefulSet creation, update, and deletion + UpdateDMCluster(*v1alpha1.DMCluster) error +} + +// NewDefaultDMClusterControl returns a new instance of the default implementation DMClusterControlInterface that +// implements the documented semantics for DMClusters. +func NewDefaultDMClusterControl( + dcControl controller.DMClusterControlInterface, + masterMemberManager manager.DMManager, + workerMemberManager manager.DMManager, + //reclaimPolicyManager manager.DMManager, + //metaManager manager.DMManager, + //orphanPodsCleaner member.OrphanPodsCleaner, + pvcCleaner member.PVCCleanerInterface, + //podRestarter member.PodRestarter, + conditionUpdater DMClusterConditionUpdater, + recorder record.EventRecorder) ControlInterface { + return &defaultDMClusterControl{ + dcControl, + masterMemberManager, + workerMemberManager, + //reclaimPolicyManager, + //metaManager, + //orphanPodsCleaner, + pvcCleaner, + //podRestarter, + conditionUpdater, + recorder, + } +} + +type defaultDMClusterControl struct { + dcControl controller.DMClusterControlInterface + masterMemberManager manager.DMManager + workerMemberManager manager.DMManager + //reclaimPolicyManager manager.DMManager + //metaManager manager.DMManager + //orphanPodsCleaner member.OrphanPodsCleaner + pvcCleaner member.PVCCleanerInterface + //podRestarter member.PodRestarter + conditionUpdater DMClusterConditionUpdater + recorder record.EventRecorder +} + +// UpdateStatefulSet executes the core logic loop for a dmcluster. +func (dcc *defaultDMClusterControl) UpdateDMCluster(dc *v1alpha1.DMCluster) error { + dcc.defaulting(dc) + if !dcc.validate(dc) { + return nil // fatal error, no need to retry on invalid object + } + + var errs []error + oldStatus := dc.Status.DeepCopy() + + if err := dcc.updateDMCluster(dc); err != nil { + errs = append(errs, err) + } + + if err := dcc.conditionUpdater.Update(dc); err != nil { + errs = append(errs, err) + } + + if apiequality.Semantic.DeepEqual(&dc.Status, oldStatus) { + return errorutils.NewAggregate(errs) + } + if _, err := dcc.dcControl.UpdateDMCluster(dc.DeepCopy(), &dc.Status, oldStatus); err != nil { + errs = append(errs, err) + } + + return errorutils.NewAggregate(errs) +} + +func (dcc *defaultDMClusterControl) defaulting(dc *v1alpha1.DMCluster) { + defaulting.SetDMClusterDefault(dc) +} + +func (dcc *defaultDMClusterControl) validate(dc *v1alpha1.DMCluster) bool { + errs := v1alpha1validation.ValidateDMCluster(dc) + if len(errs) > 0 { + aggregatedErr := errs.ToAggregate() + klog.Errorf("dm cluster %s/%s is not valid and must be fixed first, aggregated error: %v", dc.GetNamespace(), dc.GetName(), aggregatedErr) + dcc.recorder.Event(dc, v1.EventTypeWarning, "FailedValidation", aggregatedErr.Error()) + return false + } + return true +} + +func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) error { + // TODO: implement reclaimPolicyManager + // syncing all PVs managed by operator's reclaim policy to Retain + // if err := dcc.reclaimPolicyManager.Sync(dc); err != nil { + // return err + // } + + // TODO: add orphanPodsCleaner for dm cluster + // cleaning all orphan pods(pd, tikv or tiflash which don't have a related PVC) managed by operator + // skipReasons, err := dcc.orphanPodsCleaner.Clean(dc) + // if err != nil { + // return err + // } + // if klog.V(10) { + // for podName, reason := range skipReasons { + // klog.Infof("pod %s of cluster %s/%s is skipped, reason %q", podName, dc.Namespace, dc.Name, reason) + // } + // } + + // TODO: restarted pods in dm cluster + // sync all the pods which need to be restarted + // if err := dcc.podRestarter.Sync(dc); err != nil { + // return err + // } + + // works that should do to making the dm-master cluster current state match the desired state: + // - create or update the dm-master service + // - create or update the dm-master headless service + // - create the dm-master statefulset + // - sync dm-master cluster status from dm-master to DMCluster object + // - set two annotations to the first dm-master member: + // - label.Bootstrapping + // - label.Replicas + // - upgrade the dm-master cluster + // - scale out/in the dm-master cluster + // - failover the dm-master cluster + if err := dcc.masterMemberManager.Sync(dc); err != nil { + return err + } + + // works that should do to making the dm-worker cluster current state match the desired state: + // - waiting for the dm-master cluster available(dm-master cluster is in quorum) + // - create or update dm-worker headless service + // - create the dm-worker statefulset + // - sync dm-worker status from dm-master to DMCluster object s + // - upgrade the dm-worker cluster + // - scale out/in the dm-worker cluster + // - failover the dm-worker cluster + if err := dcc.workerMemberManager.Sync(dc); err != nil { + return err + } + + // TODO: syncing labels for dm: syncing the labels from Pod to PVC and PV, these labels include: + // - label.StoreIDLabelKey + // - label.MemberIDLabelKey + // - label.NamespaceLabelKey + // if err := dcc.metaManager.Sync(dc); err != nil { + // return err + // } + + // TODO: clean pods cleaning the pod scheduling annotation for dm cluster + // pvcSkipReasons, err := dcc.pvcCleaner.Clean(dc) + // if err != nil { + // return err + // } + // if klog.V(10) { + // for pvcName, reason := range pvcSkipReasons { + // klog.Infof("pvc %s of cluster %s/%s is skipped, reason %q", pvcName, dc.Namespace, dc.Name, reason) + // } + // } + + // TODO: sync dm cluster attributes + // syncing the some tidbcluster status attributes + // - sync tidbmonitor reference + // return dcc.tidbClusterStatusManager.Sync(dc) + return nil +} diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go new file mode 100644 index 0000000000..e09f0f53f0 --- /dev/null +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -0,0 +1,365 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmcluster + +import ( + "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/juju/errors" + perrors "github.com/pingcap/errors" + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" + informers "github.com/pingcap/tidb-operator/pkg/client/informers/externalversions" + listers "github.com/pingcap/tidb-operator/pkg/client/listers/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/dmapi" + mm "github.com/pingcap/tidb-operator/pkg/manager/member" + corev1 "k8s.io/api/core/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + kubeinformers "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + eventv1 "k8s.io/client-go/kubernetes/typed/core/v1" + appslisters "k8s.io/client-go/listers/apps/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + "k8s.io/kubernetes/pkg/apis/apps" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// Controller controls dmclusters. +type Controller struct { + // kubernetes client interface + kubeClient kubernetes.Interface + // operator client interface + cli versioned.Interface + // control returns an interface capable of syncing a dm cluster. + // Abstracted out for testing. + control ControlInterface + // dcLister is able to list/get dmclusters from a shared informer's store + dcLister listers.DMClusterLister + // dcListerSynced returns true if the dmclusters shared informer has synced at least once + dcListerSynced cache.InformerSynced + // setLister is able to list/get stateful sets from a shared informer's store + setLister appslisters.StatefulSetLister + // setListerSynced returns true if the statefulset shared informer has synced at least once + setListerSynced cache.InformerSynced + // dmclusters that need to be synced. + queue workqueue.RateLimitingInterface +} + +// NewController creates a dm controller. +func NewController( + kubeCli kubernetes.Interface, + cli versioned.Interface, + genericCli client.Client, + informerFactory informers.SharedInformerFactory, + kubeInformerFactory kubeinformers.SharedInformerFactory, + autoFailover bool, +) *Controller { + eventBroadcaster := record.NewBroadcasterWithCorrelatorOptions(record.CorrelatorOptions{QPS: 1}) + eventBroadcaster.StartLogging(klog.V(2).Infof) + eventBroadcaster.StartRecordingToSink(&eventv1.EventSinkImpl{ + Interface: eventv1.New(kubeCli.CoreV1().RESTClient()).Events("")}) + recorder := eventBroadcaster.NewRecorder(v1alpha1.Scheme, corev1.EventSource{Component: "tidb-controller-manager"}) + + dcInformer := informerFactory.Pingcap().V1alpha1().DMClusters() + setInformer := kubeInformerFactory.Apps().V1().StatefulSets() + svcInformer := kubeInformerFactory.Core().V1().Services() + epsInformer := kubeInformerFactory.Core().V1().Endpoints() + pvcInformer := kubeInformerFactory.Core().V1().PersistentVolumeClaims() + pvInformer := kubeInformerFactory.Core().V1().PersistentVolumes() + podInformer := kubeInformerFactory.Core().V1().Pods() + //nodeInformer := kubeInformerFactory.Core().V1().Nodes() + //secretInformer := kubeInformerFactory.Core().V1().Secrets() + + dcControl := controller.NewRealDMClusterControl(cli, dcInformer.Lister(), recorder) + masterControl := dmapi.NewDefaultMasterControl(kubeCli) + setControl := controller.NewRealStatefuSetControl(kubeCli, setInformer.Lister(), recorder) + svcControl := controller.NewRealServiceControl(kubeCli, svcInformer.Lister(), recorder) + pvControl := controller.NewRealPVControl(kubeCli, pvcInformer.Lister(), pvInformer.Lister(), recorder) + pvcControl := controller.NewRealPVCControl(kubeCli, recorder, pvcInformer.Lister()) + // podControl := controller.NewRealPodControl(kubeCli, masterControl, podInformer.Lister(), recorder) + typedControl := controller.NewTypedControl(controller.NewRealGenericControl(genericCli, recorder)) + + dcc := &Controller{ + kubeClient: kubeCli, + cli: cli, + control: NewDefaultDMClusterControl( + dcControl, + mm.NewMasterMemberManager( + masterControl, + setControl, + svcControl, + // podControl, + typedControl, + setInformer.Lister(), + svcInformer.Lister(), + podInformer.Lister(), + epsInformer.Lister(), + pvcInformer.Lister(), + ), + mm.NewWorkerMemberManager( + masterControl, + setControl, + svcControl, + typedControl, + setInformer.Lister(), + svcInformer.Lister(), + podInformer.Lister(), + ), + //meta.NewReclaimPolicyManager( + // pvcInformer.Lister(), + // pvInformer.Lister(), + // pvControl, + //), + //meta.NewMetaManager( + // pvcInformer.Lister(), + // pvcControl, + // pvInformer.Lister(), + // pvControl, + // podInformer.Lister(), + // podControl, + //), + //mm.NewOrphanPodsCleaner( + // podInformer.Lister(), + // podControl, + // pvcInformer.Lister(), + // kubeCli, + //), + mm.NewRealPVCCleaner( + kubeCli, + podInformer.Lister(), + pvcControl, + pvcInformer.Lister(), + pvInformer.Lister(), + pvControl, + ), + //mm.NewDMClusterStatusManager(kubeCli, cli, scalerInformer.Lister(), tikvGroupInformer.Lister()), + //podRestarter, + &dmClusterConditionUpdater{}, + recorder, + ), + queue: workqueue.NewNamedRateLimitingQueue( + workqueue.DefaultControllerRateLimiter(), + "dmcluster", + ), + } + + dcInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: dcc.enqueueDMCluster, + UpdateFunc: func(old, cur interface{}) { + dcc.enqueueDMCluster(cur) + }, + DeleteFunc: dcc.enqueueDMCluster, + }) + dcc.dcLister = dcInformer.Lister() + dcc.dcListerSynced = dcInformer.Informer().HasSynced + + setInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: dcc.addStatefulSet, + UpdateFunc: func(old, cur interface{}) { + dcc.updateStatefuSet(old, cur) + }, + DeleteFunc: dcc.deleteStatefulSet, + }) + dcc.setLister = setInformer.Lister() + dcc.setListerSynced = setInformer.Informer().HasSynced + + return dcc +} + +// Run runs the dmcluster controller. +func (dcc *Controller) Run(workers int, stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer dcc.queue.ShutDown() + + klog.Info("Starting dmcluster controller") + defer klog.Info("Shutting down dmcluster controller") + + for i := 0; i < workers; i++ { + go wait.Until(dcc.worker, time.Second, stopCh) + } + + <-stopCh +} + +// worker runs a worker goroutine that invokes processNextWorkItem until the the controller's queue is closed +func (dcc *Controller) worker() { + for dcc.processNextWorkItem() { + } +} + +// processNextWorkItem dequeues items, processes them, and marks them done. It enforces that the syncHandler is never +// invoked concurrently with the same key. +func (dcc *Controller) processNextWorkItem() bool { + key, quit := dcc.queue.Get() + if quit { + return false + } + defer dcc.queue.Done(key) + if err := dcc.sync(key.(string)); err != nil { + if perrors.Find(err, controller.IsRequeueError) != nil { + klog.Infof("DMCluster: %v, still need sync: %v, requeuing", key.(string), err) + } else { + utilruntime.HandleError(fmt.Errorf("DMCluster: %v, sync failed %v, requeuing", key.(string), err)) + } + dcc.queue.AddRateLimited(key) + } else { + dcc.queue.Forget(key) + } + return true +} + +// sync syncs the given dmcluster. +func (dcc *Controller) sync(key string) error { + startTime := time.Now() + defer func() { + klog.V(4).Infof("Finished syncing DMCluster %q (%v)", key, time.Since(startTime)) + }() + + ns, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + return err + } + dc, err := dcc.dcLister.DMClusters(ns).Get(name) + if errors.IsNotFound(err) { + klog.Infof("DMCluster has been deleted %v", key) + return nil + } + if err != nil { + return err + } + + return dcc.syncDMCluster(dc.DeepCopy()) +} + +func (dcc *Controller) syncDMCluster(dc *v1alpha1.DMCluster) error { + return dcc.control.UpdateDMCluster(dc) +} + +// enqueueDMCluster enqueues the given dmcluster in the work queue. +func (dcc *Controller) enqueueDMCluster(obj interface{}) { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err != nil { + utilruntime.HandleError(fmt.Errorf("Cound't get key for object %+v: %v", obj, err)) + return + } + dcc.queue.Add(key) +} + +// addStatefulSet adds the dmcluster for the statefulset to the sync queue +func (dcc *Controller) addStatefulSet(obj interface{}) { + set := obj.(*apps.StatefulSet) + ns := set.GetNamespace() + setName := set.GetName() + + if set.DeletionTimestamp != nil { + // on a restart of the controller manager, it's possible a new statefulset shows up in a state that + // is already pending deletion. Prevent the statefulset from being a creation observation. + dcc.deleteStatefulSet(set) + return + } + + // If it has a ControllerRef, that's all that matters. + dc := dcc.resolveDMClusterFromSet(ns, set) + if dc == nil { + return + } + klog.V(4).Infof("StatefulSet %s/%s created, DMCluster: %s/%s", ns, setName, ns, dc.Name) + dcc.enqueueDMCluster(dc) +} + +// updateStatefuSet adds the dmcluster for the current and old statefulsets to the sync queue. +func (dcc *Controller) updateStatefuSet(old, cur interface{}) { + curSet := cur.(*apps.StatefulSet) + oldSet := old.(*apps.StatefulSet) + ns := curSet.GetNamespace() + setName := curSet.GetName() + if curSet.ResourceVersion == oldSet.ResourceVersion { + // Periodic resync will send update events for all known statefulsets. + // Two different versions of the same statefulset will always have different RVs. + return + } + + // If it has a ControllerRef, that's all that matters. + dc := dcc.resolveDMClusterFromSet(ns, curSet) + if dc == nil { + return + } + klog.V(4).Infof("StatefulSet %s/%s updated, DMCluster: %s/%s", ns, setName, ns, dc.Name) + dcc.enqueueDMCluster(dc) +} + +// deleteStatefulSet enqueues the dmcluster for the statefulset accounting for deletion tombstones. +func (dcc *Controller) deleteStatefulSet(obj interface{}) { + set, ok := obj.(*apps.StatefulSet) + ns := set.GetNamespace() + setName := set.GetName() + + // When a delete is dropped, the relist will notice a statefuset in the store not + // in the list, leading to the insertion of a tombstone object which contains + // the deleted key/value. + if !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + utilruntime.HandleError(fmt.Errorf("couldn't get object from tombstone %+v", obj)) + return + } + set, ok = tombstone.Obj.(*apps.StatefulSet) + if !ok { + utilruntime.HandleError(fmt.Errorf("tombstone contained object that is not a statefuset %+v", obj)) + return + } + } + + // If it has a DMCluster, that's all that matters. + dc := dcc.resolveDMClusterFromSet(ns, set) + if dc == nil { + return + } + klog.V(4).Infof("StatefulSet %s/%s deleted through %v.", ns, setName, utilruntime.GetCaller()) + dcc.enqueueDMCluster(dc) +} + +// resolveDMClusterFromSet returns the DMCluster by a StatefulSet, +// or nil if the StatefulSet could not be resolved to a matching DMCluster +// of the correct Kind. +func (dcc *Controller) resolveDMClusterFromSet(namespace string, set *apps.StatefulSet) *v1alpha1.DMCluster { + controllerRef := metav1.GetControllerOf(set) + if controllerRef == nil { + return nil + } + + // We can't look up by UID, so look up by Name and then verify UID. + // Don't even try to look up by Name if it's the wrong Kind. + if controllerRef.Kind != controller.ControllerKind.Kind { + return nil + } + dc, err := dcc.dcLister.DMClusters(namespace).Get(controllerRef.Name) + if err != nil { + return nil + } + if dc.UID != controllerRef.UID { + // The controller we found with this Name is not the same one that the + // ControllerRef points to. + return nil + } + return dc +} diff --git a/pkg/controller/dmcluster_control.go b/pkg/controller/dmcluster_control.go new file mode 100644 index 0000000000..1901d51d87 --- /dev/null +++ b/pkg/controller/dmcluster_control.go @@ -0,0 +1,81 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + "fmt" + + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" + listers "github.com/pingcap/tidb-operator/pkg/client/listers/pingcap/v1alpha1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/retry" + "k8s.io/klog" +) + +// DMClusterControlInterface manages DMClusters +type DMClusterControlInterface interface { + UpdateDMCluster(*v1alpha1.DMCluster, *v1alpha1.DMClusterStatus, *v1alpha1.DMClusterStatus) (*v1alpha1.DMCluster, error) +} + +type realDMClusterControl struct { + cli versioned.Interface + dcLister listers.DMClusterLister + recorder record.EventRecorder +} + +// NewRealDMClusterControl creates a new DMClusterControlInterface +func NewRealDMClusterControl(cli versioned.Interface, + dcLister listers.DMClusterLister, + recorder record.EventRecorder) DMClusterControlInterface { + return &realDMClusterControl{ + cli, + dcLister, + recorder, + } +} + +func (rdc *realDMClusterControl) UpdateDMCluster(dc *v1alpha1.DMCluster, newStatus *v1alpha1.DMClusterStatus, oldStatus *v1alpha1.DMClusterStatus) (*v1alpha1.DMCluster, error) { + ns := dc.GetNamespace() + dcName := dc.GetName() + + status := dc.Status.DeepCopy() + var updateDC *v1alpha1.DMCluster + + // don't wait due to limited number of clients, but backoff after the default number of steps + err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + var updateErr error + updateDC, updateErr = rdc.cli.PingcapV1alpha1().DMClusters(ns).Update(dc) + if updateErr == nil { + klog.Infof("DMCluster: [%s/%s] updated successfully", ns, dcName) + return nil + } + klog.V(4).Infof("failed to update DMCluster: [%s/%s], error: %v", ns, dcName, updateErr) + + if updated, err := rdc.dcLister.DMClusters(ns).Get(dcName); err == nil { + // make a copy so we don't mutate the shared cache + dc = updated.DeepCopy() + dc.Status = *status + } else { + utilruntime.HandleError(fmt.Errorf("error getting updated DMCluster %s/%s from lister: %v", ns, dcName, err)) + } + + return updateErr + }) + if err != nil { + klog.Errorf("failed to update DMCluster: [%s/%s], error: %v", ns, dcName, err) + } + return updateDC, err +} diff --git a/pkg/controller/dmmaster_control.go b/pkg/controller/dmmaster_control.go new file mode 100644 index 0000000000..6e39d5af6d --- /dev/null +++ b/pkg/controller/dmmaster_control.go @@ -0,0 +1,31 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/dmapi" +) + +// GetMasterClient gets the master client from the DMCluster +func GetMasterClient(dmControl dmapi.MasterControlInterface, dc *v1alpha1.DMCluster) dmapi.MasterClient { + return dmControl.GetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), dc.IsTLSClusterEnabled()) +} + +// NewFakeMasterClient creates a fake master client that is set as the master client +func NewFakeMasterClient(dmControl *dmapi.FakeMasterControl, dc *v1alpha1.DMCluster) *dmapi.FakeMasterClient { + masterClient := dmapi.NewFakeMasterClient() + dmControl.SetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), masterClient) + return masterClient +} diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index 19abdf8d79..2b8dfdf313 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -31,6 +31,8 @@ const ( type MasterClient interface { // GetMasters returns all master members from cluster GetMasters() ([]*MastersInfo, error) + GetWorkers() ([]*WorkersInfo, error) + GetLeader() (MembersLeader, error) } var ( @@ -50,19 +52,54 @@ type MastersInfo struct { ClientURLs []string `json:"clientURLs,omitempty"` } +type WorkersInfo struct { + Name string `json:"name,omitempty"` + Addr string `json:"addr,omitempty"` + Stage string `json:"stage,omitempty"` + Source string `json:"source,omitempty"` +} + type MembersMaster struct { Msg string `json:"msg,omitempty"` Masters []*MastersInfo `json:"masters,omitempty"` } +type MembersWorker struct { + Msg string `json:"msg,omitempty"` + Workers []*WorkersInfo `json:"workers,omitempty"` +} + +type MembersLeader struct { + Msg string `json:"msg,omitempty"` + Name string `json:"name,omitempty"` + Addr string `json:"addr,omitempty"` +} + type ListMemberMaster struct { MembersMaster `json:"master,omitempty"` } +type ListMemberWorker struct { + MembersWorker `json:"worker,omitempty"` +} + +type ListMemberLeader struct { + MembersLeader `json:"leader,omitempty"` +} + type MastersResp struct { ListMemberRespHeader `json:",inline"` + ListMemberResp []*ListMemberMaster `json:"members,omitempty"` +} - ListMemberResp []*ListMemberMaster `json:"members,omitempty"` +type WorkerResp struct { + ListMemberRespHeader `json:",inline"` + ListMemberResp []*ListMemberWorker `json:"members,omitempty"` +} + +type LeaderResp struct { + ListMemberRespHeader `json:",inline"` + ListMemberResp []*ListMemberLeader `json:"members,omitempty"` } // masterClient is default implementation of MasterClient @@ -84,15 +121,59 @@ func (mc *masterClient) GetMasters() ([]*MastersInfo, error) { return nil, err } if !listMemberResp.Result { - return nil, fmt.Errorf("unable to list members info from dm-master, err: %s", listMemberResp.Msg) + return nil, fmt.Errorf("unable to list masters info, err: %s", listMemberResp.Msg) } if len(listMemberResp.ListMemberResp) != 1 { - return nil, fmt.Errorf("invalid list members resp: %s", body) + return nil, fmt.Errorf("invalid list masters resp: %s", body) } return listMemberResp.ListMemberResp[0].Masters, nil } +func (mc *masterClient) GetWorkers() ([]*WorkersInfo, error) { + query := "?worker=true" + apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) + body, err := httputil.GetBodyOK(mc.httpClient, apiURL) + if err != nil { + return nil, err + } + listMemberResp := &WorkerResp{} + err = json.Unmarshal(body, listMemberResp) + if err != nil { + return nil, err + } + if !listMemberResp.Result { + return nil, fmt.Errorf("unable to list workers info, err: %s", listMemberResp.Msg) + } + if len(listMemberResp.ListMemberResp) != 1 { + return nil, fmt.Errorf("invalid list workers resp: %s", body) + } + + return listMemberResp.ListMemberResp[0].Workers, nil +} + +func (mc *masterClient) GetLeader() (MembersLeader, error) { + query := "?leader=true" + apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) + body, err := httputil.GetBodyOK(mc.httpClient, apiURL) + if err != nil { + return MembersLeader{}, err + } + listMemberResp := &LeaderResp{} + err = json.Unmarshal(body, listMemberResp) + if err != nil { + return MembersLeader{}, err + } + if !listMemberResp.Result { + return MembersLeader{}, fmt.Errorf("unable to get leader info, err: %s", listMemberResp.Msg) + } + if len(listMemberResp.ListMemberResp) != 1 { + return MembersLeader{}, fmt.Errorf("invalid list leader resp: %s", body) + } + + return listMemberResp.ListMemberResp[0].MembersLeader, nil +} + // NewMasterClient returns a new MasterClient func NewMasterClient(url string, timeout time.Duration, tlsConfig *tls.Config) MasterClient { var disableKeepalive bool diff --git a/pkg/dmapi/fake_dmapi.go b/pkg/dmapi/fake_dmapi.go index 9af8ee2c4f..deb20a29a4 100644 --- a/pkg/dmapi/fake_dmapi.go +++ b/pkg/dmapi/fake_dmapi.go @@ -21,6 +21,8 @@ type ActionType string const ( GetMastersActionType ActionType = "GetMasters" + GetWorkersActionType ActionType = "GetWorkers" + GetLeaderActionType ActionType = "GetLeader" ) type NotFoundReaction struct { @@ -72,3 +74,21 @@ func (pc *FakeMasterClient) GetMasters() ([]*MastersInfo, error) { } return result.([]*MastersInfo), nil } + +func (pc *FakeMasterClient) GetWorkers() ([]*WorkersInfo, error) { + action := &Action{} + result, err := pc.fakeAPI(GetWorkersActionType, action) + if err != nil { + return nil, err + } + return result.([]*WorkersInfo), nil +} + +func (pc *FakeMasterClient) GetLeader() (MembersLeader, error) { + action := &Action{} + result, err := pc.fakeAPI(GetLeaderActionType, action) + if err != nil { + return MembersLeader{}, err + } + return result.(MembersLeader), nil +} diff --git a/pkg/label/label.go b/pkg/label/label.go index 57ea057ce3..b110e9a9f0 100644 --- a/pkg/label/label.go +++ b/pkg/label/label.go @@ -104,6 +104,8 @@ const ( AnnTiKVDeleteSlots = "tikv.tidb.pingcap.com/delete-slots" // TiFlashDeleteSlots is annotation key of tiflash delete slots. AnnTiFlashDeleteSlots = "tiflash.tidb.pingcap.com/delete-slots" + // DMMasterDeleteSlots is annotation key of dm-master delete slots. + AnnDMMasterDeleteSlots = "dm-master.tidb.pingcap.com/delete-slots" // AnnTiDBLastAutoScalingTimestamp is annotation key of tidbcluster to indicate the last timestamp for tidb auto-scaling AnnTiDBLastAutoScalingTimestamp = "tidb.tidb.pingcap.com/last-autoscaling-timestamp" @@ -149,6 +151,11 @@ const ( InitJobLabelVal string = "initializer" // TiDBOperator is ManagedByLabelKey label value TiDBOperator string = "tidb-operator" + + // DMMasterLabelVal is dm-master label value + DMMasterLabelVal string = "dm-master" + // DMWorkerLabelVal is dm-worker label value + DMWorkerLabelVal string = "dm-worker" ) // Label is the label field in metadata @@ -310,6 +317,24 @@ func (l Label) Pump() Label { return l } +func (l Label) DMMaster() Label { + l.Component(DMMasterLabelVal) + return l +} + +func (l Label) DMWorker() Label { + l.Component(DMWorkerLabelVal) + return l +} + +func (l Label) IsDMMaster() bool { + return l[ComponentLabelKey] == DMMasterLabelVal +} + +func (l Label) IsDMWorker() bool { + return l[ComponentLabelKey] == DMWorkerLabelVal +} + func (l Label) IsPump() bool { return l[ComponentLabelKey] == PumpLabelVal } diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go index e009fa05a8..3cd6df597f 100644 --- a/pkg/manager/manager.go +++ b/pkg/manager/manager.go @@ -28,3 +28,8 @@ type TiDBGroupManager interface { type TiKVGroupManager interface { SyncTiKVGroup(tg *v1alpha1.TiKVGroup, tc *v1alpha1.TidbCluster) error } + +type DMManager interface { + // Sync implements the logic for syncing dmcluster. + Sync(*v1alpha1.DMCluster) error +} diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go new file mode 100644 index 0000000000..0422687f70 --- /dev/null +++ b/pkg/manager/member/dm_master_member_manager.go @@ -0,0 +1,770 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package member + +import ( + "fmt" + "path" + "path/filepath" + "strconv" + "strings" + + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/dmapi" + "github.com/pingcap/tidb-operator/pkg/label" + "github.com/pingcap/tidb-operator/pkg/manager" + "github.com/pingcap/tidb-operator/pkg/util" + + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + v1 "k8s.io/client-go/listers/apps/v1" + corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/klog" + "k8s.io/utils/pointer" +) + +const ( + // dmMasterDataVolumeMountPath is the mount path for dm-master data volume + dmMasterDataVolumeMountPath = "/var/lib/dm-master" + // dmMasterClusterCertPath is where the cert for inter-cluster communication stored (if any) + dmMasterClusterCertPath = "/var/lib/dm-master-tls" +) + +type masterMemberManager struct { + masterControl dmapi.MasterControlInterface + setControl controller.StatefulSetControlInterface + svcControl controller.ServiceControlInterface + //podControl controller.PodControlInterface + typedControl controller.TypedControlInterface + setLister v1.StatefulSetLister + svcLister corelisters.ServiceLister + podLister corelisters.PodLister + epsLister corelisters.EndpointsLister + pvcLister corelisters.PersistentVolumeClaimLister +} + +// NewMasterMemberManager returns a *masterMemberManager +func NewMasterMemberManager(masterControl dmapi.MasterControlInterface, + setControl controller.StatefulSetControlInterface, + svcControl controller.ServiceControlInterface, + //podControl controller.PodControlInterface, + typedControl controller.TypedControlInterface, + setLister v1.StatefulSetLister, + svcLister corelisters.ServiceLister, + podLister corelisters.PodLister, + epsLister corelisters.EndpointsLister, + pvcLister corelisters.PersistentVolumeClaimLister) manager.DMManager { + return &masterMemberManager{ + masterControl, + setControl, + svcControl, + //podControl, + typedControl, + setLister, + svcLister, + podLister, + epsLister, + pvcLister} +} + +func (mmm *masterMemberManager) Sync(dc *v1alpha1.DMCluster) error { + clusterVersionLT2, err := clusterVersionLessThan2(dc.MasterVersion()) + if err != nil { + klog.V(4).Infof("cluster version: %s is not semantic versioning compatible", dc.MasterVersion()) + } else if clusterVersionLT2 { + return fmt.Errorf("dm-operator only supports to deploy dm-2.0") + } + + // Sync dm-master Service + if err := mmm.syncMasterServiceForDMCluster(dc); err != nil { + return err + } + + // Sync dm-master Headless Service + if err := mmm.syncMasterHeadlessServiceForDMCluster(dc); err != nil { + return err + } + + // Sync dm-master StatefulSet + return mmm.syncMasterStatefulSetForDMCluster(dc) +} + +func (mmm *masterMemberManager) syncMasterServiceForDMCluster(dc *v1alpha1.DMCluster) error { + if dc.Spec.Paused { + klog.V(4).Infof("dm cluster %s/%s is paused, skip syncing for dm-master service", dc.GetNamespace(), dc.GetName()) + return nil + } + + ns := dc.GetNamespace() + dcName := dc.GetName() + + newSvc := mmm.getNewMasterServiceForDMCluster(dc) + oldSvcTmp, err := mmm.svcLister.Services(ns).Get(controller.DMMasterMemberName(dcName)) + if errors.IsNotFound(err) { + err = controller.SetServiceLastAppliedConfigAnnotation(newSvc) + if err != nil { + return err + } + return mmm.svcControl.CreateService(dc, newSvc) + } + if err != nil { + return fmt.Errorf("syncMasterServiceForDMCluster: failed to get svc %s for cluster %s/%s, error: %s", controller.DMMasterMemberName(dcName), ns, dcName, err) + } + + oldSvc := oldSvcTmp.DeepCopy() + util.RetainManagedFields(newSvc, oldSvc) + + equal, err := controller.ServiceEqual(newSvc, oldSvc) + if err != nil { + return err + } + annoEqual := util.IsSubMapOf(newSvc.Annotations, oldSvc.Annotations) + isOrphan := metav1.GetControllerOf(oldSvc) == nil + + if !equal || !annoEqual || isOrphan { + svc := *oldSvc + svc.Spec = newSvc.Spec + err = controller.SetServiceLastAppliedConfigAnnotation(&svc) + if err != nil { + return err + } + svc.Spec.ClusterIP = oldSvc.Spec.ClusterIP + for k, v := range newSvc.Annotations { + svc.Annotations[k] = v + } + // also override labels when adopt orphan + if isOrphan { + svc.OwnerReferences = newSvc.OwnerReferences + svc.Labels = newSvc.Labels + } + _, err = mmm.svcControl.UpdateService(dc, &svc) + return err + } + + return nil +} + +func (mmm *masterMemberManager) syncMasterHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) error { + if dc.Spec.Paused { + klog.V(4).Infof("dm cluster %s/%s is paused, skip syncing for dm-master headless service", dc.GetNamespace(), dc.GetName()) + return nil + } + + ns := dc.GetNamespace() + dcName := dc.GetName() + + newSvc := getNewMasterHeadlessServiceForDMCluster(dc) + oldSvc, err := mmm.svcLister.Services(ns).Get(controller.DMMasterPeerMemberName(dcName)) + if errors.IsNotFound(err) { + err = controller.SetServiceLastAppliedConfigAnnotation(newSvc) + if err != nil { + return err + } + return mmm.svcControl.CreateService(dc, newSvc) + } + if err != nil { + return fmt.Errorf("syncMasterHeadlessServiceForDMCluster: failed to get svc %s for cluster %s/%s, error: %s", controller.DMMasterPeerMemberName(dcName), ns, dcName, err) + } + + equal, err := controller.ServiceEqual(newSvc, oldSvc) + if err != nil { + return err + } + if !equal { + svc := *oldSvc + svc.Spec = newSvc.Spec + err = controller.SetServiceLastAppliedConfigAnnotation(&svc) + if err != nil { + return err + } + _, err = mmm.svcControl.UpdateService(dc, &svc) + return err + } + + return nil +} + +func (mmm *masterMemberManager) syncMasterStatefulSetForDMCluster(dc *v1alpha1.DMCluster) error { + ns := dc.GetNamespace() + dcName := dc.GetName() + + oldMasterSetTmp, err := mmm.setLister.StatefulSets(ns).Get(controller.DMMasterMemberName(dcName)) + if err != nil && !errors.IsNotFound(err) { + return fmt.Errorf("syncMasterStatefulSetForDMCluster: fail to get sts %s for cluster %s/%s, error: %s", controller.DMMasterMemberName(dcName), ns, dcName, err) + } + + setNotExist := errors.IsNotFound(err) + oldMasterSet := oldMasterSetTmp.DeepCopy() + + if err := mmm.syncDMClusterStatus(dc, oldMasterSet); err != nil { + klog.Errorf("failed to sync DMCluster: [%s/%s]'s status, error: %v", ns, dcName, err) + } + + if dc.Spec.Paused { + klog.V(4).Infof("dm cluster %s/%s is paused, skip syncing for dm-master statefulset", dc.GetNamespace(), dc.GetName()) + return nil + } + + cm, err := mmm.syncMasterConfigMap(dc, oldMasterSet) + if err != nil { + return err + } + newMasterSet, err := getNewMasterSetForDMCluster(dc, cm) + if err != nil { + return err + } + if setNotExist { + err = SetStatefulSetLastAppliedConfigAnnotation(newMasterSet) + if err != nil { + return err + } + if err := mmm.setControl.CreateStatefulSet(dc, newMasterSet); err != nil { + return err + } + dc.Status.Master.StatefulSet = &apps.StatefulSetStatus{} + return controller.RequeueErrorf("DMCluster: [%s/%s], waiting for dm-master cluster running", ns, dcName) + } + + if !dc.Status.Master.Synced { + force := NeedForceUpgrade(dc.Annotations) + if force { + dc.Status.Master.Phase = v1alpha1.UpgradePhase + setUpgradePartition(newMasterSet, 0) + errSTS := updateStatefulSet(mmm.setControl, dc, newMasterSet, oldMasterSet) + return controller.RequeueErrorf("dmcluster: [%s/%s]'s dm-master needs force upgrade, %v", ns, dcName, errSTS) + } + } + + // TODO: dm add rolling update later + // if !templateEqual(newMasterSet, oldMasterSet) || dc.Status.Master.Phase == v1alpha1.UpgradePhase { + // if err := mmm.masterUpgrader.Upgrade(dc, oldMasterSet, newMasterSet); err != nil { + // return err + // } + // } + + // TODO: dm add scaler + //if err := mmm.masterScaler.Scale(dc, oldMasterSet, newMasterSet); err != nil { + // return err + //} + + // TODO: dm add auto failover + // if mmm.autoFailover { + // if mmm.shouldRecover(tc) { + // mmm.masterFailover.Recover(tc) + // } else if dc.MasterAllPodsStarted() && !dc.MasterAllMembersReady() || tc.MasterAutoFailovering() { + // if err := mmm.masterFailover.Failover(tc); err != nil { + // return err + // } + // } + // } + + return updateStatefulSet(mmm.setControl, dc, newMasterSet, oldMasterSet) +} + +func (mmm *masterMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set *apps.StatefulSet) error { + if set == nil { + // skip if not created yet + return nil + } + + ns := dc.GetNamespace() + dcName := dc.GetName() + + dc.Status.Master.StatefulSet = &set.Status + + upgrading, err := mmm.masterStatefulSetIsUpgrading(set, dc) + if err != nil { + return err + } + if upgrading { + dc.Status.Master.Phase = v1alpha1.UpgradePhase + } else if dc.MasterStsDesiredReplicas() != *set.Spec.Replicas { + dc.Status.Master.Phase = v1alpha1.ScalePhase + } else { + dc.Status.Master.Phase = v1alpha1.NormalPhase + } + + dmClient := controller.GetMasterClient(mmm.masterControl, dc) + + mastersInfo, err := dmClient.GetMasters() + if err != nil { + dc.Status.Master.Synced = false + // get endpoints info + eps, epErr := mmm.epsLister.Endpoints(ns).Get(controller.DMMasterMemberName(dcName)) + if epErr != nil { + return fmt.Errorf("syncDMClusterStatus: failed to get endpoints %s for cluster %s/%s, err: %s, epErr %s", controller.DMMasterMemberName(dcName), ns, dcName, err, epErr) + } + // dm-master service has no endpoints + if eps != nil && len(eps.Subsets) == 0 { + return fmt.Errorf("%s, service %s/%s has no endpoints", err, ns, controller.DMMasterMemberName(dcName)) + } + return err + } + + leader, err := dmClient.GetLeader() + if err != nil { + dc.Status.Master.Synced = false + return err + } + masterStatus := map[string]v1alpha1.MasterMember{} + for _, master := range mastersInfo { + id := master.MemberID + memberID := strconv.FormatUint(id, 10) + var clientURL string + if len(master.ClientURLs) > 0 { + clientURL = master.ClientURLs[0] + } + name := master.Name + if len(name) == 0 { + klog.Warningf("dm-master member: [%d] doesn't have a name, and can't get it from clientUrls: [%s], dm-master Info: [%v] in [%s/%s]", + id, master.ClientURLs, master, ns, dcName) + continue + } + + status := v1alpha1.MasterMember{ + Name: name, + ID: memberID, + ClientURL: clientURL, + Health: master.Alive, + } + + oldMasterMember, exist := dc.Status.Master.Members[name] + + status.LastTransitionTime = metav1.Now() + if exist && status.Health == oldMasterMember.Health { + status.LastTransitionTime = oldMasterMember.LastTransitionTime + } + + masterStatus[name] = status + } + + dc.Status.Master.Synced = true + dc.Status.Master.Members = masterStatus + dc.Status.Master.Leader = dc.Status.Master.Members[leader.Name] + dc.Status.Master.Image = "" + c := filterContainer(set, "dm-master") + if c != nil { + dc.Status.Master.Image = c.Image + } + + // k8s check + err = mmm.collectUnjoinedMembers(dc, set, masterStatus) + if err != nil { + return err + } + return nil +} + +// syncMasterConfigMap syncs the configmap of dm-master +func (mmm *masterMemberManager) syncMasterConfigMap(dc *v1alpha1.DMCluster, set *apps.StatefulSet) (*corev1.ConfigMap, error) { + if dc.Spec.Master.Config == nil { + return nil, nil + } + newCm, err := getMasterConfigMap(dc) + if err != nil { + return nil, err + } + return mmm.typedControl.CreateOrUpdateConfigMap(dc, newCm) +} + +func (mmm *masterMemberManager) getNewMasterServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Service { + svcSpec := dc.Spec.Master.Service + if svcSpec == nil { + return nil + } + + ns := dc.Namespace + dcName := dc.Name + svcName := controller.DMMasterMemberName(dcName) + instanceName := dc.GetInstanceName() + masterSelector := label.New().Instance(instanceName).DMMaster() + masterLabels := masterSelector.Copy().UsedByEndUser().Labels() + + ports := []corev1.ServicePort{ + { + Name: "dm-master", + Port: 8261, + TargetPort: intstr.FromInt(8261), + Protocol: corev1.ProtocolTCP, + NodePort: svcSpec.GetMasterNodePort(), + }, + } + masterSvc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + Namespace: ns, + Labels: masterLabels, + Annotations: copyAnnotations(svcSpec.Annotations), + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Spec: corev1.ServiceSpec{ + Type: svcSpec.Type, + Ports: ports, + Selector: masterSelector.Labels(), + }, + } + if svcSpec.Type == corev1.ServiceTypeLoadBalancer { + if svcSpec.LoadBalancerIP != nil { + masterSvc.Spec.LoadBalancerIP = *svcSpec.LoadBalancerIP + } + if svcSpec.LoadBalancerSourceRanges != nil { + masterSvc.Spec.LoadBalancerSourceRanges = svcSpec.LoadBalancerSourceRanges + } + } + if svcSpec.ExternalTrafficPolicy != nil { + masterSvc.Spec.ExternalTrafficPolicy = *svcSpec.ExternalTrafficPolicy + } + if svcSpec.ClusterIP != nil { + masterSvc.Spec.ClusterIP = *svcSpec.ClusterIP + } + return masterSvc +} + +func getNewMasterHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Service { + ns := dc.Namespace + tcName := dc.Name + svcName := controller.DMMasterMemberName(tcName) + instanceName := dc.GetInstanceName() + masterSelector := label.New().Instance(instanceName).DMMaster() + masterLabels := masterSelector.Copy().UsedByPeer().Labels() + + return &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + Namespace: ns, + Labels: masterLabels, + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Spec: corev1.ServiceSpec{ + ClusterIP: "None", + Ports: []corev1.ServicePort{ + { + Name: "dm-master-peer", + Port: 8291, + TargetPort: intstr.FromInt(8291), + Protocol: corev1.ProtocolTCP, + }, + }, + Selector: masterSelector.Labels(), + PublishNotReadyAddresses: true, + }, + } +} + +func (mmm *masterMemberManager) masterStatefulSetIsUpgrading(set *apps.StatefulSet, dc *v1alpha1.DMCluster) (bool, error) { + if statefulSetIsUpgrading(set) { + return true, nil + } + instanceName := dc.GetInstanceName() + selector, err := label.New(). + Instance(instanceName). + DMMaster(). + Selector() + if err != nil { + return false, err + } + masterPods, err := mmm.podLister.Pods(dc.GetNamespace()).List(selector) + if err != nil { + return false, fmt.Errorf("masterStatefulSetIsUpgrading: failed to list pods for cluster %s/%s, selector %s, error: %v", dc.GetNamespace(), instanceName, selector, err) + } + for _, pod := range masterPods { + revisionHash, exist := pod.Labels[apps.ControllerRevisionHashLabelKey] + if !exist { + return false, nil + } + if revisionHash != dc.Status.Master.StatefulSet.UpdateRevision { + return true, nil + } + } + return false, nil +} + +func getDMFailureReplicas(dc *v1alpha1.DMCluster) int { + failureReplicas := 0 + for _, failureMember := range dc.Status.Master.FailureMembers { + if failureMember.MemberDeleted { + failureReplicas++ + } + } + return failureReplicas +} + +func getNewMasterSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) (*apps.StatefulSet, error) { + ns := dc.Namespace + dcName := dc.Name + baseMasterSpec := dc.BaseMasterSpec() + instanceName := dc.GetInstanceName() + masterConfigMap := cm.Name + + annMount, annVolume := annotationsMountVolume() + volMounts := []corev1.VolumeMount{ + annMount, + {Name: "config", ReadOnly: true, MountPath: "/etc/dm-master"}, + {Name: "startup-script", ReadOnly: true, MountPath: "/usr/local/bin"}, + {Name: v1alpha1.DMMasterMemberType.String(), MountPath: dmMasterDataVolumeMountPath}, + } + if dc.IsTLSClusterEnabled() { + volMounts = append(volMounts, corev1.VolumeMount{ + Name: "dm-master-tls", ReadOnly: true, MountPath: "/var/lib/dm-master-tls", + }) + } + + vols := []corev1.Volume{ + annVolume, + {Name: "config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: masterConfigMap, + }, + Items: []corev1.KeyToPath{{Key: "config-file", Path: "dm-master.toml"}}, + }, + }, + }, + {Name: "startup-script", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: masterConfigMap, + }, + Items: []corev1.KeyToPath{{Key: "startup-script", Path: "dm_master_start_script.sh"}}, + }, + }, + }, + } + if dc.IsTLSClusterEnabled() { + vols = append(vols, corev1.Volume{ + Name: "dm-master-tls", VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: util.ClusterTLSSecretName(dc.Name, label.DMMasterLabelVal), + }, + }, + }) + } + + storageRequest, err := controller.ParseStorageRequest(dc.Spec.Master.Requests) + if err != nil { + return nil, fmt.Errorf("cannot parse storage request for dm-master, dmcluster %s/%s, error: %v", dc.Namespace, dc.Name, err) + } + + masterLabel := label.New().Instance(instanceName).DMMaster() + setName := controller.DMMasterMemberName(dcName) + podAnnotations := CombineAnnotations(controller.AnnProm(8261), baseMasterSpec.Annotations()) + stsAnnotations := getStsAnnotations(dc.Annotations, label.DMMasterLabelVal) + + masterContainer := corev1.Container{ + Name: v1alpha1.DMMasterMemberType.String(), + Image: dc.MasterImage(), + ImagePullPolicy: baseMasterSpec.ImagePullPolicy(), + Command: []string{"/bin/sh", "/usr/local/bin/dm_master_start_script.sh"}, + Ports: []corev1.ContainerPort{ + { + Name: "peer", + ContainerPort: int32(8291), + Protocol: corev1.ProtocolTCP, + }, + { + Name: "client", + ContainerPort: int32(8261), + Protocol: corev1.ProtocolTCP, + }, + }, + VolumeMounts: volMounts, + Resources: controller.ContainerResource(dc.Spec.Master.ResourceRequirements), + } + env := []corev1.EnvVar{ + { + Name: "NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }, + { + Name: "PEER_SERVICE_NAME", + Value: controller.DMMasterPeerMemberName(dcName), + }, + { + Name: "SERVICE_NAME", + Value: controller.DMMasterMemberName(dcName), + }, + { + Name: "SET_NAME", + Value: setName, + }, + { + Name: "TZ", + Value: dc.Spec.Timezone, + }, + } + + podSpec := baseMasterSpec.BuildPodSpec() + if baseMasterSpec.HostNetwork() { + podSpec.DNSPolicy = corev1.DNSClusterFirstWithHostNet + env = append(env, corev1.EnvVar{ + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.name", + }, + }, + }) + } + masterContainer.Env = util.AppendEnv(env, baseMasterSpec.Env()) + podSpec.Volumes = append(vols, baseMasterSpec.AdditionalVolumes()...) + podSpec.Containers = append([]corev1.Container{masterContainer}, baseMasterSpec.AdditionalContainers()...) + + masterSet := &apps.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: setName, + Namespace: ns, + Labels: masterLabel.Labels(), + Annotations: stsAnnotations, + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Spec: apps.StatefulSetSpec{ + Replicas: pointer.Int32Ptr(dc.MasterStsDesiredReplicas()), + Selector: masterLabel.LabelSelector(), + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: masterLabel.Labels(), + Annotations: podAnnotations, + }, + Spec: podSpec, + }, + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: v1alpha1.DMMasterMemberType.String(), + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteOnce, + }, + StorageClassName: dc.Spec.Master.StorageClassName, + Resources: storageRequest, + }, + }, + }, + ServiceName: controller.DMMasterPeerMemberName(dcName), + PodManagementPolicy: apps.ParallelPodManagement, + UpdateStrategy: apps.StatefulSetUpdateStrategy{ + Type: apps.RollingUpdateStatefulSetStrategyType, + RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{ + Partition: pointer.Int32Ptr(dc.MasterStsDesiredReplicas()), + }}, + }, + } + + return masterSet, nil +} + +func getMasterConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { + // For backward compatibility, only sync dm configmap when .master.config is non-nil + config := dc.Spec.Master.Config + if config == nil { + return nil, nil + } + + // override CA if tls enabled + if dc.IsTLSClusterEnabled() { + config.SSLCA = pointer.StringPtr(path.Join(dmMasterClusterCertPath, tlsSecretRootCAKey)) + config.SSLCert = pointer.StringPtr(path.Join(dmMasterClusterCertPath, corev1.TLSCertKey)) + config.SSLKey = pointer.StringPtr(path.Join(dmMasterClusterCertPath, corev1.TLSPrivateKeyKey)) + } + + confText, err := MarshalTOML(config) + if err != nil { + return nil, err + } + startScript, err := RenderDMMasterStartScript(&DMMasterStartScriptModel{ + Scheme: dc.Scheme(), + DataDir: filepath.Join(dmMasterDataVolumeMountPath, dc.Spec.Master.DataSubDir), + DiscoveryURL: dc.Spec.Discovery.Address, + }) + if err != nil { + return nil, err + } + + instanceName := dc.GetInstanceName() + masterLabel := label.New().Instance(instanceName).DMMaster().Labels() + cm := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: controller.DMMasterMemberName(dc.Name), + Namespace: dc.Namespace, + Labels: masterLabel, + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Data: map[string]string{ + "config-file": string(confText), + "startup-script": startScript, + }, + } + + if err := AddConfigMapDigestSuffix(cm); err != nil { + return nil, err + } + return cm, nil +} + +func (mmm *masterMemberManager) collectUnjoinedMembers(dc *v1alpha1.DMCluster, set *apps.StatefulSet, masterStatus map[string]v1alpha1.MasterMember) error { + podSelector, podSelectErr := metav1.LabelSelectorAsSelector(set.Spec.Selector) + if podSelectErr != nil { + return podSelectErr + } + pods, podErr := mmm.podLister.Pods(dc.Namespace).List(podSelector) + if podErr != nil { + return fmt.Errorf("collectUnjoinedMembers: failed to list pods for cluster %s/%s, selector %s, error %v", dc.GetNamespace(), dc.GetName(), set.Spec.Selector, podErr) + } + for _, pod := range pods { + var joined = false + for podName := range masterStatus { + if strings.EqualFold(pod.Name, podName) { + joined = true + break + } + } + if !joined { + if dc.Status.Master.UnjoinedMembers == nil { + dc.Status.Master.UnjoinedMembers = map[string]v1alpha1.UnjoinedMember{} + } + ordinal, err := util.GetOrdinalFromPodName(pod.Name) + if err != nil { + return err + } + pvcName := ordinalPVCName(v1alpha1.DMMasterMemberType, controller.DMMasterMemberName(dc.Name), ordinal) + pvc, err := mmm.pvcLister.PersistentVolumeClaims(dc.Namespace).Get(pvcName) + if err != nil { + return fmt.Errorf("collectUnjoinedMembers: failed to get pvc %s of cluster %s/%s, error %v", pvcName, dc.GetNamespace(), dc.GetName(), err) + } + dc.Status.Master.UnjoinedMembers[pod.Name] = v1alpha1.UnjoinedMember{ + PodName: pod.Name, + PVCUID: pvc.UID, + CreatedAt: metav1.Now(), + } + } else { + if dc.Status.Master.UnjoinedMembers != nil { + if _, ok := dc.Status.Master.UnjoinedMembers[pod.Name]; ok { + delete(dc.Status.Master.UnjoinedMembers, pod.Name) + } + } + } + } + return nil +} diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go new file mode 100644 index 0000000000..1bbac7671c --- /dev/null +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -0,0 +1,524 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package member + +import ( + "fmt" + "path" + "path/filepath" + + "github.com/pingcap/tidb-operator/pkg/util" + + "k8s.io/utils/pointer" + + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/dmapi" + "github.com/pingcap/tidb-operator/pkg/label" + "github.com/pingcap/tidb-operator/pkg/manager" + + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + v1 "k8s.io/client-go/listers/apps/v1" + corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/klog" +) + +const ( + // dmWorkerDataVolumeMountPath is the mount path for dm-worker data volume + dmWorkerDataVolumeMountPath = "/var/lib/dm-worker" + // dmWorkerClusterCertPath is where the cert for inter-cluster communication stored (if any) + dmWorkerClusterCertPath = "/var/lib/dm-worker-tls" +) + +type workerMemberManager struct { + masterControl dmapi.MasterControlInterface + setControl controller.StatefulSetControlInterface + svcControl controller.ServiceControlInterface + //podControl controller.PodControlInterface + typedControl controller.TypedControlInterface + setLister v1.StatefulSetLister + svcLister corelisters.ServiceLister + podLister corelisters.PodLister +} + +// NewWorkerMemberManager returns a *ticdcMemberManager +func NewWorkerMemberManager(masterControl dmapi.MasterControlInterface, + setControl controller.StatefulSetControlInterface, + svcControl controller.ServiceControlInterface, + //podControl controller.PodControlInterface, + typedControl controller.TypedControlInterface, + setLister v1.StatefulSetLister, + svcLister corelisters.ServiceLister, + podLister corelisters.PodLister) manager.DMManager { + return &workerMemberManager{ + masterControl, + setControl, + svcControl, + //podControl, + typedControl, + setLister, + svcLister, + podLister, + } +} + +func (wmm *workerMemberManager) Sync(dc *v1alpha1.DMCluster) error { + ns := dc.GetNamespace() + dcName := dc.GetName() + + if dc.Spec.Worker == nil { + return nil + } + if dc.Spec.Paused { + klog.Infof("DMCluster %s/%s is paused, skip syncing dm-worker deployment", ns, dcName) + return nil + } + if !dc.MasterIsAvailable() { + return controller.RequeueErrorf("DMCluster: %s/%s, waiting for dm-master cluster running", ns, dcName) + } + + // Sync dm-worker Headless Service + if err := wmm.syncWorkerHeadlessServiceForDMCluster(dc); err != nil { + return err + } + + // Sync dm-worker StatefulSet + return wmm.syncWorkerStatefulSetForDMCluster(dc) +} + +func (wmm *workerMemberManager) syncWorkerHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) error { + ns := dc.GetNamespace() + dcName := dc.GetName() + + newSvc := getNewWorkerHeadlessServiceForDMCluster(dc) + oldSvcTmp, err := wmm.svcLister.Services(ns).Get(controller.DMWorkerPeerMemberName(dcName)) + if errors.IsNotFound(err) { + err = controller.SetServiceLastAppliedConfigAnnotation(newSvc) + if err != nil { + return err + } + return wmm.svcControl.CreateService(dc, newSvc) + } + if err != nil { + return fmt.Errorf("syncWorkerHeadlessServiceForDMCluster: failed to get svc %s for cluster %s/%s, error: %s", controller.DMWorkerPeerMemberName(dcName), ns, dcName, err) + } + + oldSvc := oldSvcTmp.DeepCopy() + + equal, err := controller.ServiceEqual(newSvc, oldSvc) + if err != nil { + return err + } + if !equal { + svc := *oldSvc + svc.Spec = newSvc.Spec + err = controller.SetServiceLastAppliedConfigAnnotation(&svc) + if err != nil { + return err + } + _, err = wmm.svcControl.UpdateService(dc, &svc) + return err + } + + return nil +} + +func getNewWorkerHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Service { + ns := dc.Namespace + dcName := dc.Name + instanceName := dc.GetInstanceName() + svcName := controller.DMWorkerPeerMemberName(dcName) + svcLabel := label.New().Instance(instanceName).DMWorker().Labels() + + svc := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + Namespace: ns, + Labels: svcLabel, + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Spec: corev1.ServiceSpec{ + ClusterIP: "None", + Ports: []corev1.ServicePort{ + { + Name: "dm-worker", + Port: 8262, + TargetPort: intstr.FromInt(int(8262)), + Protocol: corev1.ProtocolTCP, + }, + }, + Selector: svcLabel, + PublishNotReadyAddresses: true, + }, + } + return &svc +} + +func (wmm *workerMemberManager) syncWorkerStatefulSetForDMCluster(dc *v1alpha1.DMCluster) error { + ns := dc.GetNamespace() + dcName := dc.GetName() + + oldStsTmp, err := wmm.setLister.StatefulSets(ns).Get(controller.DMWorkerPeerMemberName(dcName)) + if err != nil && !errors.IsNotFound(err) { + return fmt.Errorf("syncWorkerStatefulSetForDMCluster: failed to get sts %s for cluster %s/%s, error: %s", controller.DMWorkerPeerMemberName(dcName), ns, dcName, err) + } + + stsNotExist := errors.IsNotFound(err) + oldSts := oldStsTmp.DeepCopy() + + // failed to sync dm-worker status will not affect subsequent logic, just print the errors. + if err := wmm.syncDMClusterStatus(dc, oldSts); err != nil { + klog.Errorf("failed to sync DMCluster: [%s/%s]'s dm-worker status, error: %v", ns, dcName, err) + } + + if dc.Spec.Paused { + klog.V(4).Infof("dm cluster %s/%s is paused, skip syncing for dm-worker statefulset", dc.GetNamespace(), dc.GetName()) + return nil + } + + cm, err := wmm.syncWorkerConfigMap(dc, oldSts) + if err != nil { + return err + } + newSts, err := getNewWorkerSetForDMCluster(dc, cm) + if err != nil { + return err + } + + if stsNotExist { + err = SetStatefulSetLastAppliedConfigAnnotation(newSts) + if err != nil { + return err + } + err = wmm.setControl.CreateStatefulSet(dc, newSts) + if err != nil { + return err + } + return nil + } + + if dc.MasterUpgrading() { + klog.Warningf("dm-master is upgrading, skipping upgrade dm-worker") + return nil + } + + return updateStatefulSet(wmm.setControl, dc, newSts, oldSts) +} + +func (wmm *workerMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set *apps.StatefulSet) error { + if set == nil { + // skip if not created yet + return nil + } + + dc.Status.Worker.StatefulSet = &set.Status + + upgrading, err := wmm.workerStatefulSetIsUpgrading(set, dc) + if err != nil { + return err + } + if upgrading { + dc.Status.Worker.Phase = v1alpha1.UpgradePhase + } else { + dc.Status.Worker.Phase = v1alpha1.NormalPhase + } + + dmClient := controller.GetMasterClient(wmm.masterControl, dc) + + workersInfo, err := dmClient.GetWorkers() + if err != nil { + dc.Status.Master.Synced = false + return err + } + + workerStatus := map[string]v1alpha1.WorkerMember{} + for _, worker := range workersInfo { + name := worker.Name + status := v1alpha1.WorkerMember{ + Name: name, + Addr: worker.Addr, + Stage: worker.Stage, + } + + oldWorkerMember, exist := dc.Status.Worker.Members[name] + + status.LastTransitionTime = metav1.Now() + if exist && status.Stage == oldWorkerMember.Stage { + status.LastTransitionTime = oldWorkerMember.LastTransitionTime + } + + workerStatus[name] = status + } + + dc.Status.Worker.Synced = true + dc.Status.Worker.Members = workerStatus + return nil +} + +func (wmm *workerMemberManager) workerStatefulSetIsUpgrading(set *apps.StatefulSet, dc *v1alpha1.DMCluster) (bool, error) { + if statefulSetIsUpgrading(set) { + return true, nil + } + instanceName := dc.GetInstanceName() + selector, err := label.New(). + Instance(instanceName). + DMWorker(). + Selector() + if err != nil { + return false, err + } + workerPods, err := wmm.podLister.Pods(dc.GetNamespace()).List(selector) + if err != nil { + return false, fmt.Errorf("workerStatefulSetIsUpgrading: failed to list pods for cluster %s/%s, selector %s, error: %v", dc.GetNamespace(), instanceName, selector, err) + } + for _, pod := range workerPods { + revisionHash, exist := pod.Labels[apps.ControllerRevisionHashLabelKey] + if !exist { + return false, nil + } + if revisionHash != dc.Status.Worker.StatefulSet.UpdateRevision { + return true, nil + } + } + return false, nil +} + +// syncWorkerConfigMap syncs the configmap of dm-worker +func (wmm *workerMemberManager) syncWorkerConfigMap(dc *v1alpha1.DMCluster, set *apps.StatefulSet) (*corev1.ConfigMap, error) { + if dc.Spec.Worker.Config == nil { + return nil, nil + } + newCm, err := getWorkerConfigMap(dc) + if err != nil { + return nil, err + } + return wmm.typedControl.CreateOrUpdateConfigMap(dc, newCm) +} + +func getNewWorkerSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) (*apps.StatefulSet, error) { + ns := dc.Namespace + dcName := dc.Name + baseWorkerSpec := dc.BaseWorkerSpec() + instanceName := dc.GetInstanceName() + workerConfigMap := cm.Name + + annMount, annVolume := annotationsMountVolume() + volMounts := []corev1.VolumeMount{ + annMount, + {Name: "config", ReadOnly: true, MountPath: "/etc/dm-worker"}, + {Name: "startup-script", ReadOnly: true, MountPath: "/usr/local/bin"}, + {Name: v1alpha1.DMWorkerMemberType.String(), MountPath: dmWorkerDataVolumeMountPath}, + } + if dc.IsTLSClusterEnabled() { + volMounts = append(volMounts, corev1.VolumeMount{ + Name: "dm-worker-tls", ReadOnly: true, MountPath: "/var/lib/dm-worker-tls", + }) + } + + vols := []corev1.Volume{ + annVolume, + {Name: "config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: workerConfigMap, + }, + Items: []corev1.KeyToPath{{Key: "config-file", Path: "dm-worker.toml"}}, + }, + }, + }, + {Name: "startup-script", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: workerConfigMap, + }, + Items: []corev1.KeyToPath{{Key: "startup-script", Path: "dm_worker_start_script.sh"}}, + }, + }, + }, + } + if dc.IsTLSClusterEnabled() { + vols = append(vols, corev1.Volume{ + Name: "dm-worker-tls", VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: util.ClusterTLSSecretName(dc.Name, label.DMWorkerLabelVal), + }, + }, + }) + } + + storageRequest, err := controller.ParseStorageRequest(dc.Spec.Worker.Requests) + if err != nil { + return nil, fmt.Errorf("cannot parse storage request for dm-worker, dmcluster %s/%s, error: %v", dc.Namespace, dc.Name, err) + } + + workerLabel := label.New().Instance(instanceName).DMWorker() + setName := controller.DMWorkerPeerMemberName(dcName) + podAnnotations := CombineAnnotations(controller.AnnProm(8262), baseWorkerSpec.Annotations()) + stsAnnotations := getStsAnnotations(dc.Annotations, label.DMWorkerLabelVal) + + workerContainer := corev1.Container{ + Name: v1alpha1.DMWorkerMemberType.String(), + Image: dc.WorkerImage(), + ImagePullPolicy: baseWorkerSpec.ImagePullPolicy(), + Command: []string{"/bin/sh", "/usr/local/bin/dm_worker_start_script.sh"}, + Ports: []corev1.ContainerPort{ + { + Name: "client", + ContainerPort: int32(8262), + Protocol: corev1.ProtocolTCP, + }, + }, + VolumeMounts: volMounts, + Resources: controller.ContainerResource(dc.Spec.Worker.ResourceRequirements), + } + env := []corev1.EnvVar{ + { + Name: "NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }, + { + Name: "CLUSTER_NAME", + Value: dcName, + }, + { + Name: "HEADLESS_SERVICE_NAME", + Value: controller.DMWorkerPeerMemberName(dcName), + }, + { + Name: "SET_NAME", + Value: setName, + }, + { + Name: "TZ", + Value: dc.Spec.Timezone, + }, + } + + podSpec := baseWorkerSpec.BuildPodSpec() + if baseWorkerSpec.HostNetwork() { + podSpec.DNSPolicy = corev1.DNSClusterFirstWithHostNet + env = append(env, corev1.EnvVar{ + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.name", + }, + }, + }) + } + workerContainer.Env = util.AppendEnv(env, baseWorkerSpec.Env()) + podSpec.Volumes = append(vols, baseWorkerSpec.AdditionalVolumes()...) + podSpec.Containers = append([]corev1.Container{workerContainer}, baseWorkerSpec.AdditionalContainers()...) + + workerSet := &apps.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: setName, + Namespace: ns, + Labels: workerLabel.Labels(), + Annotations: stsAnnotations, + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Spec: apps.StatefulSetSpec{ + Replicas: pointer.Int32Ptr(dc.WorkerStsDesiredReplicas()), + Selector: workerLabel.LabelSelector(), + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: workerLabel.Labels(), + Annotations: podAnnotations, + }, + Spec: podSpec, + }, + VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: v1alpha1.DMWorkerMemberType.String(), + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteOnce, + }, + StorageClassName: dc.Spec.Worker.StorageClassName, + Resources: storageRequest, + }, + }, + }, + ServiceName: controller.DMWorkerPeerMemberName(dcName), + PodManagementPolicy: apps.ParallelPodManagement, + UpdateStrategy: apps.StatefulSetUpdateStrategy{ + Type: apps.RollingUpdateStatefulSetStrategyType, + RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{ + Partition: pointer.Int32Ptr(dc.WorkerStsDesiredReplicas()), + }}, + }, + } + + return workerSet, nil +} + +func getWorkerConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { + // For backward compatibility, only sync dm configmap when .worker.config is non-nil + config := dc.Spec.Worker.Config + if config == nil { + return nil, nil + } + + // override CA if tls enabled + if dc.IsTLSClusterEnabled() { + config.SSLCA = pointer.StringPtr(path.Join(dmWorkerClusterCertPath, tlsSecretRootCAKey)) + config.SSLCert = pointer.StringPtr(path.Join(dmWorkerClusterCertPath, corev1.TLSCertKey)) + config.SSLKey = pointer.StringPtr(path.Join(dmWorkerClusterCertPath, corev1.TLSPrivateKeyKey)) + } + + confText, err := MarshalTOML(config) + if err != nil { + return nil, err + } + startScript, err := RenderDMWorkerStartScript(&DMWorkerStartScriptModel{ + DataDir: filepath.Join(dmWorkerDataVolumeMountPath, dc.Spec.Worker.DataSubDir), + MasterAddress: dc.Scheme() + "://" + controller.DMMasterMemberName(dc.Name) + ":8261", + }) + if err != nil { + return nil, err + } + + instanceName := dc.GetInstanceName() + workerLabel := label.New().Instance(instanceName).DMWorker().Labels() + cm := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: controller.DMWorkerPeerMemberName(dc.Name), + Namespace: dc.Namespace, + Labels: workerLabel, + OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, + }, + Data: map[string]string{ + "config-file": string(confText), + "startup-script": startScript, + }, + } + + if err := AddConfigMapDigestSuffix(cm); err != nil { + return nil, err + } + return cm, nil +} diff --git a/pkg/manager/member/pd_member_manager.go b/pkg/manager/member/pd_member_manager.go index b7d6cf1a8c..94ae7217b9 100644 --- a/pkg/manager/member/pd_member_manager.go +++ b/pkg/manager/member/pd_member_manager.go @@ -244,7 +244,7 @@ func (pmm *pdMemberManager) syncPDStatefulSetForTidbCluster(tc *v1alpha1.TidbClu } if !tc.Status.PD.Synced { - force := NeedForceUpgrade(tc) + force := NeedForceUpgrade(tc.Annotations) if force { tc.Status.PD.Phase = v1alpha1.UpgradePhase setUpgradePartition(newPDSet, 0) @@ -630,7 +630,7 @@ func getNewPDSetForTidbCluster(tc *v1alpha1.TidbCluster, cm *corev1.ConfigMap) ( pdLabel := label.New().Instance(instanceName).PD() setName := controller.PDMemberName(tcName) podAnnotations := CombineAnnotations(controller.AnnProm(2379), basePDSpec.Annotations()) - stsAnnotations := getStsAnnotations(tc, label.PDLabelVal) + stsAnnotations := getStsAnnotations(tc.Annotations, label.PDLabelVal) failureReplicas := getFailureReplicas(tc) pdContainer := corev1.Container{ @@ -827,6 +827,15 @@ func clusterVersionGreaterThanOrEqualTo4(version string) (bool, error) { return v.Major() >= 4, nil } +func clusterVersionLessThan2(version string) (bool, error) { + v, err := semver.NewVersion(version) + if err != nil { + return true, err + } + + return v.Major() < 2, nil +} + func (pmm *pdMemberManager) collectUnjoinedMembers(tc *v1alpha1.TidbCluster, set *apps.StatefulSet, pdStatus map[string]v1alpha1.PDMember) error { podSelector, podSelectErr := metav1.LabelSelectorAsSelector(set.Spec.Selector) if podSelectErr != nil { diff --git a/pkg/manager/member/template.go b/pkg/manager/member/template.go index 54c0009c04..5d818efca5 100644 --- a/pkg/manager/member/template.go +++ b/pkg/manager/member/template.go @@ -361,3 +361,166 @@ func renderTemplateFunc(tpl *template.Template, model interface{}) (string, erro } return buff.String(), nil } + +// dmMasterStartScriptTpl is the dm-master start script +// Note: changing this will cause a rolling-update of dm-master cluster +var dmMasterStartScriptTpl = template.Must(template.New("dm-master-start-script").Parse(`#!/bin/sh + +# This script is used to start dm-master containers in kubernetes cluster + +# Use DownwardAPIVolumeFiles to store informations of the cluster: +# https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/#the-downward-api +# +# runmode="normal/debug" +# + +set -uo pipefail + +ANNOTATIONS="/etc/podinfo/annotations" + +if [[ ! -f "${ANNOTATIONS}" ]] +then + echo "${ANNOTATIONS} does't exist, exiting." + exit 1 +fi +source ${ANNOTATIONS} 2>/dev/null + +runmode=${runmode:-normal} +if [[ X${runmode} == Xdebug ]] +then + echo "entering debug mode." + tail -f /dev/null +fi + +# Use HOSTNAME if POD_NAME is unset for backward compatibility. +POD_NAME=${POD_NAME:-$HOSTNAME} +# the general form of variable PEER_SERVICE_NAME is: "-dm-master-peer" +cluster_name=` + "`" + `echo ${PEER_SERVICE_NAME} | sed 's/-dm-master-peer//'` + "`" + + ` +domain="${POD_NAME}.${PEER_SERVICE_NAME}.${NAMESPACE}.svc" +discovery_url={{ .DiscoveryURL }} +encoded_domain_url=` + "`" + `echo ${domain}:8291 | base64 | tr "\n" " " | sed "s/ //g"` + "`" + + ` +elapseTime=0 +period=1 +threshold=30 +while true; do +sleep ${period} +elapseTime=$(( elapseTime+period )) + +if [[ ${elapseTime} -ge ${threshold} ]] +then +echo "waiting for dm-master cluster ready timeout" >&2 +exit 1 +fi + +if nslookup ${domain} 2>/dev/null +then +echo "nslookup domain ${domain}.svc success" +break +else +echo "nslookup domain ${domain} failed" >&2 +fi +done + +ARGS="--data-dir={{ .DataDir }} \ +--name=${POD_NAME} \ +--peer-urls={{ .Scheme }}://0.0.0.0:8291 \ +--advertise-peer-urls={{ .Scheme }}://${domain}:8291 \ +--client-urls={{ .Scheme }}://0.0.0.0:8261 \ +--advertise-client-urls={{ .Scheme }}://${domain}:8261 \ +--config=/etc/dm-master/dm-master.toml \ +" + +if [[ -f {{ .DataDir }}/join ]] +then +# The content of the join file is: +# demo-dm-master-0=http://demo-dm-master-0.demo-dm-master-peer.demo.svc:8291,demo-dm-master-1=http://demo-dm-master-1.demo-dm-master-peer.demo.svc:8291 +# The --join args must be: +# --join=http://demo-dm-master-0.demo-dm-master-peer.demo.svc:8261,http://demo-dm-master-1.demo-dm-master-peer.demo.svc:8261 +join=` + "`" + `cat {{ .DataDir }}/join | tr "," "\n" | awk -F'=' '{print $2}' | tr "\n" ","` + "`" + ` +join=${join%,} +ARGS="${ARGS} --join=${join}" +elif [[ ! -d {{ .DataDir }}/member/wal ]] +then +until result=$(wget -qO- -T 3 http://${discovery_url}/new/${encoded_domain_url}/dm 2>/dev/null); do +echo "waiting for discovery service to return start args ..." +sleep $((RANDOM % 5)) +done +ARGS="${ARGS}${result}" +fi + +echo "starting dm-master ..." +sleep $((RANDOM % 10)) +echo "/dm-master ${ARGS}" +exec /dm-master ${ARGS} +`)) + +type DMMasterStartScriptModel struct { + Scheme string + DataDir string + DiscoveryURL string +} + +func RenderDMMasterStartScript(model *DMMasterStartScriptModel) (string, error) { + return renderTemplateFunc(dmMasterStartScriptTpl, model) +} + +// dmWorkerStartScriptTpl is the dm-worker start script +// Note: changing this will cause a rolling-update of dm-worker cluster +var dmWorkerStartScriptTpl = template.Must(template.New("dm-worker-start-script").Parse(`#!/bin/sh + +# This script is used to start dm-worker containers in kubernetes cluster + +# Use DownwardAPIVolumeFiles to store informations of the cluster: +# https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/#the-downward-api +# +# runmode="normal/debug" +# + +set -uo pipefail + +ANNOTATIONS="/etc/podinfo/annotations" + +if [[ ! -f "${ANNOTATIONS}" ]] +then + echo "${ANNOTATIONS} does't exist, exiting." + exit 1 +fi +source ${ANNOTATIONS} 2>/dev/null + +runmode=${runmode:-normal} +if [[ X${runmode} == Xdebug ]] +then + echo "entering debug mode." + tail -f /dev/null +fi + + +# Use HOSTNAME if POD_NAME is unset for backward compatibility. +POD_NAME=${POD_NAME:-$HOSTNAME} +ARGS="--join={{ .MasterAddress }} \ +--advertise-addr=${POD_NAME}.${HEADLESS_SERVICE_NAME}.${NAMESPACE}.svc:8262 \ +--addr=0.0.0.0:8262 \ +--data-dir={{ .DataDir }} \ +--config=/etc/dm-worker/dm-worker.toml +" + +if [ ! -z "${STORE_LABELS:-}" ]; then + LABELS=" --labels ${STORE_LABELS} " + ARGS="${ARGS}${LABELS}" +fi + +echo "starting dm-worker ..." +echo "/dm-worker ${ARGS}" +exec /dm-worker ${ARGS} +`)) + +type DMWorkerStartScriptModel struct { + DataDir string + MasterAddress string +} + +func RenderDMWorkerStartScript(model *DMWorkerStartScriptModel) (string, error) { + return renderTemplateFunc(dmWorkerStartScriptTpl, model) +} diff --git a/pkg/manager/member/ticdc_member_manager.go b/pkg/manager/member/ticdc_member_manager.go index 6d55ad3f01..f78703fe39 100644 --- a/pkg/manager/member/ticdc_member_manager.go +++ b/pkg/manager/member/ticdc_member_manager.go @@ -256,7 +256,7 @@ func getNewTiCDCStatefulSet(tc *v1alpha1.TidbCluster) (*apps.StatefulSet, error) ticdcLabel := labelTiCDC(tc) stsName := controller.TiCDCMemberName(tcName) podAnnotations := CombineAnnotations(controller.AnnProm(8301), baseTiCDCSpec.Annotations()) - stsAnnotations := getStsAnnotations(tc, label.TiCDCLabelVal) + stsAnnotations := getStsAnnotations(tc.Annotations, label.TiCDCLabelVal) headlessSvcName := controller.TiCDCPeerMemberName(tcName) cmdArgs := []string{"/cdc server", "--addr=0.0.0.0:8301", "--advertise-addr=${POD_NAME}.${HEADLESS_SERVICE_NAME}.${NAMESPACE}.svc:8301"} diff --git a/pkg/manager/member/tidb_member_manager.go b/pkg/manager/member/tidb_member_manager.go index d4d2c1810d..96c53d19b8 100644 --- a/pkg/manager/member/tidb_member_manager.go +++ b/pkg/manager/member/tidb_member_manager.go @@ -750,7 +750,7 @@ func getNewTiDBSetForTidbCluster(tc *v1alpha1.TidbCluster, cm *corev1.ConfigMap) tidbLabel := label.New().Instance(instanceName).TiDB() podAnnotations := CombineAnnotations(controller.AnnProm(10080), baseTiDBSpec.Annotations()) - stsAnnotations := getStsAnnotations(tc, label.TiDBLabelVal) + stsAnnotations := getStsAnnotations(tc.Annotations, label.TiDBLabelVal) tidbSet := &apps.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ Name: controller.TiDBMemberName(tcName), diff --git a/pkg/manager/member/tiflash_member_manager.go b/pkg/manager/member/tiflash_member_manager.go index df4be1656e..e73d38b0a3 100644 --- a/pkg/manager/member/tiflash_member_manager.go +++ b/pkg/manager/member/tiflash_member_manager.go @@ -425,7 +425,7 @@ func getNewStatefulSet(tc *v1alpha1.TidbCluster, cm *corev1.ConfigMap) (*apps.St setName := controller.TiFlashMemberName(tcName) podAnnotations := CombineAnnotations(controller.AnnProm(8234), baseTiFlashSpec.Annotations()) podAnnotations = CombineAnnotations(controller.AnnAdditionalProm("tiflash.proxy", 20292), podAnnotations) - stsAnnotations := getStsAnnotations(tc, label.TiFlashLabelVal) + stsAnnotations := getStsAnnotations(tc.Annotations, label.TiFlashLabelVal) capacity := controller.TiKVCapacity(tc.Spec.TiFlash.Limits) headlessSvcName := controller.TiFlashPeerMemberName(tcName) diff --git a/pkg/manager/member/tikv_member_manager.go b/pkg/manager/member/tikv_member_manager.go index 292bdc5f97..0d3081bc41 100644 --- a/pkg/manager/member/tikv_member_manager.go +++ b/pkg/manager/member/tikv_member_manager.go @@ -424,7 +424,7 @@ func getNewTiKVSetForTidbCluster(tc *v1alpha1.TidbCluster, cm *corev1.ConfigMap) tikvLabel := labelTiKV(tc) setName := controller.TiKVMemberName(tcName) podAnnotations := CombineAnnotations(controller.AnnProm(20180), baseTiKVSpec.Annotations()) - stsAnnotations := getStsAnnotations(tc, label.TiKVLabelVal) + stsAnnotations := getStsAnnotations(tc.Annotations, label.TiKVLabelVal) capacity := controller.TiKVCapacity(tc.Spec.TiKV.Limits) headlessSvcName := controller.TiKVPeerMemberName(tcName) diff --git a/pkg/manager/member/utils.go b/pkg/manager/member/utils.go index c1876ef4a0..0798687880 100644 --- a/pkg/manager/member/utils.go +++ b/pkg/manager/member/utils.go @@ -191,10 +191,10 @@ func CombineAnnotations(a, b map[string]string) map[string]string { } // NeedForceUpgrade check if force upgrade is necessary -func NeedForceUpgrade(tc *v1alpha1.TidbCluster) bool { +func NeedForceUpgrade(ann map[string]string) bool { // Check if annotation 'pingcap.com/force-upgrade: "true"' is set - if tc.Annotations != nil { - forceVal, ok := tc.Annotations[label.AnnForceUpgradeKey] + if ann != nil { + forceVal, ok := ann[label.AnnForceUpgradeKey] if ok && (forceVal == label.AnnForceUpgradeVal) { return true } @@ -248,23 +248,25 @@ func AddConfigMapDigestSuffix(cm *corev1.ConfigMap) error { } // getStsAnnotations gets annotations for statefulset of given component. -func getStsAnnotations(tc *v1alpha1.TidbCluster, component string) map[string]string { +func getStsAnnotations(tcAnns map[string]string, component string) map[string]string { anns := map[string]string{} - tcAnns := tc.Annotations if tcAnns == nil { return anns } // delete slots var key string - if component == label.PDLabelVal { + switch component { + case label.PDLabelVal: key = label.AnnPDDeleteSlots - } else if component == label.TiDBLabelVal { + case label.TiDBLabelVal: key = label.AnnTiDBDeleteSlots - } else if component == label.TiKVLabelVal { + case label.TiKVLabelVal: key = label.AnnTiKVDeleteSlots - } else if component == label.TiFlashLabelVal { + case label.TiFlashLabelVal: key = label.AnnTiFlashDeleteSlots - } else { + case label.DMMasterLabelVal: + key = label.AnnDMMasterDeleteSlots + default: return anns } if val, ok := tcAnns[key]; ok { diff --git a/pkg/manager/member/utils_test.go b/pkg/manager/member/utils_test.go index 7007da0b0f..428bba34d1 100644 --- a/pkg/manager/member/utils_test.go +++ b/pkg/manager/member/utils_test.go @@ -155,7 +155,7 @@ func TestGetStsAnnotations(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := getStsAnnotations(tt.tc, tt.component) + got := getStsAnnotations(tt.tc.Annotations, tt.component) if diff := cmp.Diff(tt.expected, got); diff != "" { t.Errorf("unexpected (-want, +got): %s", diff) } diff --git a/pkg/util/dmcluster/dmcluster.go b/pkg/util/dmcluster/dmcluster.go new file mode 100644 index 0000000000..f9046d2fe4 --- /dev/null +++ b/pkg/util/dmcluster/dmcluster.go @@ -0,0 +1,87 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package dmcluster + +import ( + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // Reasons for DMCluster conditions. + + // Ready + Ready = "Ready" + // StatefulSetNotUpToDate is added when one of statefulsets is not up to date. + StatfulSetNotUpToDate = "StatefulSetNotUpToDate" + // MasterUnhealthy is added when one of dm-master members is unhealthy. + MasterUnhealthy = "DMMasterUnhealthy" +) + +// NewDMClusterCondition creates a new dmcluster condition. +func NewDMClusterCondition(condType v1alpha1.DMClusterConditionType, status v1.ConditionStatus, reason, message string) *v1alpha1.DMClusterCondition { + return &v1alpha1.DMClusterCondition{ + Type: condType, + Status: status, + LastUpdateTime: metav1.Now(), + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + } +} + +// GetDMClusterCondition returns the condition with the provided type. +func GetDMClusterCondition(status v1alpha1.DMClusterStatus, condType v1alpha1.DMClusterConditionType) *v1alpha1.DMClusterCondition { + for i := range status.Conditions { + c := status.Conditions[i] + if c.Type == condType { + return &c + } + } + return nil +} + +// SetDMClusterCondition updates the dm cluster to include the provided condition. If the condition that +// we are about to add already exists and has the same status and reason then we are not going to update. +func SetDMClusterCondition(status *v1alpha1.DMClusterStatus, condition v1alpha1.DMClusterCondition) { + currentCond := GetDMClusterCondition(*status, condition.Type) + if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason { + return + } + // Do not update lastTransitionTime if the status of the condition doesn't change. + if currentCond != nil && currentCond.Status == condition.Status { + condition.LastTransitionTime = currentCond.LastTransitionTime + } + newConditions := filterOutCondition(status.Conditions, condition.Type) + status.Conditions = append(newConditions, condition) +} + +// filterOutCondition returns a new slice of tidbcluster conditions without conditions with the provided type. +func filterOutCondition(conditions []v1alpha1.DMClusterCondition, condType v1alpha1.DMClusterConditionType) []v1alpha1.DMClusterCondition { + var newConditions []v1alpha1.DMClusterCondition + for _, c := range conditions { + if c.Type == condType { + continue + } + newConditions = append(newConditions, c) + } + return newConditions +} + +// GetDMClusterReadyCondition extracts the dmcluster ready condition from the given status and returns that. +// Returns nil if the condition is not present. +func GetDMClusterReadyCondition(status v1alpha1.DMClusterStatus) *v1alpha1.DMClusterCondition { + return GetDMClusterCondition(status, v1alpha1.DMClusterReady) +} diff --git a/pkg/webhook/pod/pods.go b/pkg/webhook/pod/pods.go index 74eef51bd5..2e9a2b4c6b 100644 --- a/pkg/webhook/pod/pods.go +++ b/pkg/webhook/pod/pods.go @@ -252,7 +252,7 @@ func (pc *PodAdmissionControl) processAdmitDeletePDPod(pod *core.Pod, ownerState return util.ARFail(err) } // Force Upgraded,Admit to Upgrade - if memberUtils.NeedForceUpgrade(tc) { + if memberUtils.NeedForceUpgrade(tc.Annotations) { klog.Infof("tc[%s/%s] is force upgraded, admit to delete pod[%s/%s]", namespace, tcName, namespace, name) return util.ARSuccess() } From a38bb0e9e97ac4a98b7fd85fa8e7b375ed02f9b5 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 19 Aug 2020 10:18:45 +0800 Subject: [PATCH 13/37] fix some bugs --- hack/update-crd-groups.sh | 1 + manifests/crd.yaml | 8056 +---------------- manifests/dm/dm-cluster.yaml | 29 + .../dmcluster/dm_cluster_controller.go | 7 +- .../member/dm_master_member_manager.go | 52 +- 5 files changed, 128 insertions(+), 8017 deletions(-) create mode 100644 manifests/dm/dm-cluster.yaml diff --git a/hack/update-crd-groups.sh b/hack/update-crd-groups.sh index 5770c064b1..28eb18cc44 100755 --- a/hack/update-crd-groups.sh +++ b/hack/update-crd-groups.sh @@ -33,6 +33,7 @@ export GO111MODULE=on go install github.com/pingcap/tidb-operator/cmd/to-crdgen to-crdgen generate tidbcluster > $crd_target +to-crdgen generate dmcluster > $crd_target to-crdgen generate backup >> $crd_target to-crdgen generate restore >> $crd_target to-crdgen generate backupschedule >> $crd_target diff --git a/manifests/crd.yaml b/manifests/crd.yaml index 9fc07e5a29..00a8d38196 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -3,69 +3,14 @@ apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: creationTimestamp: null - name: tidbclusters.pingcap.com + name: dmclusters.pingcap.com spec: - additionalPrinterColumns: - - JSONPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - JSONPath: .status.pd.image - description: The image for PD cluster - name: PD - type: string - - JSONPath: .spec.pd.requests.storage - description: The storage size specified for PD node - name: Storage - type: string - - JSONPath: .status.pd.statefulSet.readyReplicas - description: The desired replicas number of PD cluster - name: Ready - type: integer - - JSONPath: .spec.pd.replicas - description: The desired replicas number of PD cluster - name: Desire - type: integer - - JSONPath: .status.tikv.image - description: The image for TiKV cluster - name: TiKV - type: string - - JSONPath: .spec.tikv.requests.storage - description: The storage size specified for TiKV node - name: Storage - type: string - - JSONPath: .status.tikv.statefulSet.readyReplicas - description: The ready replicas number of TiKV cluster - name: Ready - type: integer - - JSONPath: .spec.tikv.replicas - description: The desired replicas number of TiKV cluster - name: Desire - type: integer - - JSONPath: .status.tidb.image - description: The image for TiDB cluster - name: TiDB - type: string - - JSONPath: .status.tidb.statefulSet.readyReplicas - description: The ready replicas number of TiDB cluster - name: Ready - type: integer - - JSONPath: .spec.tidb.replicas - description: The desired replicas number of TiDB cluster - name: Desire - type: integer - - JSONPath: .status.conditions[?(@.type=="Ready")].message - name: Status - priority: 1 - type: string - - JSONPath: .metadata.creationTimestamp - name: Age - type: date group: pingcap.com names: - kind: TidbCluster - plural: tidbclusters + kind: DMCluster + plural: dmclusters shortNames: - - tc + - dc scope: Namespaced validation: openAPIV3Schema: @@ -332,35 +277,15 @@ spec: type: object annotations: type: object - cluster: + discovery: properties: - name: - type: string - namespace: + address: type: string required: - - name - type: object - configUpdateStrategy: - type: string - discovery: - properties: - limits: - type: object - requests: - type: object + - address type: object - enableDynamicConfiguration: - type: boolean enablePVReclaim: type: boolean - helper: - properties: - image: - type: string - imagePullPolicy: - type: string - type: object hostNetwork: type: boolean imagePullPolicy: @@ -372,11 +297,7 @@ spec: type: string type: object type: array - nodeSelector: - type: object - paused: - type: boolean - pd: + master: properties: additionalContainers: items: @@ -1717,210 +1638,25 @@ spec: type: string config: properties: - auto-compaction-mode: - type: string - auto-compaction-retention-v2: - type: string - cluster-version: - type: string - dashboard: - properties: - enable-telemetry: - type: boolean - internal-proxy: - type: boolean - public-path-prefix: - type: string - tidb-cacert-path: - type: string - tidb-cert-path: - type: string - tidb-key-path: - type: string - type: object - election-interval: - type: string - enable-grpc-gateway: - type: boolean - enable-prevote: - type: boolean - force-new-cluster: - type: boolean - label-property: - type: object - lease: - format: int64 - type: integer - log: - properties: - development: - type: boolean - disable-caller: - type: boolean - disable-error-verbose: - type: boolean - disable-stacktrace: - type: boolean - disable-timestamp: - type: boolean - file: - properties: - filename: - type: string - log-rotate: - type: boolean - max-backups: - format: int32 - type: integer - max-days: - format: int32 - type: integer - max-size: - format: int32 - type: integer - type: object - format: - type: string - level: - type: string - type: object log-file: type: string - log-level: - type: string - metric: - properties: - address: - type: string - interval: - type: string - job: - type: string - type: object - namespace: - type: object - namespace-classifier: - type: string - pd-server: - properties: - metric-storage: - type: string - use-region-storage: - type: string - type: object - quota-backend-bytes: + log-format: type: string - replication: - properties: - enable-placement-rules: - type: string - max-replicas: - format: int64 - type: integer - strictly-match-label: - type: string - type: object - schedule: - properties: - disable-location-replacement: - type: string - disable-make-up-replica: - type: string - disable-namespace-relocation: - type: string - disable-raft-learner: - type: string - disable-remove-down-replica: - type: string - disable-remove-extra-replica: - type: string - disable-replace-offline-replica: - type: string - enable-cross-table-merge: - type: string - enable-one-way-merge: - type: string - high-space-ratio: - format: double - type: number - hot-region-cache-hits-threshold: - format: int64 - type: integer - hot-region-schedule-limit: - format: int64 - type: integer - leader-schedule-limit: - format: int64 - type: integer - low-space-ratio: - format: double - type: number - max-merge-region-keys: - format: int64 - type: integer - max-merge-region-size: - format: int64 - type: integer - max-pending-peer-count: - format: int64 - type: integer - max-snapshot-count: - format: int64 - type: integer - max-store-down-time: - type: string - merge-schedule-limit: - format: int64 - type: integer - patrol-region-interval: - type: string - region-schedule-limit: - format: int64 - type: integer - replica-schedule-limit: - format: int64 - type: integer - schedulers-payload: - type: object - schedulers-v2: - items: - properties: - args: - items: - type: string - type: array - disable: - type: boolean - type: - type: string - type: object - type: array - split-merge-interval: - type: string - tolerant-size-ratio: - format: double - type: number - type: object - security: - properties: - cacert-path: - type: string - cert-path: - type: string - key-path: - type: string - type: object - tikv-interval: + log-level: type: string - tso-save-interval: + rpc-rate-burst: + format: int32 + type: integer + rpc-rate-limit: + format: double + type: number + rpc-timeout: type: string type: object configUpdateStrategy: type: string dataSubDir: type: string - enableDashboardInternalProxy: - type: boolean env: items: properties: @@ -2054,30 +1790,12 @@ spec: type: object schedulerName: type: string - service: - properties: - annotations: - type: object - clusterIP: - type: string - loadBalancerIP: - type: string - loadBalancerSourceRanges: - items: - type: string - type: array - portName: - type: string - type: - type: string - type: object + service: {} storageClassName: type: string terminationGracePeriodSeconds: format: int64 type: integer - tlsClientSecretName: - type: string tolerations: items: properties: @@ -2099,9 +1817,38 @@ spec: required: - replicas type: object + nodeSelector: + type: object + paused: + type: boolean priorityClassName: type: string - pump: + pvReclaimPolicy: + type: string + schedulerName: + type: string + timezone: + type: string + tlsCluster: {} + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + worker: properties: additionalContainers: items: @@ -3441,9 +3188,31 @@ spec: baseImage: type: string config: + properties: + cert-allowed-cn: + items: + type: string + type: array + keepalive-ttl: + format: int64 + type: integer + log-file: + type: string + log-format: + type: string + log-level: + type: string + ssl-ca: + type: string + ssl-cert: + type: string + ssl-key: + type: string type: object configUpdateStrategy: type: string + dataSubDir: + type: string env: items: properties: @@ -3600,7689 +3369,8 @@ spec: required: - replicas type: object - pvReclaimPolicy: - type: string - schedulerName: - type: string - ticdc: - properties: - additionalContainers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - properties: - limits: - type: object - requests: - type: object - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - name - - devicePath - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - name - - mountPath - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - additionalVolumes: - items: - properties: - awsElasticBlockStore: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - azureDisk: - properties: - cachingMode: - type: string - diskName: - type: string - diskURI: - type: string - fsType: - type: string - kind: - type: string - readOnly: - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - properties: - readOnly: - type: boolean - secretName: - type: string - shareName: - type: string - required: - - secretName - - shareName - type: object - cephfs: - properties: - monitors: - items: - type: string - type: array - path: - type: string - readOnly: - type: boolean - secretFile: - type: string - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - type: object - cinder: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeID: - type: string - required: - - volumeID - type: object - configMap: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - csi: - properties: - driver: - type: string - fsType: - type: string - nodePublishSecretRef: - properties: - name: - type: string - type: object - readOnly: - type: boolean - volumeAttributes: - type: object - required: - - driver - type: object - downwardAPI: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - properties: - medium: - type: string - sizeLimit: {} - type: object - fc: - properties: - fsType: - type: string - lun: - format: int32 - type: integer - readOnly: - type: boolean - targetWWNs: - items: - type: string - type: array - wwids: - items: - type: string - type: array - type: object - flexVolume: - properties: - driver: - type: string - fsType: - type: string - options: - type: object - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - required: - - driver - type: object - flocker: - properties: - datasetName: - type: string - datasetUUID: - type: string - type: object - gcePersistentDisk: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - pdName: - type: string - readOnly: - type: boolean - required: - - pdName - type: object - gitRepo: - properties: - directory: - type: string - repository: - type: string - revision: - type: string - required: - - repository - type: object - glusterfs: - properties: - endpoints: - type: string - path: - type: string - readOnly: - type: boolean - required: - - endpoints - - path - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - iscsi: - properties: - chapAuthDiscovery: - type: boolean - chapAuthSession: - type: boolean - fsType: - type: string - initiatorName: - type: string - iqn: - type: string - iscsiInterface: - type: string - lun: - format: int32 - type: integer - portals: - items: - type: string - type: array - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - targetPortal: - type: string - required: - - targetPortal - - iqn - - lun - type: object - name: - type: string - nfs: - properties: - path: - type: string - readOnly: - type: boolean - server: - type: string - required: - - server - - path - type: object - persistentVolumeClaim: - properties: - claimName: - type: string - readOnly: - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - properties: - fsType: - type: string - pdID: - type: string - required: - - pdID - type: object - portworxVolume: - properties: - fsType: - type: string - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - projected: - properties: - defaultMode: - format: int32 - type: integer - sources: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - serviceAccountToken: - properties: - audience: - type: string - expirationSeconds: - format: int64 - type: integer - path: - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - properties: - group: - type: string - readOnly: - type: boolean - registry: - type: string - tenant: - type: string - user: - type: string - volume: - type: string - required: - - registry - - volume - type: object - rbd: - properties: - fsType: - type: string - image: - type: string - keyring: - type: string - monitors: - items: - type: string - type: array - pool: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - - image - type: object - scaleIO: - properties: - fsType: - type: string - gateway: - type: string - protectionDomain: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - sslEnabled: - type: boolean - storageMode: - type: string - storagePool: - type: string - system: - type: string - volumeName: - type: string - required: - - gateway - - system - - secretRef - type: object - secret: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - optional: - type: boolean - secretName: - type: string - type: object - storageos: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeName: - type: string - volumeNamespace: - type: string - type: object - vsphereVolume: - properties: - fsType: - type: string - storagePolicyID: - type: string - storagePolicyName: - type: string - volumePath: - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - affinity: - properties: - nodeAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - preference: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - format: int32 - type: integer - required: - - weight - - preference - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - properties: - nodeSelectorTerms: - items: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - annotations: - type: object - baseImage: - type: string - config: - properties: - gcTTL: - format: int32 - type: integer - logFile: - type: string - logLevel: - type: string - timezone: - type: string - type: object - configUpdateStrategy: - type: string - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - hostNetwork: - type: boolean - imagePullPolicy: - type: string - imagePullSecrets: - items: - properties: - name: - type: string - type: object - type: array - limits: - type: object - nodeSelector: - type: object - podSecurityContext: - properties: - fsGroup: - format: int64 - type: integer - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - supplementalGroups: - items: - format: int64 - type: integer - type: array - sysctls: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - priorityClassName: - type: string - replicas: - format: int32 - type: integer - requests: - type: object - schedulerName: - type: string - serviceAccount: - type: string - terminationGracePeriodSeconds: - format: int64 - type: integer - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - version: - type: string - required: - - replicas - type: object - tidb: - properties: - additionalContainers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - properties: - limits: - type: object - requests: - type: object - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - name - - devicePath - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - name - - mountPath - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - additionalVolumes: - items: - properties: - awsElasticBlockStore: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - azureDisk: - properties: - cachingMode: - type: string - diskName: - type: string - diskURI: - type: string - fsType: - type: string - kind: - type: string - readOnly: - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - properties: - readOnly: - type: boolean - secretName: - type: string - shareName: - type: string - required: - - secretName - - shareName - type: object - cephfs: - properties: - monitors: - items: - type: string - type: array - path: - type: string - readOnly: - type: boolean - secretFile: - type: string - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - type: object - cinder: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeID: - type: string - required: - - volumeID - type: object - configMap: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - csi: - properties: - driver: - type: string - fsType: - type: string - nodePublishSecretRef: - properties: - name: - type: string - type: object - readOnly: - type: boolean - volumeAttributes: - type: object - required: - - driver - type: object - downwardAPI: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - properties: - medium: - type: string - sizeLimit: {} - type: object - fc: - properties: - fsType: - type: string - lun: - format: int32 - type: integer - readOnly: - type: boolean - targetWWNs: - items: - type: string - type: array - wwids: - items: - type: string - type: array - type: object - flexVolume: - properties: - driver: - type: string - fsType: - type: string - options: - type: object - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - required: - - driver - type: object - flocker: - properties: - datasetName: - type: string - datasetUUID: - type: string - type: object - gcePersistentDisk: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - pdName: - type: string - readOnly: - type: boolean - required: - - pdName - type: object - gitRepo: - properties: - directory: - type: string - repository: - type: string - revision: - type: string - required: - - repository - type: object - glusterfs: - properties: - endpoints: - type: string - path: - type: string - readOnly: - type: boolean - required: - - endpoints - - path - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - iscsi: - properties: - chapAuthDiscovery: - type: boolean - chapAuthSession: - type: boolean - fsType: - type: string - initiatorName: - type: string - iqn: - type: string - iscsiInterface: - type: string - lun: - format: int32 - type: integer - portals: - items: - type: string - type: array - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - targetPortal: - type: string - required: - - targetPortal - - iqn - - lun - type: object - name: - type: string - nfs: - properties: - path: - type: string - readOnly: - type: boolean - server: - type: string - required: - - server - - path - type: object - persistentVolumeClaim: - properties: - claimName: - type: string - readOnly: - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - properties: - fsType: - type: string - pdID: - type: string - required: - - pdID - type: object - portworxVolume: - properties: - fsType: - type: string - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - projected: - properties: - defaultMode: - format: int32 - type: integer - sources: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - serviceAccountToken: - properties: - audience: - type: string - expirationSeconds: - format: int64 - type: integer - path: - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - properties: - group: - type: string - readOnly: - type: boolean - registry: - type: string - tenant: - type: string - user: - type: string - volume: - type: string - required: - - registry - - volume - type: object - rbd: - properties: - fsType: - type: string - image: - type: string - keyring: - type: string - monitors: - items: - type: string - type: array - pool: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - - image - type: object - scaleIO: - properties: - fsType: - type: string - gateway: - type: string - protectionDomain: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - sslEnabled: - type: boolean - storageMode: - type: string - storagePool: - type: string - system: - type: string - volumeName: - type: string - required: - - gateway - - system - - secretRef - type: object - secret: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - optional: - type: boolean - secretName: - type: string - type: object - storageos: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeName: - type: string - volumeNamespace: - type: string - type: object - vsphereVolume: - properties: - fsType: - type: string - storagePolicyID: - type: string - storagePolicyName: - type: string - volumePath: - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - affinity: - properties: - nodeAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - preference: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - format: int32 - type: integer - required: - - weight - - preference - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - properties: - nodeSelectorTerms: - items: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - annotations: - type: object - baseImage: - type: string - binlogEnabled: - type: boolean - config: - properties: - alter-primary-key: - type: boolean - binlog: - properties: - binlog-socket: - type: string - enable: - type: boolean - ignore-error: - type: boolean - strategy: - type: string - write-timeout: - type: string - type: object - check-mb4-value-in-utf8: - type: boolean - compatible-kill-query: - type: boolean - cors: - type: string - delay-clean-table-lock: - format: int64 - type: integer - enable-batch-dml: - type: boolean - enable-dynamic-config: - type: boolean - enable-streaming: - type: boolean - enable-table-lock: - type: boolean - enable-telemetry: - type: boolean - experimental: - properties: - allow-auto-random: - type: boolean - allow-expression-index: - type: boolean - type: object - isolation-read: - properties: - engines: - items: - type: string - type: array - type: object - lease: - type: string - log: - properties: - disable-timestamp: - type: boolean - enable-error-stack: - type: boolean - enable-slow-log: - type: boolean - enable-timestamp: - type: boolean - expensive-threshold: - format: int32 - type: integer - file: - properties: - filename: - type: string - log-rotate: - type: boolean - max-backups: - format: int32 - type: integer - max-days: - format: int32 - type: integer - max-size: - format: int32 - type: integer - type: object - format: - type: string - level: - type: string - query-log-max-len: - format: int64 - type: integer - record-plan-in-slow-log: - format: int64 - type: integer - slow-query-file: - type: string - slow-threshold: - format: int64 - type: integer - type: object - lower-case-table-names: - format: int32 - type: integer - max-index-length: - format: int64 - type: integer - max-server-connections: - format: int64 - type: integer - mem-quota-query: - format: int64 - type: integer - new_collations_enabled_on_first_bootstrap: - type: boolean - oom-action: - type: string - oom-use-tmp-storage: - type: boolean - opentracing: - properties: - enable: - type: boolean - reporter: - properties: - buffer-flush-interval: - format: int64 - type: integer - local-agent-host-port: - type: string - log-spans: - type: boolean - queue-size: - format: int32 - type: integer - type: object - rpc-metrics: - type: boolean - sampler: - properties: - max-operations: - format: int32 - type: integer - param: - format: double - type: number - sampling-refresh-interval: - format: int64 - type: integer - sampling-server-url: - type: string - type: - type: string - type: object - type: object - performance: - properties: - agg-push-down-join: - type: boolean - bind-info-lease: - type: string - committer-concurrency: - format: int32 - type: integer - cross-join: - type: boolean - feedback-probability: - format: double - type: number - force-priority: - type: string - max-memory: - format: int64 - type: integer - max-procs: - format: int32 - type: integer - max-txn-ttl: - format: int64 - type: integer - pseudo-estimate-ratio: - format: double - type: number - query-feedback-limit: - format: int32 - type: integer - run-auto-analyze: - type: boolean - stats-lease: - type: string - stmt-count-limit: - format: int32 - type: integer - tcp-keep-alive: - type: boolean - txn-entry-count-limit: - format: int64 - type: integer - txn-total-size-limit: - format: int64 - type: integer - type: object - pessimistic-txn: - properties: - enable: - type: boolean - max-retry-count: - format: int32 - type: integer - type: object - plugin: - properties: - dir: - type: string - load: - type: string - type: object - prepared-plan-cache: - properties: - capacity: - format: int32 - type: integer - enabled: - type: boolean - memory-guard-ratio: - format: double - type: number - type: object - proxy-protocol: - properties: - header-timeout: - format: int32 - type: integer - networks: - type: string - type: object - repair-mode: - type: boolean - repair-table-list: - items: - type: string - type: array - run-ddl: - type: boolean - security: - properties: - cluster-ssl-ca: - type: string - cluster-ssl-cert: - type: string - cluster-ssl-key: - type: string - skip-grant-table: - type: boolean - ssl-ca: - type: string - ssl-cert: - type: string - ssl-key: - type: string - type: object - socket: - type: string - split-region-max-num: - format: int64 - type: integer - split-table: - type: boolean - status: - properties: - metrics-addr: - type: string - metrics-interval: - format: int32 - type: integer - record-db-qps: - type: boolean - report-status: - type: boolean - type: object - stmt-summary: - properties: - enable: - type: boolean - enable-internal-query: - type: boolean - history-size: - format: int32 - type: integer - max-sql-length: - format: int32 - type: integer - max-stmt-count: - format: int32 - type: integer - refresh-interval: - format: int32 - type: integer - type: object - tikv-client: - properties: - batch-wait-size: - format: int32 - type: integer - commit-timeout: - type: string - copr-cache: {} - grpc-connection-count: - format: int32 - type: integer - grpc-keepalive-time: - format: int32 - type: integer - grpc-keepalive-timeout: - format: int32 - type: integer - max-batch-size: - format: int32 - type: integer - max-batch-wait-time: - format: int64 - type: integer - max-txn-time-use: - format: int32 - type: integer - overload-threshold: - format: int32 - type: integer - region-cache-ttl: - format: int32 - type: integer - store-limit: - format: int64 - type: integer - store-liveness-timeout: - type: string - type: object - tmp-storage-path: - type: string - tmp-storage-quota: - format: int64 - type: integer - token-limit: - format: int32 - type: integer - treat-old-version-utf8-as-utf8mb4: - type: boolean - txn-local-latches: - properties: - capacity: - format: int32 - type: integer - enabled: - type: boolean - type: object - type: object - configUpdateStrategy: - type: string - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - hostNetwork: - type: boolean - imagePullPolicy: - type: string - imagePullSecrets: - items: - properties: - name: - type: string - type: object - type: array - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - type: object - limits: - type: object - maxFailoverCount: - format: int32 - type: integer - nodeSelector: - type: object - plugins: - items: - type: string - type: array - podSecurityContext: - properties: - fsGroup: - format: int64 - type: integer - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - supplementalGroups: - items: - format: int64 - type: integer - type: array - sysctls: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - priorityClassName: - type: string - replicas: - format: int32 - type: integer - requests: - type: object - schedulerName: - type: string - separateSlowLog: - type: boolean - service: - properties: - exposeStatus: - type: boolean - externalTrafficPolicy: - type: string - mysqlNodePort: - format: int32 - type: integer - statusNodePort: - format: int32 - type: integer - type: object - slowLogTailer: - properties: - limits: - type: object - requests: - type: object - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - tlsClient: {} - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - version: - type: string - required: - - replicas - type: object - tiflash: - properties: - additionalContainers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - properties: - limits: - type: object - requests: - type: object - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - name - - devicePath - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - name - - mountPath - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - additionalVolumes: - items: - properties: - awsElasticBlockStore: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - azureDisk: - properties: - cachingMode: - type: string - diskName: - type: string - diskURI: - type: string - fsType: - type: string - kind: - type: string - readOnly: - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - properties: - readOnly: - type: boolean - secretName: - type: string - shareName: - type: string - required: - - secretName - - shareName - type: object - cephfs: - properties: - monitors: - items: - type: string - type: array - path: - type: string - readOnly: - type: boolean - secretFile: - type: string - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - type: object - cinder: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeID: - type: string - required: - - volumeID - type: object - configMap: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - csi: - properties: - driver: - type: string - fsType: - type: string - nodePublishSecretRef: - properties: - name: - type: string - type: object - readOnly: - type: boolean - volumeAttributes: - type: object - required: - - driver - type: object - downwardAPI: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - properties: - medium: - type: string - sizeLimit: {} - type: object - fc: - properties: - fsType: - type: string - lun: - format: int32 - type: integer - readOnly: - type: boolean - targetWWNs: - items: - type: string - type: array - wwids: - items: - type: string - type: array - type: object - flexVolume: - properties: - driver: - type: string - fsType: - type: string - options: - type: object - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - required: - - driver - type: object - flocker: - properties: - datasetName: - type: string - datasetUUID: - type: string - type: object - gcePersistentDisk: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - pdName: - type: string - readOnly: - type: boolean - required: - - pdName - type: object - gitRepo: - properties: - directory: - type: string - repository: - type: string - revision: - type: string - required: - - repository - type: object - glusterfs: - properties: - endpoints: - type: string - path: - type: string - readOnly: - type: boolean - required: - - endpoints - - path - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - iscsi: - properties: - chapAuthDiscovery: - type: boolean - chapAuthSession: - type: boolean - fsType: - type: string - initiatorName: - type: string - iqn: - type: string - iscsiInterface: - type: string - lun: - format: int32 - type: integer - portals: - items: - type: string - type: array - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - targetPortal: - type: string - required: - - targetPortal - - iqn - - lun - type: object - name: - type: string - nfs: - properties: - path: - type: string - readOnly: - type: boolean - server: - type: string - required: - - server - - path - type: object - persistentVolumeClaim: - properties: - claimName: - type: string - readOnly: - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - properties: - fsType: - type: string - pdID: - type: string - required: - - pdID - type: object - portworxVolume: - properties: - fsType: - type: string - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - projected: - properties: - defaultMode: - format: int32 - type: integer - sources: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - serviceAccountToken: - properties: - audience: - type: string - expirationSeconds: - format: int64 - type: integer - path: - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - properties: - group: - type: string - readOnly: - type: boolean - registry: - type: string - tenant: - type: string - user: - type: string - volume: - type: string - required: - - registry - - volume - type: object - rbd: - properties: - fsType: - type: string - image: - type: string - keyring: - type: string - monitors: - items: - type: string - type: array - pool: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - - image - type: object - scaleIO: - properties: - fsType: - type: string - gateway: - type: string - protectionDomain: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - sslEnabled: - type: boolean - storageMode: - type: string - storagePool: - type: string - system: - type: string - volumeName: - type: string - required: - - gateway - - system - - secretRef - type: object - secret: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - optional: - type: boolean - secretName: - type: string - type: object - storageos: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeName: - type: string - volumeNamespace: - type: string - type: object - vsphereVolume: - properties: - fsType: - type: string - storagePolicyID: - type: string - storagePolicyName: - type: string - volumePath: - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - affinity: - properties: - nodeAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - preference: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - format: int32 - type: integer - required: - - weight - - preference - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - properties: - nodeSelectorTerms: - items: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - annotations: - type: object - baseImage: - type: string - config: - properties: - config: - properties: - flash: - properties: - compact_log_min_period: - format: int32 - type: integer - flash_cluster: - properties: - master_ttl: - format: int32 - type: integer - refresh_interval: - format: int32 - type: integer - update_rule_interval: - format: int32 - type: integer - type: object - overlap_threshold: - format: double - type: number - type: object - logger: - properties: - count: - format: int32 - type: integer - level: - type: string - size: - type: string - type: object - mark_cache_size: - format: int64 - type: integer - minmax_index_cache_size: - format: int64 - type: integer - path_realtime_mode: - type: boolean - type: object - type: object - configUpdateStrategy: - type: string - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - hostNetwork: - type: boolean - imagePullPolicy: - type: string - imagePullSecrets: - items: - properties: - name: - type: string - type: object - type: array - limits: - type: object - logTailer: - properties: - limits: - type: object - requests: - type: object - type: object - maxFailoverCount: - format: int32 - type: integer - nodeSelector: - type: object - podSecurityContext: - properties: - fsGroup: - format: int64 - type: integer - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - supplementalGroups: - items: - format: int64 - type: integer - type: array - sysctls: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - priorityClassName: - type: string - privileged: - type: boolean - replicas: - format: int32 - type: integer - requests: - type: object - schedulerName: - type: string - serviceAccount: - type: string - storageClaims: - items: - properties: - resources: - properties: - limits: - type: object - requests: - type: object - type: object - storageClassName: - type: string - type: object - type: array - terminationGracePeriodSeconds: - format: int64 - type: integer - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - version: - type: string - required: - - replicas - - storageClaims - type: object - tikv: - properties: - additionalContainers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - properties: - limits: - type: object - requests: - type: object - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: string - - type: integer - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: string - - type: integer - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - name - - devicePath - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - name - - mountPath - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - additionalVolumes: - items: - properties: - awsElasticBlockStore: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - azureDisk: - properties: - cachingMode: - type: string - diskName: - type: string - diskURI: - type: string - fsType: - type: string - kind: - type: string - readOnly: - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - properties: - readOnly: - type: boolean - secretName: - type: string - shareName: - type: string - required: - - secretName - - shareName - type: object - cephfs: - properties: - monitors: - items: - type: string - type: array - path: - type: string - readOnly: - type: boolean - secretFile: - type: string - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - type: object - cinder: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeID: - type: string - required: - - volumeID - type: object - configMap: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - csi: - properties: - driver: - type: string - fsType: - type: string - nodePublishSecretRef: - properties: - name: - type: string - type: object - readOnly: - type: boolean - volumeAttributes: - type: object - required: - - driver - type: object - downwardAPI: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - properties: - medium: - type: string - sizeLimit: {} - type: object - fc: - properties: - fsType: - type: string - lun: - format: int32 - type: integer - readOnly: - type: boolean - targetWWNs: - items: - type: string - type: array - wwids: - items: - type: string - type: array - type: object - flexVolume: - properties: - driver: - type: string - fsType: - type: string - options: - type: object - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - required: - - driver - type: object - flocker: - properties: - datasetName: - type: string - datasetUUID: - type: string - type: object - gcePersistentDisk: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - pdName: - type: string - readOnly: - type: boolean - required: - - pdName - type: object - gitRepo: - properties: - directory: - type: string - repository: - type: string - revision: - type: string - required: - - repository - type: object - glusterfs: - properties: - endpoints: - type: string - path: - type: string - readOnly: - type: boolean - required: - - endpoints - - path - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - iscsi: - properties: - chapAuthDiscovery: - type: boolean - chapAuthSession: - type: boolean - fsType: - type: string - initiatorName: - type: string - iqn: - type: string - iscsiInterface: - type: string - lun: - format: int32 - type: integer - portals: - items: - type: string - type: array - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - targetPortal: - type: string - required: - - targetPortal - - iqn - - lun - type: object - name: - type: string - nfs: - properties: - path: - type: string - readOnly: - type: boolean - server: - type: string - required: - - server - - path - type: object - persistentVolumeClaim: - properties: - claimName: - type: string - readOnly: - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - properties: - fsType: - type: string - pdID: - type: string - required: - - pdID - type: object - portworxVolume: - properties: - fsType: - type: string - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - projected: - properties: - defaultMode: - format: int32 - type: integer - sources: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - downwardAPI: - properties: - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - name: - type: string - optional: - type: boolean - type: object - serviceAccountToken: - properties: - audience: - type: string - expirationSeconds: - format: int64 - type: integer - path: - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - properties: - group: - type: string - readOnly: - type: boolean - registry: - type: string - tenant: - type: string - user: - type: string - volume: - type: string - required: - - registry - - volume - type: object - rbd: - properties: - fsType: - type: string - image: - type: string - keyring: - type: string - monitors: - items: - type: string - type: array - pool: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - - image - type: object - scaleIO: - properties: - fsType: - type: string - gateway: - type: string - protectionDomain: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - sslEnabled: - type: boolean - storageMode: - type: string - storagePool: - type: string - system: - type: string - volumeName: - type: string - required: - - gateway - - system - - secretRef - type: object - secret: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - optional: - type: boolean - secretName: - type: string - type: object - storageos: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeName: - type: string - volumeNamespace: - type: string - type: object - vsphereVolume: - properties: - fsType: - type: string - storagePolicyID: - type: string - storagePolicyName: - type: string - volumePath: - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - affinity: - properties: - nodeAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - preference: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - format: int32 - type: integer - required: - - weight - - preference - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - properties: - nodeSelectorTerms: - items: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - weight - - podAffinityTerm - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - annotations: - type: object - baseImage: - type: string - config: - properties: - backup: - properties: - num-threads: - format: int64 - type: integer - type: object - coprocessor: - properties: - batch-split-limit: - format: int64 - type: integer - region-max-keys: - format: int64 - type: integer - region-max-size: - type: string - region-split-keys: - format: int64 - type: integer - region-split-size: - type: string - split-region-on-table: - type: boolean - type: object - gc: - properties: - "\tbatch-keys": - format: int64 - type: integer - "\tmax-write-bytes-per-sec": - type: string - type: object - import: - properties: - import-dir: - type: string - max-open-engines: - format: int64 - type: integer - max-prepare-duration: - type: string - num-import-jobs: - format: int64 - type: integer - num-import-sst-jobs: - format: int64 - type: integer - num-threads: - format: int64 - type: integer - region-split-size: - type: string - stream-channel-window: - format: int64 - type: integer - upload-speed-limit: - type: string - type: object - log-file: - type: string - log-level: - type: string - log-rotation-size: - type: string - log-rotation-timespan: - type: string - panic-when-unexpected-key-or-data: - type: boolean - pd: - properties: - endpoints: - items: - type: string - type: array - retry-interval: - type: string - retry-log-every: - format: int64 - type: integer - retry-max-count: - format: int64 - type: integer - type: object - pessimistic-txn: - properties: - enabled: - type: boolean - pipelined: - type: boolean - wait-for-lock-timeout: - type: string - wake-up-delay-duration: - type: string - type: object - raftdb: - properties: - allow-concurrent-memtable-write: - type: boolean - bytes-per-sync: - type: string - compaction-readahead-size: - type: string - create-if-missing: - type: boolean - defaultcf: - properties: - block-based-bloom-filter: - type: boolean - block-cache-size: - type: string - block-size: - type: string - bloom-filter-bits-per-key: - format: int64 - type: integer - cache-index-and-filter-blocks: - type: boolean - compaction-pri: - format: int64 - type: integer - compaction-style: - format: int64 - type: integer - compression-per-level: - items: - type: string - type: array - disable-auto-compactions: - type: boolean - disable-block-cache: - type: boolean - dynamic-level-bytes: - type: boolean - enable-doubly-skiplist: - type: boolean - force-consistency-checks: - type: boolean - hard-pending-compaction-bytes-limit: - type: string - level0-file-num-compaction-trigger: - format: int64 - type: integer - level0-slowdown-writes-trigger: - format: int64 - type: integer - level0-stop-writes-trigger: - format: int64 - type: integer - max-bytes-for-level-base: - type: string - max-bytes-for-level-multiplier: - format: int64 - type: integer - max-compaction-bytes: - type: string - max-write-buffer-number: - format: int64 - type: integer - min-write-buffer-number-to-merge: - format: int64 - type: integer - num-levels: - format: int64 - type: integer - optimize-filters-for-hits: - type: boolean - pin-l0-filter-and-index-blocks: - type: boolean - prop-keys-index-distance: - format: int64 - type: integer - prop-size-index-distance: - format: int64 - type: integer - read-amp-bytes-per-bit: - format: int64 - type: integer - soft-pending-compaction-bytes-limit: - type: string - target-file-size-base: - type: string - titan: - properties: - blob-cache-size: - type: string - blob-file-compression: - type: string - blob-run-mode: - type: string - discardable-ratio: - format: double - type: number - gc-merge-rewrite: - type: boolean - level_merge: - type: boolean - max-gc-batch-size: - type: string - merge-small-file-threshold: - type: string - min-blob-size: - type: string - min-gc-batch-size: - type: string - sample-ratio: - format: double - type: number - type: object - use-bloom-filter: - type: boolean - whole-key-filtering: - type: boolean - write-buffer-size: - type: string - type: object - enable-pipelined-write: - type: boolean - enable-statistics: - type: boolean - info-log-dir: - type: string - info-log-keep-log-file-num: - format: int64 - type: integer - info-log-max-size: - type: string - info-log-roll-time: - type: string - max-background-jobs: - format: int64 - type: integer - max-manifest-file-size: - type: string - max-open-files: - format: int64 - type: integer - max-sub-compactions: - format: int64 - type: integer - max-total-wal-size: - type: string - stats-dump-period: - type: string - use-direct-io-for-flush-and-compaction: - type: boolean - wal-bytes-per-sync: - type: string - wal-dir: - type: string - wal-recovery-mode: - type: string - wal-size-limit: - type: string - wal-ttl-seconds: - format: int64 - type: integer - writable-file-max-buffer-size: - type: string - type: object - raftstore: - properties: - abnormal-leader-missing-duration: - type: string - allow-remove-leader: - type: boolean - apply-early: - type: boolean - apply-max-batch-size: - format: int64 - type: integer - apply-pool-size: - format: int64 - type: integer - apply-yield-duration: - type: string - clean-stale-peer-delay: - type: string - cleanup-import-sst-interval: - type: string - consistency-check-interval: - type: string - dev-assert: - type: boolean - hibernate-regions: - type: boolean - leader-transfer-max-log-lag: - format: int64 - type: integer - lock-cf-compact-bytes-threshold: - type: string - lock-cf-compact-interval: - type: string - max-leader-missing-duration: - type: string - max-peer-down-duration: - type: string - merge-check-tick-interval: - type: string - merge-max-log-gap: - format: int64 - type: integer - messages-per-tick: - format: int64 - type: integer - notify-capacity: - format: int64 - type: integer - pd-heartbeat-tick-interval: - type: string - pd-store-heartbeat-tick-interval: - type: string - peer-stale-state-check-interval: - type: string - perf-level: - format: int64 - type: integer - prevote: - type: boolean - raft-base-tick-interval: - type: string - raft-election-timeout-ticks: - format: int64 - type: integer - raft-entry-cache-life-time: - type: string - raft-entry-max-size: - type: string - raft-heartbeat-ticks: - format: int64 - type: integer - raft-log-gc-count-limit: - format: int64 - type: integer - raft-log-gc-size-limit: - type: string - raft-log-gc-threshold: - format: int64 - type: integer - raft-log-gc-tick-interval: - type: string - raft-max-inflight-msgs: - format: int64 - type: integer - raft-max-size-per-msg: - type: string - raft-reject-transfer-leader-duration: - type: string - raft-store-max-leader-lease: - type: string - region-compact-check-interval: - type: string - region-compact-check-step: - format: int64 - type: integer - region-compact-min-tombstones: - format: int64 - type: integer - region-compact-tombstones-percent: - format: int64 - type: integer - region-split-check-diff: - type: string - report-region-flow-interval: - type: string - right-derive-when-split: - type: boolean - snap-apply-batch-size: - type: string - snap-gc-timeout: - type: string - snap-mgr-gc-tick-interval: - type: string - split-region-check-tick-interval: - type: string - store-max-batch-size: - format: int64 - type: integer - store-pool-size: - format: int64 - type: integer - store-reschedule-duration: - type: string - sync-log: - type: boolean - use-delete-range: - type: boolean - type: object - readpool: - properties: - coprocessor: - properties: - high-concurrency: - format: int64 - type: integer - low-concurrency: - format: int64 - type: integer - max-tasks-per-worker-high: - format: int64 - type: integer - max-tasks-per-worker-low: - format: int64 - type: integer - max-tasks-per-worker-normal: - format: int64 - type: integer - normal-concurrency: - format: int64 - type: integer - stack-size: - type: string - use-unified-pool: - type: boolean - type: object - storage: - properties: - high-concurrency: - format: int64 - type: integer - low-concurrency: - format: int64 - type: integer - max-tasks-per-worker-high: - format: int64 - type: integer - max-tasks-per-worker-low: - format: int64 - type: integer - max-tasks-per-worker-normal: - format: int64 - type: integer - normal-concurrency: - format: int64 - type: integer - stack-size: - type: string - use-unified-pool: - type: boolean - type: object - unified: - properties: - max-tasks-per-worker: - format: int32 - type: integer - max-thread-count: - format: int32 - type: integer - min-thread-count: - format: int32 - type: integer - stack-size: - type: string - type: object - type: object - refresh-config-interval: - type: string - rocksdb: - properties: - auto-tuned: - type: boolean - bytes-per-sync: - type: string - compaction-readahead-size: - type: string - create-if-missing: - type: boolean - defaultcf: - properties: - block-based-bloom-filter: - type: boolean - block-cache-size: - type: string - block-size: - type: string - bloom-filter-bits-per-key: - format: int64 - type: integer - cache-index-and-filter-blocks: - type: boolean - compaction-pri: - format: int64 - type: integer - compaction-style: - format: int64 - type: integer - compression-per-level: - items: - type: string - type: array - disable-auto-compactions: - type: boolean - disable-block-cache: - type: boolean - dynamic-level-bytes: - type: boolean - enable-doubly-skiplist: - type: boolean - force-consistency-checks: - type: boolean - hard-pending-compaction-bytes-limit: - type: string - level0-file-num-compaction-trigger: - format: int64 - type: integer - level0-slowdown-writes-trigger: - format: int64 - type: integer - level0-stop-writes-trigger: - format: int64 - type: integer - max-bytes-for-level-base: - type: string - max-bytes-for-level-multiplier: - format: int64 - type: integer - max-compaction-bytes: - type: string - max-write-buffer-number: - format: int64 - type: integer - min-write-buffer-number-to-merge: - format: int64 - type: integer - num-levels: - format: int64 - type: integer - optimize-filters-for-hits: - type: boolean - pin-l0-filter-and-index-blocks: - type: boolean - prop-keys-index-distance: - format: int64 - type: integer - prop-size-index-distance: - format: int64 - type: integer - read-amp-bytes-per-bit: - format: int64 - type: integer - soft-pending-compaction-bytes-limit: - type: string - target-file-size-base: - type: string - titan: - properties: - blob-cache-size: - type: string - blob-file-compression: - type: string - blob-run-mode: - type: string - discardable-ratio: - format: double - type: number - gc-merge-rewrite: - type: boolean - level_merge: - type: boolean - max-gc-batch-size: - type: string - merge-small-file-threshold: - type: string - min-blob-size: - type: string - min-gc-batch-size: - type: string - sample-ratio: - format: double - type: number - type: object - use-bloom-filter: - type: boolean - whole-key-filtering: - type: boolean - write-buffer-size: - type: string - type: object - enable-pipelined-write: - type: boolean - enable-statistics: - type: boolean - info-log-dir: - type: string - info-log-keep-log-file-num: - format: int64 - type: integer - info-log-max-size: - type: string - info-log-roll-time: - type: string - lockcf: - properties: - block-based-bloom-filter: - type: boolean - block-cache-size: - type: string - block-size: - type: string - bloom-filter-bits-per-key: - format: int64 - type: integer - cache-index-and-filter-blocks: - type: boolean - compaction-pri: - format: int64 - type: integer - compaction-style: - format: int64 - type: integer - compression-per-level: - items: - type: string - type: array - disable-auto-compactions: - type: boolean - disable-block-cache: - type: boolean - dynamic-level-bytes: - type: boolean - enable-doubly-skiplist: - type: boolean - force-consistency-checks: - type: boolean - hard-pending-compaction-bytes-limit: - type: string - level0-file-num-compaction-trigger: - format: int64 - type: integer - level0-slowdown-writes-trigger: - format: int64 - type: integer - level0-stop-writes-trigger: - format: int64 - type: integer - max-bytes-for-level-base: - type: string - max-bytes-for-level-multiplier: - format: int64 - type: integer - max-compaction-bytes: - type: string - max-write-buffer-number: - format: int64 - type: integer - min-write-buffer-number-to-merge: - format: int64 - type: integer - num-levels: - format: int64 - type: integer - optimize-filters-for-hits: - type: boolean - pin-l0-filter-and-index-blocks: - type: boolean - prop-keys-index-distance: - format: int64 - type: integer - prop-size-index-distance: - format: int64 - type: integer - read-amp-bytes-per-bit: - format: int64 - type: integer - soft-pending-compaction-bytes-limit: - type: string - target-file-size-base: - type: string - titan: - properties: - blob-cache-size: - type: string - blob-file-compression: - type: string - blob-run-mode: - type: string - discardable-ratio: - format: double - type: number - gc-merge-rewrite: - type: boolean - level_merge: - type: boolean - max-gc-batch-size: - type: string - merge-small-file-threshold: - type: string - min-blob-size: - type: string - min-gc-batch-size: - type: string - sample-ratio: - format: double - type: number - type: object - use-bloom-filter: - type: boolean - whole-key-filtering: - type: boolean - write-buffer-size: - type: string - type: object - max-background-jobs: - format: int64 - type: integer - max-manifest-file-size: - type: string - max-open-files: - format: int64 - type: integer - max-sub-compactions: - format: int64 - type: integer - max-total-wal-size: - type: string - raftcf: - properties: - block-based-bloom-filter: - type: boolean - block-cache-size: - type: string - block-size: - type: string - bloom-filter-bits-per-key: - format: int64 - type: integer - cache-index-and-filter-blocks: - type: boolean - compaction-pri: - format: int64 - type: integer - compaction-style: - format: int64 - type: integer - compression-per-level: - items: - type: string - type: array - disable-auto-compactions: - type: boolean - disable-block-cache: - type: boolean - dynamic-level-bytes: - type: boolean - enable-doubly-skiplist: - type: boolean - force-consistency-checks: - type: boolean - hard-pending-compaction-bytes-limit: - type: string - level0-file-num-compaction-trigger: - format: int64 - type: integer - level0-slowdown-writes-trigger: - format: int64 - type: integer - level0-stop-writes-trigger: - format: int64 - type: integer - max-bytes-for-level-base: - type: string - max-bytes-for-level-multiplier: - format: int64 - type: integer - max-compaction-bytes: - type: string - max-write-buffer-number: - format: int64 - type: integer - min-write-buffer-number-to-merge: - format: int64 - type: integer - num-levels: - format: int64 - type: integer - optimize-filters-for-hits: - type: boolean - pin-l0-filter-and-index-blocks: - type: boolean - prop-keys-index-distance: - format: int64 - type: integer - prop-size-index-distance: - format: int64 - type: integer - read-amp-bytes-per-bit: - format: int64 - type: integer - soft-pending-compaction-bytes-limit: - type: string - target-file-size-base: - type: string - titan: - properties: - blob-cache-size: - type: string - blob-file-compression: - type: string - blob-run-mode: - type: string - discardable-ratio: - format: double - type: number - gc-merge-rewrite: - type: boolean - level_merge: - type: boolean - max-gc-batch-size: - type: string - merge-small-file-threshold: - type: string - min-blob-size: - type: string - min-gc-batch-size: - type: string - sample-ratio: - format: double - type: number - type: object - use-bloom-filter: - type: boolean - whole-key-filtering: - type: boolean - write-buffer-size: - type: string - type: object - rate-bytes-per-sec: - type: string - rate-limiter-mode: - format: int64 - type: integer - stats-dump-period: - type: string - titan: - properties: - dirname: - type: string - disable-gc: - type: boolean - enabled: - type: boolean - max-background-gc: - format: int64 - type: integer - purge-obsolete-files-period: - type: string - type: object - use-direct-io-for-flush-and-compaction: - type: boolean - wal-bytes-per-sync: - type: string - wal-recovery-mode: - format: int64 - type: integer - wal-size-limit: - type: string - wal-ttl-seconds: - format: int64 - type: integer - writable-file-max-buffer-size: - type: string - writecf: - properties: - block-based-bloom-filter: - type: boolean - block-cache-size: - type: string - block-size: - type: string - bloom-filter-bits-per-key: - format: int64 - type: integer - cache-index-and-filter-blocks: - type: boolean - compaction-pri: - format: int64 - type: integer - compaction-style: - format: int64 - type: integer - compression-per-level: - items: - type: string - type: array - disable-auto-compactions: - type: boolean - disable-block-cache: - type: boolean - dynamic-level-bytes: - type: boolean - enable-doubly-skiplist: - type: boolean - force-consistency-checks: - type: boolean - hard-pending-compaction-bytes-limit: - type: string - level0-file-num-compaction-trigger: - format: int64 - type: integer - level0-slowdown-writes-trigger: - format: int64 - type: integer - level0-stop-writes-trigger: - format: int64 - type: integer - max-bytes-for-level-base: - type: string - max-bytes-for-level-multiplier: - format: int64 - type: integer - max-compaction-bytes: - type: string - max-write-buffer-number: - format: int64 - type: integer - min-write-buffer-number-to-merge: - format: int64 - type: integer - num-levels: - format: int64 - type: integer - optimize-filters-for-hits: - type: boolean - pin-l0-filter-and-index-blocks: - type: boolean - prop-keys-index-distance: - format: int64 - type: integer - prop-size-index-distance: - format: int64 - type: integer - read-amp-bytes-per-bit: - format: int64 - type: integer - soft-pending-compaction-bytes-limit: - type: string - target-file-size-base: - type: string - titan: - properties: - blob-cache-size: - type: string - blob-file-compression: - type: string - blob-run-mode: - type: string - discardable-ratio: - format: double - type: number - gc-merge-rewrite: - type: boolean - level_merge: - type: boolean - max-gc-batch-size: - type: string - merge-small-file-threshold: - type: string - min-blob-size: - type: string - min-gc-batch-size: - type: string - sample-ratio: - format: double - type: number - type: object - use-bloom-filter: - type: boolean - whole-key-filtering: - type: boolean - write-buffer-size: - type: string - type: object - type: object - security: - properties: - ca-path: - type: string - cert-path: - type: string - cipher-file: - type: string - encryption: {} - key-path: - type: string - override-ssl-target: - type: string - type: object - server: - properties: - concurrent-recv-snap-limit: - format: int32 - type: integer - concurrent-send-snap-limit: - format: int32 - type: integer - enable-request-batch: - type: boolean - end-point-batch-row-limit: - format: int32 - type: integer - end-point-enable-batch-if-possible: - format: int32 - type: integer - end-point-recursion-limit: - format: int32 - type: integer - end-point-request-max-handle-duration: - type: string - end-point-stream-batch-row-limit: - format: int32 - type: integer - end-point-stream-channel-size: - format: int32 - type: integer - grpc-compression-type: - type: string - grpc-concurrency: - format: int32 - type: integer - grpc-concurrent-stream: - format: int32 - type: integer - grpc-keepalive-time: - type: string - grpc-keepalive-timeout: - type: string - grpc-memory-pool-quota: - type: string - grpc-raft-conn-num: - format: int32 - type: integer - grpc-stream-initial-window-size: - type: string - heavy-load-threshold: - format: int32 - type: integer - heavy-load-wait-duration: - type: string - labels: - type: object - request-batch-enable-cross-command: - type: boolean - request-batch-wait-duration: - type: string - snap-max-total-size: - type: string - snap-max-write-bytes-per-sec: - type: string - stats-concurrency: - format: int32 - type: integer - status-thread-pool-size: - type: string - type: object - slow-log-file: - type: string - slow-log-threshold: - type: string - storage: - properties: - block-cache: - properties: - capacity: - type: string - high-pri-pool-ratio: - format: double - type: number - memory-allocator: - type: string - num-shard-bits: - format: int64 - type: integer - shared: - type: boolean - strict-capacity-limit: - type: boolean - type: object - max-key-size: - format: int64 - type: integer - reserve-space: - type: string - scheduler-concurrency: - format: int64 - type: integer - scheduler-notify-capacity: - format: int64 - type: integer - scheduler-pending-write-threshold: - type: string - scheduler-worker-pool-size: - format: int64 - type: integer - type: object - type: object - configUpdateStrategy: - type: string - dataSubDir: - type: string - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: {} - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - hostNetwork: - type: boolean - imagePullPolicy: - type: string - imagePullSecrets: - items: - properties: - name: - type: string - type: object - type: array - limits: - type: object - maxFailoverCount: - format: int32 - type: integer - nodeSelector: - type: object - podSecurityContext: - properties: - fsGroup: - format: int64 - type: integer - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - supplementalGroups: - items: - format: int64 - type: integer - type: array - sysctls: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - priorityClassName: - type: string - privileged: - type: boolean - replicas: - format: int32 - type: integer - requests: - type: object - schedulerName: - type: string - serviceAccount: - type: string - storageClassName: - type: string - terminationGracePeriodSeconds: - format: int64 - type: integer - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - version: - type: string - required: - - replicas - type: object - timezone: - type: string - tlsCluster: {} - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - version: - type: string + required: + - discovery type: object type: object version: v1alpha1 diff --git a/manifests/dm/dm-cluster.yaml b/manifests/dm/dm-cluster.yaml new file mode 100644 index 0000000000..429131c0c4 --- /dev/null +++ b/manifests/dm/dm-cluster.yaml @@ -0,0 +1,29 @@ +# IT IS NOT SUITABLE FOR PRODUCTION USE. +# This YAML describes a basic TiDB cluster with minimum resource requirements, +# which should be able to run in any Kubernetes cluster with storage support. +apiVersion: pingcap.com/v1alpha1 +kind: DMCluster +metadata: + name: basic + namespace: lichunzhu +spec: + version: v2.0.0-beta.2 + pvReclaimPolicy: Delete + discovery: + address: "http://basic-discovery.lichunzhu.svc:10261" + master: + baseImage: pingcap/dm + replicas: 1 + # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used + # storageClassName: local-storage + requests: + storage: "1Gi" + config: {} + worker: + baseImage: pingcap/dm + replicas: 1 + # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used + # storageClassName: local-storage + requests: + storage: "1Gi" + config: {} diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index e09f0f53f0..d2c1afbbc2 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -17,9 +17,6 @@ import ( "fmt" "time" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/juju/errors" perrors "github.com/pingcap/errors" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" @@ -28,7 +25,10 @@ import ( "github.com/pingcap/tidb-operator/pkg/controller" "github.com/pingcap/tidb-operator/pkg/dmapi" mm "github.com/pingcap/tidb-operator/pkg/manager/member" + apps "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" kubeinformers "k8s.io/client-go/informers" @@ -39,7 +39,6 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" "k8s.io/klog" - "k8s.io/kubernetes/pkg/apis/apps" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 0422687f70..43e3028980 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -133,10 +133,7 @@ func (mmm *masterMemberManager) syncMasterServiceForDMCluster(dc *v1alpha1.DMClu if err != nil { return err } - annoEqual := util.IsSubMapOf(newSvc.Annotations, oldSvc.Annotations) - isOrphan := metav1.GetControllerOf(oldSvc) == nil - - if !equal || !annoEqual || isOrphan { + if !equal { svc := *oldSvc svc.Spec = newSvc.Spec err = controller.SetServiceLastAppliedConfigAnnotation(&svc) @@ -147,11 +144,6 @@ func (mmm *masterMemberManager) syncMasterServiceForDMCluster(dc *v1alpha1.DMClu for k, v := range newSvc.Annotations { svc.Annotations[k] = v } - // also override labels when adopt orphan - if isOrphan { - svc.OwnerReferences = newSvc.OwnerReferences - svc.Labels = newSvc.Labels - } _, err = mmm.svcControl.UpdateService(dc, &svc) return err } @@ -383,11 +375,6 @@ func (mmm *masterMemberManager) syncMasterConfigMap(dc *v1alpha1.DMCluster, set } func (mmm *masterMemberManager) getNewMasterServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Service { - svcSpec := dc.Spec.Master.Service - if svcSpec == nil { - return nil - } - ns := dc.Namespace dcName := dc.Name svcName := controller.DMMasterMemberName(dcName) @@ -401,7 +388,6 @@ func (mmm *masterMemberManager) getNewMasterServiceForDMCluster(dc *v1alpha1.DMC Port: 8261, TargetPort: intstr.FromInt(8261), Protocol: corev1.ProtocolTCP, - NodePort: svcSpec.GetMasterNodePort(), }, } masterSvc := &corev1.Service{ @@ -409,28 +395,35 @@ func (mmm *masterMemberManager) getNewMasterServiceForDMCluster(dc *v1alpha1.DMC Name: svcName, Namespace: ns, Labels: masterLabels, - Annotations: copyAnnotations(svcSpec.Annotations), OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, }, Spec: corev1.ServiceSpec{ - Type: svcSpec.Type, + Type: corev1.ServiceTypeClusterIP, Ports: ports, Selector: masterSelector.Labels(), }, } - if svcSpec.Type == corev1.ServiceTypeLoadBalancer { - if svcSpec.LoadBalancerIP != nil { - masterSvc.Spec.LoadBalancerIP = *svcSpec.LoadBalancerIP + svcSpec := dc.Spec.Master.Service + if svcSpec != nil { + if svcSpec.Type != "" { + masterSvc.Spec.Type = svcSpec.Type } - if svcSpec.LoadBalancerSourceRanges != nil { - masterSvc.Spec.LoadBalancerSourceRanges = svcSpec.LoadBalancerSourceRanges + masterSvc.ObjectMeta.Annotations = copyAnnotations(svcSpec.Annotations) + masterSvc.Spec.Ports[0].NodePort = svcSpec.GetMasterNodePort() + if svcSpec.Type == corev1.ServiceTypeLoadBalancer { + if svcSpec.LoadBalancerIP != nil { + masterSvc.Spec.LoadBalancerIP = *svcSpec.LoadBalancerIP + } + if svcSpec.LoadBalancerSourceRanges != nil { + masterSvc.Spec.LoadBalancerSourceRanges = svcSpec.LoadBalancerSourceRanges + } + } + if svcSpec.ExternalTrafficPolicy != nil { + masterSvc.Spec.ExternalTrafficPolicy = *svcSpec.ExternalTrafficPolicy + } + if svcSpec.ClusterIP != nil { + masterSvc.Spec.ClusterIP = *svcSpec.ClusterIP } - } - if svcSpec.ExternalTrafficPolicy != nil { - masterSvc.Spec.ExternalTrafficPolicy = *svcSpec.ExternalTrafficPolicy - } - if svcSpec.ClusterIP != nil { - masterSvc.Spec.ClusterIP = *svcSpec.ClusterIP } return masterSvc } @@ -438,7 +431,7 @@ func (mmm *masterMemberManager) getNewMasterServiceForDMCluster(dc *v1alpha1.DMC func getNewMasterHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Service { ns := dc.Namespace tcName := dc.Name - svcName := controller.DMMasterMemberName(tcName) + svcName := controller.DMMasterPeerMemberName(tcName) instanceName := dc.GetInstanceName() masterSelector := label.New().Instance(instanceName).DMMaster() masterLabels := masterSelector.Copy().UsedByPeer().Labels() @@ -693,6 +686,7 @@ func getMasterConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { if err != nil { return nil, err } + klog.Info("start to render dm-master start script") startScript, err := RenderDMMasterStartScript(&DMMasterStartScriptModel{ Scheme: dc.Scheme(), DataDir: filepath.Join(dmMasterDataVolumeMountPath, dc.Spec.Master.DataSubDir), From 850035c8343222ecd0408cfd673186ae3899f9e4 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 20 Aug 2020 14:05:17 +0800 Subject: [PATCH 14/37] fix ut --- pkg/apis/pingcap/v1alpha1/tidbcluster_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/pingcap/v1alpha1/tidbcluster_test.go b/pkg/apis/pingcap/v1alpha1/tidbcluster_test.go index df30ed523d..1d18a469e2 100644 --- a/pkg/apis/pingcap/v1alpha1/tidbcluster_test.go +++ b/pkg/apis/pingcap/v1alpha1/tidbcluster_test.go @@ -178,7 +178,7 @@ func TestComponentAccessor(t *testing.T) { testFn := func(test *testcase, t *testing.T) { t.Log(test.name) - accessor := &componentAccessorImpl{test.cluster, test.component} + accessor := buildTidbClusterComponentAccessor(test.cluster, test.component) test.expectFn(g, accessor) } affinity := &corev1.Affinity{ From cd3f5b431b603722f8f0528b84b6e22549c5fda8 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Mon, 24 Aug 2020 19:38:32 +0800 Subject: [PATCH 15/37] fix dm-master start --- examples/basic/tidb-cluster.yaml | 2 +- examples/basic/tidb-monitor.yaml | 2 +- hack/update-crd-groups.sh | 2 +- manifests/crd.yaml | 11288 ++++++++++++++++++++++++ manifests/dm/dm-cluster.yaml | 4 +- pkg/apis/pingcap/v1alpha1/register.go | 1 + pkg/controller/controller_utils.go | 7 +- pkg/discovery/server/server.go | 8 +- pkg/manager/member/template.go | 8 +- 9 files changed, 11307 insertions(+), 15 deletions(-) diff --git a/examples/basic/tidb-cluster.yaml b/examples/basic/tidb-cluster.yaml index 81684a6fc0..da4f4ba297 100644 --- a/examples/basic/tidb-cluster.yaml +++ b/examples/basic/tidb-cluster.yaml @@ -6,7 +6,7 @@ kind: TidbCluster metadata: name: basic spec: - version: v4.0.0 + version: v4.0.4 timezone: UTC pvReclaimPolicy: Delete discovery: {} diff --git a/examples/basic/tidb-monitor.yaml b/examples/basic/tidb-monitor.yaml index 78271c302b..7db8f90439 100644 --- a/examples/basic/tidb-monitor.yaml +++ b/examples/basic/tidb-monitor.yaml @@ -13,7 +13,7 @@ spec: version: 6.1.6 initializer: baseImage: pingcap/tidb-monitor-initializer - version: v4.0.0 + version: v4.0.4 reloader: baseImage: pingcap/tidb-monitor-reloader version: v1.0.1 diff --git a/hack/update-crd-groups.sh b/hack/update-crd-groups.sh index 28eb18cc44..1de6d7e534 100755 --- a/hack/update-crd-groups.sh +++ b/hack/update-crd-groups.sh @@ -33,7 +33,7 @@ export GO111MODULE=on go install github.com/pingcap/tidb-operator/cmd/to-crdgen to-crdgen generate tidbcluster > $crd_target -to-crdgen generate dmcluster > $crd_target +to-crdgen generate dmcluster >> $crd_target to-crdgen generate backup >> $crd_target to-crdgen generate restore >> $crd_target to-crdgen generate backupschedule >> $crd_target diff --git a/manifests/crd.yaml b/manifests/crd.yaml index 00a8d38196..5eceb7bdbc 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -1,6 +1,11294 @@ --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: tidbclusters.pingcap.com +spec: + additionalPrinterColumns: + - JSONPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - JSONPath: .status.pd.image + description: The image for PD cluster + name: PD + type: string + - JSONPath: .spec.pd.requests.storage + description: The storage size specified for PD node + name: Storage + type: string + - JSONPath: .status.pd.statefulSet.readyReplicas + description: The desired replicas number of PD cluster + name: Ready + type: integer + - JSONPath: .spec.pd.replicas + description: The desired replicas number of PD cluster + name: Desire + type: integer + - JSONPath: .status.tikv.image + description: The image for TiKV cluster + name: TiKV + type: string + - JSONPath: .spec.tikv.requests.storage + description: The storage size specified for TiKV node + name: Storage + type: string + - JSONPath: .status.tikv.statefulSet.readyReplicas + description: The ready replicas number of TiKV cluster + name: Ready + type: integer + - JSONPath: .spec.tikv.replicas + description: The desired replicas number of TiKV cluster + name: Desire + type: integer + - JSONPath: .status.tidb.image + description: The image for TiDB cluster + name: TiDB + type: string + - JSONPath: .status.tidb.statefulSet.readyReplicas + description: The ready replicas number of TiDB cluster + name: Ready + type: integer + - JSONPath: .spec.tidb.replicas + description: The desired replicas number of TiDB cluster + name: Desire + type: integer + - JSONPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: pingcap.com + names: + kind: TidbCluster + plural: tidbclusters + shortNames: + - tc + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + spec: + properties: + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + cluster: + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + configUpdateStrategy: + type: string + discovery: + properties: + limits: + type: object + requests: + type: object + type: object + enableDynamicConfiguration: + type: boolean + enablePVReclaim: + type: boolean + helper: + properties: + image: + type: string + imagePullPolicy: + type: string + type: object + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + nodeSelector: + type: object + paused: + type: boolean + pd: + properties: + additionalContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + limits: + type: object + requests: + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - name + - devicePath + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - name + - mountPath + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + additionalVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + readOnly: + type: boolean + volumeAttributes: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: {} + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + targetPortal: + type: string + required: + - targetPortal + - iqn + - lun + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - server + - path + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + - image + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - system + - secretRef + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + baseImage: + type: string + config: + properties: + auto-compaction-mode: + type: string + auto-compaction-retention-v2: + type: string + cluster-version: + type: string + dashboard: + properties: + enable-telemetry: + type: boolean + internal-proxy: + type: boolean + public-path-prefix: + type: string + tidb-cacert-path: + type: string + tidb-cert-path: + type: string + tidb-key-path: + type: string + type: object + election-interval: + type: string + enable-grpc-gateway: + type: boolean + enable-prevote: + type: boolean + force-new-cluster: + type: boolean + label-property: + type: object + lease: + format: int64 + type: integer + log: + properties: + development: + type: boolean + disable-caller: + type: boolean + disable-error-verbose: + type: boolean + disable-stacktrace: + type: boolean + disable-timestamp: + type: boolean + file: + properties: + filename: + type: string + log-rotate: + type: boolean + max-backups: + format: int32 + type: integer + max-days: + format: int32 + type: integer + max-size: + format: int32 + type: integer + type: object + format: + type: string + level: + type: string + type: object + log-file: + type: string + log-level: + type: string + metric: + properties: + address: + type: string + interval: + type: string + job: + type: string + type: object + namespace: + type: object + namespace-classifier: + type: string + pd-server: + properties: + metric-storage: + type: string + use-region-storage: + type: string + type: object + quota-backend-bytes: + type: string + replication: + properties: + enable-placement-rules: + type: string + max-replicas: + format: int64 + type: integer + strictly-match-label: + type: string + type: object + schedule: + properties: + disable-location-replacement: + type: string + disable-make-up-replica: + type: string + disable-namespace-relocation: + type: string + disable-raft-learner: + type: string + disable-remove-down-replica: + type: string + disable-remove-extra-replica: + type: string + disable-replace-offline-replica: + type: string + enable-cross-table-merge: + type: string + enable-one-way-merge: + type: string + high-space-ratio: + format: double + type: number + hot-region-cache-hits-threshold: + format: int64 + type: integer + hot-region-schedule-limit: + format: int64 + type: integer + leader-schedule-limit: + format: int64 + type: integer + low-space-ratio: + format: double + type: number + max-merge-region-keys: + format: int64 + type: integer + max-merge-region-size: + format: int64 + type: integer + max-pending-peer-count: + format: int64 + type: integer + max-snapshot-count: + format: int64 + type: integer + max-store-down-time: + type: string + merge-schedule-limit: + format: int64 + type: integer + patrol-region-interval: + type: string + region-schedule-limit: + format: int64 + type: integer + replica-schedule-limit: + format: int64 + type: integer + schedulers-payload: + type: object + schedulers-v2: + items: + properties: + args: + items: + type: string + type: array + disable: + type: boolean + type: + type: string + type: object + type: array + split-merge-interval: + type: string + tolerant-size-ratio: + format: double + type: number + type: object + security: + properties: + cacert-path: + type: string + cert-path: + type: string + key-path: + type: string + type: object + tikv-interval: + type: string + tso-save-interval: + type: string + type: object + configUpdateStrategy: + type: string + dataSubDir: + type: string + enableDashboardInternalProxy: + type: boolean + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + limits: + type: object + maxFailoverCount: + format: int32 + type: integer + nodeSelector: + type: object + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + replicas: + format: int32 + type: integer + requests: + type: object + schedulerName: + type: string + service: + properties: + annotations: + type: object + clusterIP: + type: string + loadBalancerIP: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + portName: + type: string + type: + type: string + type: object + storageClassName: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tlsClientSecretName: + type: string + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + required: + - replicas + type: object + priorityClassName: + type: string + pump: + properties: + additionalContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + limits: + type: object + requests: + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - name + - devicePath + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - name + - mountPath + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + additionalVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + readOnly: + type: boolean + volumeAttributes: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: {} + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + targetPortal: + type: string + required: + - targetPortal + - iqn + - lun + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - server + - path + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + - image + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - system + - secretRef + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + baseImage: + type: string + config: + type: object + configUpdateStrategy: + type: string + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + limits: + type: object + nodeSelector: + type: object + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + replicas: + format: int32 + type: integer + requests: + type: object + schedulerName: + type: string + storageClassName: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + required: + - replicas + type: object + pvReclaimPolicy: + type: string + schedulerName: + type: string + ticdc: + properties: + additionalContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + limits: + type: object + requests: + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - name + - devicePath + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - name + - mountPath + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + additionalVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + readOnly: + type: boolean + volumeAttributes: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: {} + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + targetPortal: + type: string + required: + - targetPortal + - iqn + - lun + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - server + - path + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + - image + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - system + - secretRef + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + baseImage: + type: string + config: + properties: + gcTTL: + format: int32 + type: integer + logFile: + type: string + logLevel: + type: string + timezone: + type: string + type: object + configUpdateStrategy: + type: string + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + limits: + type: object + nodeSelector: + type: object + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + replicas: + format: int32 + type: integer + requests: + type: object + schedulerName: + type: string + serviceAccount: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + required: + - replicas + type: object + tidb: + properties: + additionalContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + limits: + type: object + requests: + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - name + - devicePath + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - name + - mountPath + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + additionalVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + readOnly: + type: boolean + volumeAttributes: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: {} + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + targetPortal: + type: string + required: + - targetPortal + - iqn + - lun + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - server + - path + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + - image + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - system + - secretRef + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + baseImage: + type: string + binlogEnabled: + type: boolean + config: + properties: + alter-primary-key: + type: boolean + binlog: + properties: + binlog-socket: + type: string + enable: + type: boolean + ignore-error: + type: boolean + strategy: + type: string + write-timeout: + type: string + type: object + check-mb4-value-in-utf8: + type: boolean + compatible-kill-query: + type: boolean + cors: + type: string + delay-clean-table-lock: + format: int64 + type: integer + enable-batch-dml: + type: boolean + enable-dynamic-config: + type: boolean + enable-streaming: + type: boolean + enable-table-lock: + type: boolean + enable-telemetry: + type: boolean + experimental: + properties: + allow-auto-random: + type: boolean + allow-expression-index: + type: boolean + type: object + isolation-read: + properties: + engines: + items: + type: string + type: array + type: object + lease: + type: string + log: + properties: + disable-timestamp: + type: boolean + enable-error-stack: + type: boolean + enable-slow-log: + type: boolean + enable-timestamp: + type: boolean + expensive-threshold: + format: int32 + type: integer + file: + properties: + filename: + type: string + log-rotate: + type: boolean + max-backups: + format: int32 + type: integer + max-days: + format: int32 + type: integer + max-size: + format: int32 + type: integer + type: object + format: + type: string + level: + type: string + query-log-max-len: + format: int64 + type: integer + record-plan-in-slow-log: + format: int64 + type: integer + slow-query-file: + type: string + slow-threshold: + format: int64 + type: integer + type: object + lower-case-table-names: + format: int32 + type: integer + max-index-length: + format: int64 + type: integer + max-server-connections: + format: int64 + type: integer + mem-quota-query: + format: int64 + type: integer + new_collations_enabled_on_first_bootstrap: + type: boolean + oom-action: + type: string + oom-use-tmp-storage: + type: boolean + opentracing: + properties: + enable: + type: boolean + reporter: + properties: + buffer-flush-interval: + format: int64 + type: integer + local-agent-host-port: + type: string + log-spans: + type: boolean + queue-size: + format: int32 + type: integer + type: object + rpc-metrics: + type: boolean + sampler: + properties: + max-operations: + format: int32 + type: integer + param: + format: double + type: number + sampling-refresh-interval: + format: int64 + type: integer + sampling-server-url: + type: string + type: + type: string + type: object + type: object + performance: + properties: + agg-push-down-join: + type: boolean + bind-info-lease: + type: string + committer-concurrency: + format: int32 + type: integer + cross-join: + type: boolean + feedback-probability: + format: double + type: number + force-priority: + type: string + max-memory: + format: int64 + type: integer + max-procs: + format: int32 + type: integer + max-txn-ttl: + format: int64 + type: integer + pseudo-estimate-ratio: + format: double + type: number + query-feedback-limit: + format: int32 + type: integer + run-auto-analyze: + type: boolean + stats-lease: + type: string + stmt-count-limit: + format: int32 + type: integer + tcp-keep-alive: + type: boolean + txn-entry-count-limit: + format: int64 + type: integer + txn-total-size-limit: + format: int64 + type: integer + type: object + pessimistic-txn: + properties: + enable: + type: boolean + max-retry-count: + format: int32 + type: integer + type: object + plugin: + properties: + dir: + type: string + load: + type: string + type: object + prepared-plan-cache: + properties: + capacity: + format: int32 + type: integer + enabled: + type: boolean + memory-guard-ratio: + format: double + type: number + type: object + proxy-protocol: + properties: + header-timeout: + format: int32 + type: integer + networks: + type: string + type: object + repair-mode: + type: boolean + repair-table-list: + items: + type: string + type: array + run-ddl: + type: boolean + security: + properties: + cluster-ssl-ca: + type: string + cluster-ssl-cert: + type: string + cluster-ssl-key: + type: string + skip-grant-table: + type: boolean + ssl-ca: + type: string + ssl-cert: + type: string + ssl-key: + type: string + type: object + socket: + type: string + split-region-max-num: + format: int64 + type: integer + split-table: + type: boolean + status: + properties: + metrics-addr: + type: string + metrics-interval: + format: int32 + type: integer + record-db-qps: + type: boolean + report-status: + type: boolean + type: object + stmt-summary: + properties: + enable: + type: boolean + enable-internal-query: + type: boolean + history-size: + format: int32 + type: integer + max-sql-length: + format: int32 + type: integer + max-stmt-count: + format: int32 + type: integer + refresh-interval: + format: int32 + type: integer + type: object + tikv-client: + properties: + batch-wait-size: + format: int32 + type: integer + commit-timeout: + type: string + copr-cache: {} + grpc-connection-count: + format: int32 + type: integer + grpc-keepalive-time: + format: int32 + type: integer + grpc-keepalive-timeout: + format: int32 + type: integer + max-batch-size: + format: int32 + type: integer + max-batch-wait-time: + format: int64 + type: integer + max-txn-time-use: + format: int32 + type: integer + overload-threshold: + format: int32 + type: integer + region-cache-ttl: + format: int32 + type: integer + store-limit: + format: int64 + type: integer + store-liveness-timeout: + type: string + type: object + tmp-storage-path: + type: string + tmp-storage-quota: + format: int64 + type: integer + token-limit: + format: int32 + type: integer + treat-old-version-utf8-as-utf8mb4: + type: boolean + txn-local-latches: + properties: + capacity: + format: int32 + type: integer + enabled: + type: boolean + type: object + type: object + configUpdateStrategy: + type: string + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + limits: + type: object + maxFailoverCount: + format: int32 + type: integer + nodeSelector: + type: object + plugins: + items: + type: string + type: array + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + replicas: + format: int32 + type: integer + requests: + type: object + schedulerName: + type: string + separateSlowLog: + type: boolean + service: + properties: + exposeStatus: + type: boolean + externalTrafficPolicy: + type: string + mysqlNodePort: + format: int32 + type: integer + statusNodePort: + format: int32 + type: integer + type: object + slowLogTailer: + properties: + limits: + type: object + requests: + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tlsClient: {} + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + required: + - replicas + type: object + tiflash: + properties: + additionalContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + limits: + type: object + requests: + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - name + - devicePath + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - name + - mountPath + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + additionalVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + readOnly: + type: boolean + volumeAttributes: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: {} + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + targetPortal: + type: string + required: + - targetPortal + - iqn + - lun + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - server + - path + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + - image + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - system + - secretRef + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + baseImage: + type: string + config: + properties: + config: + properties: + flash: + properties: + compact_log_min_period: + format: int32 + type: integer + flash_cluster: + properties: + master_ttl: + format: int32 + type: integer + refresh_interval: + format: int32 + type: integer + update_rule_interval: + format: int32 + type: integer + type: object + overlap_threshold: + format: double + type: number + type: object + logger: + properties: + count: + format: int32 + type: integer + level: + type: string + size: + type: string + type: object + mark_cache_size: + format: int64 + type: integer + minmax_index_cache_size: + format: int64 + type: integer + path_realtime_mode: + type: boolean + type: object + type: object + configUpdateStrategy: + type: string + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + limits: + type: object + logTailer: + properties: + limits: + type: object + requests: + type: object + type: object + maxFailoverCount: + format: int32 + type: integer + nodeSelector: + type: object + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + privileged: + type: boolean + replicas: + format: int32 + type: integer + requests: + type: object + schedulerName: + type: string + serviceAccount: + type: string + storageClaims: + items: + properties: + resources: + properties: + limits: + type: object + requests: + type: object + type: object + storageClassName: + type: string + type: object + type: array + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + required: + - replicas + - storageClaims + type: object + tikv: + properties: + additionalContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + limits: + type: object + requests: + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: string + - type: integer + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: string + - type: integer + required: + - port + type: object + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - name + - devicePath + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - name + - mountPath + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + additionalVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + readOnly: + type: boolean + volumeAttributes: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: {} + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + targetPortal: + type: string + required: + - targetPortal + - iqn + - lun + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - server + - path + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + user: + type: string + required: + - monitors + - image + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - system + - secretRef + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - weight + - preference + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - weight + - podAffinityTerm + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + type: object + baseImage: + type: string + config: + properties: + backup: + properties: + num-threads: + format: int64 + type: integer + type: object + coprocessor: + properties: + batch-split-limit: + format: int64 + type: integer + region-max-keys: + format: int64 + type: integer + region-max-size: + type: string + region-split-keys: + format: int64 + type: integer + region-split-size: + type: string + split-region-on-table: + type: boolean + type: object + gc: + properties: + "\tbatch-keys": + format: int64 + type: integer + "\tmax-write-bytes-per-sec": + type: string + type: object + import: + properties: + import-dir: + type: string + max-open-engines: + format: int64 + type: integer + max-prepare-duration: + type: string + num-import-jobs: + format: int64 + type: integer + num-import-sst-jobs: + format: int64 + type: integer + num-threads: + format: int64 + type: integer + region-split-size: + type: string + stream-channel-window: + format: int64 + type: integer + upload-speed-limit: + type: string + type: object + log-file: + type: string + log-level: + type: string + log-rotation-size: + type: string + log-rotation-timespan: + type: string + panic-when-unexpected-key-or-data: + type: boolean + pd: + properties: + endpoints: + items: + type: string + type: array + retry-interval: + type: string + retry-log-every: + format: int64 + type: integer + retry-max-count: + format: int64 + type: integer + type: object + pessimistic-txn: + properties: + enabled: + type: boolean + pipelined: + type: boolean + wait-for-lock-timeout: + type: string + wake-up-delay-duration: + type: string + type: object + raftdb: + properties: + allow-concurrent-memtable-write: + type: boolean + bytes-per-sync: + type: string + compaction-readahead-size: + type: string + create-if-missing: + type: boolean + defaultcf: + properties: + block-based-bloom-filter: + type: boolean + block-cache-size: + type: string + block-size: + type: string + bloom-filter-bits-per-key: + format: int64 + type: integer + cache-index-and-filter-blocks: + type: boolean + compaction-pri: + format: int64 + type: integer + compaction-style: + format: int64 + type: integer + compression-per-level: + items: + type: string + type: array + disable-auto-compactions: + type: boolean + disable-block-cache: + type: boolean + dynamic-level-bytes: + type: boolean + enable-doubly-skiplist: + type: boolean + force-consistency-checks: + type: boolean + hard-pending-compaction-bytes-limit: + type: string + level0-file-num-compaction-trigger: + format: int64 + type: integer + level0-slowdown-writes-trigger: + format: int64 + type: integer + level0-stop-writes-trigger: + format: int64 + type: integer + max-bytes-for-level-base: + type: string + max-bytes-for-level-multiplier: + format: int64 + type: integer + max-compaction-bytes: + type: string + max-write-buffer-number: + format: int64 + type: integer + min-write-buffer-number-to-merge: + format: int64 + type: integer + num-levels: + format: int64 + type: integer + optimize-filters-for-hits: + type: boolean + pin-l0-filter-and-index-blocks: + type: boolean + prop-keys-index-distance: + format: int64 + type: integer + prop-size-index-distance: + format: int64 + type: integer + read-amp-bytes-per-bit: + format: int64 + type: integer + soft-pending-compaction-bytes-limit: + type: string + target-file-size-base: + type: string + titan: + properties: + blob-cache-size: + type: string + blob-file-compression: + type: string + blob-run-mode: + type: string + discardable-ratio: + format: double + type: number + gc-merge-rewrite: + type: boolean + level_merge: + type: boolean + max-gc-batch-size: + type: string + merge-small-file-threshold: + type: string + min-blob-size: + type: string + min-gc-batch-size: + type: string + sample-ratio: + format: double + type: number + type: object + use-bloom-filter: + type: boolean + whole-key-filtering: + type: boolean + write-buffer-size: + type: string + type: object + enable-pipelined-write: + type: boolean + enable-statistics: + type: boolean + info-log-dir: + type: string + info-log-keep-log-file-num: + format: int64 + type: integer + info-log-max-size: + type: string + info-log-roll-time: + type: string + max-background-jobs: + format: int64 + type: integer + max-manifest-file-size: + type: string + max-open-files: + format: int64 + type: integer + max-sub-compactions: + format: int64 + type: integer + max-total-wal-size: + type: string + stats-dump-period: + type: string + use-direct-io-for-flush-and-compaction: + type: boolean + wal-bytes-per-sync: + type: string + wal-dir: + type: string + wal-recovery-mode: + type: string + wal-size-limit: + type: string + wal-ttl-seconds: + format: int64 + type: integer + writable-file-max-buffer-size: + type: string + type: object + raftstore: + properties: + abnormal-leader-missing-duration: + type: string + allow-remove-leader: + type: boolean + apply-early: + type: boolean + apply-max-batch-size: + format: int64 + type: integer + apply-pool-size: + format: int64 + type: integer + apply-yield-duration: + type: string + clean-stale-peer-delay: + type: string + cleanup-import-sst-interval: + type: string + consistency-check-interval: + type: string + dev-assert: + type: boolean + hibernate-regions: + type: boolean + leader-transfer-max-log-lag: + format: int64 + type: integer + lock-cf-compact-bytes-threshold: + type: string + lock-cf-compact-interval: + type: string + max-leader-missing-duration: + type: string + max-peer-down-duration: + type: string + merge-check-tick-interval: + type: string + merge-max-log-gap: + format: int64 + type: integer + messages-per-tick: + format: int64 + type: integer + notify-capacity: + format: int64 + type: integer + pd-heartbeat-tick-interval: + type: string + pd-store-heartbeat-tick-interval: + type: string + peer-stale-state-check-interval: + type: string + perf-level: + format: int64 + type: integer + prevote: + type: boolean + raft-base-tick-interval: + type: string + raft-election-timeout-ticks: + format: int64 + type: integer + raft-entry-cache-life-time: + type: string + raft-entry-max-size: + type: string + raft-heartbeat-ticks: + format: int64 + type: integer + raft-log-gc-count-limit: + format: int64 + type: integer + raft-log-gc-size-limit: + type: string + raft-log-gc-threshold: + format: int64 + type: integer + raft-log-gc-tick-interval: + type: string + raft-max-inflight-msgs: + format: int64 + type: integer + raft-max-size-per-msg: + type: string + raft-reject-transfer-leader-duration: + type: string + raft-store-max-leader-lease: + type: string + region-compact-check-interval: + type: string + region-compact-check-step: + format: int64 + type: integer + region-compact-min-tombstones: + format: int64 + type: integer + region-compact-tombstones-percent: + format: int64 + type: integer + region-split-check-diff: + type: string + report-region-flow-interval: + type: string + right-derive-when-split: + type: boolean + snap-apply-batch-size: + type: string + snap-gc-timeout: + type: string + snap-mgr-gc-tick-interval: + type: string + split-region-check-tick-interval: + type: string + store-max-batch-size: + format: int64 + type: integer + store-pool-size: + format: int64 + type: integer + store-reschedule-duration: + type: string + sync-log: + type: boolean + use-delete-range: + type: boolean + type: object + readpool: + properties: + coprocessor: + properties: + high-concurrency: + format: int64 + type: integer + low-concurrency: + format: int64 + type: integer + max-tasks-per-worker-high: + format: int64 + type: integer + max-tasks-per-worker-low: + format: int64 + type: integer + max-tasks-per-worker-normal: + format: int64 + type: integer + normal-concurrency: + format: int64 + type: integer + stack-size: + type: string + use-unified-pool: + type: boolean + type: object + storage: + properties: + high-concurrency: + format: int64 + type: integer + low-concurrency: + format: int64 + type: integer + max-tasks-per-worker-high: + format: int64 + type: integer + max-tasks-per-worker-low: + format: int64 + type: integer + max-tasks-per-worker-normal: + format: int64 + type: integer + normal-concurrency: + format: int64 + type: integer + stack-size: + type: string + use-unified-pool: + type: boolean + type: object + unified: + properties: + max-tasks-per-worker: + format: int32 + type: integer + max-thread-count: + format: int32 + type: integer + min-thread-count: + format: int32 + type: integer + stack-size: + type: string + type: object + type: object + refresh-config-interval: + type: string + rocksdb: + properties: + auto-tuned: + type: boolean + bytes-per-sync: + type: string + compaction-readahead-size: + type: string + create-if-missing: + type: boolean + defaultcf: + properties: + block-based-bloom-filter: + type: boolean + block-cache-size: + type: string + block-size: + type: string + bloom-filter-bits-per-key: + format: int64 + type: integer + cache-index-and-filter-blocks: + type: boolean + compaction-pri: + format: int64 + type: integer + compaction-style: + format: int64 + type: integer + compression-per-level: + items: + type: string + type: array + disable-auto-compactions: + type: boolean + disable-block-cache: + type: boolean + dynamic-level-bytes: + type: boolean + enable-doubly-skiplist: + type: boolean + force-consistency-checks: + type: boolean + hard-pending-compaction-bytes-limit: + type: string + level0-file-num-compaction-trigger: + format: int64 + type: integer + level0-slowdown-writes-trigger: + format: int64 + type: integer + level0-stop-writes-trigger: + format: int64 + type: integer + max-bytes-for-level-base: + type: string + max-bytes-for-level-multiplier: + format: int64 + type: integer + max-compaction-bytes: + type: string + max-write-buffer-number: + format: int64 + type: integer + min-write-buffer-number-to-merge: + format: int64 + type: integer + num-levels: + format: int64 + type: integer + optimize-filters-for-hits: + type: boolean + pin-l0-filter-and-index-blocks: + type: boolean + prop-keys-index-distance: + format: int64 + type: integer + prop-size-index-distance: + format: int64 + type: integer + read-amp-bytes-per-bit: + format: int64 + type: integer + soft-pending-compaction-bytes-limit: + type: string + target-file-size-base: + type: string + titan: + properties: + blob-cache-size: + type: string + blob-file-compression: + type: string + blob-run-mode: + type: string + discardable-ratio: + format: double + type: number + gc-merge-rewrite: + type: boolean + level_merge: + type: boolean + max-gc-batch-size: + type: string + merge-small-file-threshold: + type: string + min-blob-size: + type: string + min-gc-batch-size: + type: string + sample-ratio: + format: double + type: number + type: object + use-bloom-filter: + type: boolean + whole-key-filtering: + type: boolean + write-buffer-size: + type: string + type: object + enable-pipelined-write: + type: boolean + enable-statistics: + type: boolean + info-log-dir: + type: string + info-log-keep-log-file-num: + format: int64 + type: integer + info-log-max-size: + type: string + info-log-roll-time: + type: string + lockcf: + properties: + block-based-bloom-filter: + type: boolean + block-cache-size: + type: string + block-size: + type: string + bloom-filter-bits-per-key: + format: int64 + type: integer + cache-index-and-filter-blocks: + type: boolean + compaction-pri: + format: int64 + type: integer + compaction-style: + format: int64 + type: integer + compression-per-level: + items: + type: string + type: array + disable-auto-compactions: + type: boolean + disable-block-cache: + type: boolean + dynamic-level-bytes: + type: boolean + enable-doubly-skiplist: + type: boolean + force-consistency-checks: + type: boolean + hard-pending-compaction-bytes-limit: + type: string + level0-file-num-compaction-trigger: + format: int64 + type: integer + level0-slowdown-writes-trigger: + format: int64 + type: integer + level0-stop-writes-trigger: + format: int64 + type: integer + max-bytes-for-level-base: + type: string + max-bytes-for-level-multiplier: + format: int64 + type: integer + max-compaction-bytes: + type: string + max-write-buffer-number: + format: int64 + type: integer + min-write-buffer-number-to-merge: + format: int64 + type: integer + num-levels: + format: int64 + type: integer + optimize-filters-for-hits: + type: boolean + pin-l0-filter-and-index-blocks: + type: boolean + prop-keys-index-distance: + format: int64 + type: integer + prop-size-index-distance: + format: int64 + type: integer + read-amp-bytes-per-bit: + format: int64 + type: integer + soft-pending-compaction-bytes-limit: + type: string + target-file-size-base: + type: string + titan: + properties: + blob-cache-size: + type: string + blob-file-compression: + type: string + blob-run-mode: + type: string + discardable-ratio: + format: double + type: number + gc-merge-rewrite: + type: boolean + level_merge: + type: boolean + max-gc-batch-size: + type: string + merge-small-file-threshold: + type: string + min-blob-size: + type: string + min-gc-batch-size: + type: string + sample-ratio: + format: double + type: number + type: object + use-bloom-filter: + type: boolean + whole-key-filtering: + type: boolean + write-buffer-size: + type: string + type: object + max-background-jobs: + format: int64 + type: integer + max-manifest-file-size: + type: string + max-open-files: + format: int64 + type: integer + max-sub-compactions: + format: int64 + type: integer + max-total-wal-size: + type: string + raftcf: + properties: + block-based-bloom-filter: + type: boolean + block-cache-size: + type: string + block-size: + type: string + bloom-filter-bits-per-key: + format: int64 + type: integer + cache-index-and-filter-blocks: + type: boolean + compaction-pri: + format: int64 + type: integer + compaction-style: + format: int64 + type: integer + compression-per-level: + items: + type: string + type: array + disable-auto-compactions: + type: boolean + disable-block-cache: + type: boolean + dynamic-level-bytes: + type: boolean + enable-doubly-skiplist: + type: boolean + force-consistency-checks: + type: boolean + hard-pending-compaction-bytes-limit: + type: string + level0-file-num-compaction-trigger: + format: int64 + type: integer + level0-slowdown-writes-trigger: + format: int64 + type: integer + level0-stop-writes-trigger: + format: int64 + type: integer + max-bytes-for-level-base: + type: string + max-bytes-for-level-multiplier: + format: int64 + type: integer + max-compaction-bytes: + type: string + max-write-buffer-number: + format: int64 + type: integer + min-write-buffer-number-to-merge: + format: int64 + type: integer + num-levels: + format: int64 + type: integer + optimize-filters-for-hits: + type: boolean + pin-l0-filter-and-index-blocks: + type: boolean + prop-keys-index-distance: + format: int64 + type: integer + prop-size-index-distance: + format: int64 + type: integer + read-amp-bytes-per-bit: + format: int64 + type: integer + soft-pending-compaction-bytes-limit: + type: string + target-file-size-base: + type: string + titan: + properties: + blob-cache-size: + type: string + blob-file-compression: + type: string + blob-run-mode: + type: string + discardable-ratio: + format: double + type: number + gc-merge-rewrite: + type: boolean + level_merge: + type: boolean + max-gc-batch-size: + type: string + merge-small-file-threshold: + type: string + min-blob-size: + type: string + min-gc-batch-size: + type: string + sample-ratio: + format: double + type: number + type: object + use-bloom-filter: + type: boolean + whole-key-filtering: + type: boolean + write-buffer-size: + type: string + type: object + rate-bytes-per-sec: + type: string + rate-limiter-mode: + format: int64 + type: integer + stats-dump-period: + type: string + titan: + properties: + dirname: + type: string + disable-gc: + type: boolean + enabled: + type: boolean + max-background-gc: + format: int64 + type: integer + purge-obsolete-files-period: + type: string + type: object + use-direct-io-for-flush-and-compaction: + type: boolean + wal-bytes-per-sync: + type: string + wal-recovery-mode: + format: int64 + type: integer + wal-size-limit: + type: string + wal-ttl-seconds: + format: int64 + type: integer + writable-file-max-buffer-size: + type: string + writecf: + properties: + block-based-bloom-filter: + type: boolean + block-cache-size: + type: string + block-size: + type: string + bloom-filter-bits-per-key: + format: int64 + type: integer + cache-index-and-filter-blocks: + type: boolean + compaction-pri: + format: int64 + type: integer + compaction-style: + format: int64 + type: integer + compression-per-level: + items: + type: string + type: array + disable-auto-compactions: + type: boolean + disable-block-cache: + type: boolean + dynamic-level-bytes: + type: boolean + enable-doubly-skiplist: + type: boolean + force-consistency-checks: + type: boolean + hard-pending-compaction-bytes-limit: + type: string + level0-file-num-compaction-trigger: + format: int64 + type: integer + level0-slowdown-writes-trigger: + format: int64 + type: integer + level0-stop-writes-trigger: + format: int64 + type: integer + max-bytes-for-level-base: + type: string + max-bytes-for-level-multiplier: + format: int64 + type: integer + max-compaction-bytes: + type: string + max-write-buffer-number: + format: int64 + type: integer + min-write-buffer-number-to-merge: + format: int64 + type: integer + num-levels: + format: int64 + type: integer + optimize-filters-for-hits: + type: boolean + pin-l0-filter-and-index-blocks: + type: boolean + prop-keys-index-distance: + format: int64 + type: integer + prop-size-index-distance: + format: int64 + type: integer + read-amp-bytes-per-bit: + format: int64 + type: integer + soft-pending-compaction-bytes-limit: + type: string + target-file-size-base: + type: string + titan: + properties: + blob-cache-size: + type: string + blob-file-compression: + type: string + blob-run-mode: + type: string + discardable-ratio: + format: double + type: number + gc-merge-rewrite: + type: boolean + level_merge: + type: boolean + max-gc-batch-size: + type: string + merge-small-file-threshold: + type: string + min-blob-size: + type: string + min-gc-batch-size: + type: string + sample-ratio: + format: double + type: number + type: object + use-bloom-filter: + type: boolean + whole-key-filtering: + type: boolean + write-buffer-size: + type: string + type: object + type: object + security: + properties: + ca-path: + type: string + cert-path: + type: string + cipher-file: + type: string + encryption: {} + key-path: + type: string + override-ssl-target: + type: string + type: object + server: + properties: + concurrent-recv-snap-limit: + format: int32 + type: integer + concurrent-send-snap-limit: + format: int32 + type: integer + enable-request-batch: + type: boolean + end-point-batch-row-limit: + format: int32 + type: integer + end-point-enable-batch-if-possible: + format: int32 + type: integer + end-point-recursion-limit: + format: int32 + type: integer + end-point-request-max-handle-duration: + type: string + end-point-stream-batch-row-limit: + format: int32 + type: integer + end-point-stream-channel-size: + format: int32 + type: integer + grpc-compression-type: + type: string + grpc-concurrency: + format: int32 + type: integer + grpc-concurrent-stream: + format: int32 + type: integer + grpc-keepalive-time: + type: string + grpc-keepalive-timeout: + type: string + grpc-memory-pool-quota: + type: string + grpc-raft-conn-num: + format: int32 + type: integer + grpc-stream-initial-window-size: + type: string + heavy-load-threshold: + format: int32 + type: integer + heavy-load-wait-duration: + type: string + labels: + type: object + request-batch-enable-cross-command: + type: boolean + request-batch-wait-duration: + type: string + snap-max-total-size: + type: string + snap-max-write-bytes-per-sec: + type: string + stats-concurrency: + format: int32 + type: integer + status-thread-pool-size: + type: string + type: object + slow-log-file: + type: string + slow-log-threshold: + type: string + storage: + properties: + block-cache: + properties: + capacity: + type: string + high-pri-pool-ratio: + format: double + type: number + memory-allocator: + type: string + num-shard-bits: + format: int64 + type: integer + shared: + type: boolean + strict-capacity-limit: + type: boolean + type: object + max-key-size: + format: int64 + type: integer + reserve-space: + type: string + scheduler-concurrency: + format: int64 + type: integer + scheduler-notify-capacity: + format: int64 + type: integer + scheduler-pending-write-threshold: + type: string + scheduler-worker-pool-size: + format: int64 + type: integer + type: object + type: object + configUpdateStrategy: + type: string + dataSubDir: + type: string + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: {} + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostNetwork: + type: boolean + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + limits: + type: object + maxFailoverCount: + format: int32 + type: integer + nodeSelector: + type: object + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + privileged: + type: boolean + replicas: + format: int32 + type: integer + requests: + type: object + schedulerName: + type: string + serviceAccount: + type: string + storageClassName: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + required: + - replicas + type: object + timezone: + type: string + tlsCluster: {} + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + version: + type: string + type: object + type: object + version: v1alpha1 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: creationTimestamp: null name: dmclusters.pingcap.com diff --git a/manifests/dm/dm-cluster.yaml b/manifests/dm/dm-cluster.yaml index 429131c0c4..350bffce0b 100644 --- a/manifests/dm/dm-cluster.yaml +++ b/manifests/dm/dm-cluster.yaml @@ -5,12 +5,12 @@ apiVersion: pingcap.com/v1alpha1 kind: DMCluster metadata: name: basic - namespace: lichunzhu + namespace: demo spec: version: v2.0.0-beta.2 pvReclaimPolicy: Delete discovery: - address: "http://basic-discovery.lichunzhu.svc:10261" + address: "http://basic-discovery.demo.svc:10261" master: baseImage: pingcap/dm replicas: 1 diff --git a/pkg/apis/pingcap/v1alpha1/register.go b/pkg/apis/pingcap/v1alpha1/register.go index 5e7e8dfa78..9861937fb8 100644 --- a/pkg/apis/pingcap/v1alpha1/register.go +++ b/pkg/apis/pingcap/v1alpha1/register.go @@ -51,6 +51,7 @@ func addKnownTypes(scheme *runtime.Scheme) error { Scheme = scheme scheme.AddKnownTypes(SchemeGroupVersion, &TidbCluster{}, + &DMCluster{}, &TidbClusterList{}, &Backup{}, &BackupList{}, diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index f3b41289c2..1827aa2067 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -40,6 +40,9 @@ var ( // controllerKind contains the schema.GroupVersionKind for tidbcluster controller type. ControllerKind = v1alpha1.SchemeGroupVersion.WithKind("TidbCluster") + // DMControllerKind contains the schema.GroupVersionKind for dmcluster controller type. + DMControllerKind = v1alpha1.SchemeGroupVersion.WithKind("DMCluster") + // BackupControllerKind contains the schema.GroupVersionKind for backup controller type. BackupControllerKind = v1alpha1.SchemeGroupVersion.WithKind("Backup") @@ -132,8 +135,8 @@ func GetDMOwnerRef(dc *v1alpha1.DMCluster) metav1.OwnerReference { controller := true blockOwnerDeletion := true return metav1.OwnerReference{ - APIVersion: ControllerKind.GroupVersion().String(), - Kind: ControllerKind.Kind, + APIVersion: DMControllerKind.GroupVersion().String(), + Kind: DMControllerKind.Kind, Name: dc.GetName(), UID: dc.GetUID(), Controller: &controller, diff --git a/pkg/discovery/server/server.go b/pkg/discovery/server/server.go index 9cc148ef74..d5f2ce822c 100644 --- a/pkg/discovery/server/server.go +++ b/pkg/discovery/server/server.go @@ -64,8 +64,8 @@ func (s *server) newHandler(req *restful.Request, resp *restful.Response) { data, err := base64.StdEncoding.DecodeString(encodedAdvertisePeerURL) if err != nil { klog.Errorf("failed to decode advertise-peer-url: %s, register-type is: %s", encodedAdvertisePeerURL, registerType) - if err := resp.WriteError(http.StatusInternalServerError, err); err != nil { - klog.Errorf("failed to writeError: %v", err) + if werr := resp.WriteError(http.StatusInternalServerError, err); werr != nil { + klog.Errorf("failed to writeError: %v", werr) } return } @@ -87,8 +87,8 @@ func (s *server) newHandler(req *restful.Request, resp *restful.Response) { } if err != nil { klog.Errorf("failed to discover: %s, %v, register-type is: %s", advertisePeerURL, err, registerType) - if err := resp.WriteError(http.StatusInternalServerError, err); err != nil { - klog.Errorf("failed to writeError: %v", err) + if werr := resp.WriteError(http.StatusInternalServerError, err); werr != nil { + klog.Errorf("failed to writeError: %v", werr) } return } diff --git a/pkg/manager/member/template.go b/pkg/manager/member/template.go index 5d818efca5..05bd68382f 100644 --- a/pkg/manager/member/template.go +++ b/pkg/manager/member/template.go @@ -397,7 +397,7 @@ POD_NAME=${POD_NAME:-$HOSTNAME} # the general form of variable PEER_SERVICE_NAME is: "-dm-master-peer" cluster_name=` + "`" + `echo ${PEER_SERVICE_NAME} | sed 's/-dm-master-peer//'` + "`" + ` -domain="${POD_NAME}.${PEER_SERVICE_NAME}.${NAMESPACE}.svc" +domain="${POD_NAME}.${PEER_SERVICE_NAME}" discovery_url={{ .DiscoveryURL }} encoded_domain_url=` + "`" + `echo ${domain}:8291 | base64 | tr "\n" " " | sed "s/ //g"` + "`" + ` @@ -427,8 +427,8 @@ ARGS="--data-dir={{ .DataDir }} \ --name=${POD_NAME} \ --peer-urls={{ .Scheme }}://0.0.0.0:8291 \ --advertise-peer-urls={{ .Scheme }}://${domain}:8291 \ ---client-urls={{ .Scheme }}://0.0.0.0:8261 \ ---advertise-client-urls={{ .Scheme }}://${domain}:8261 \ +--master-addr=0.0.0.0:8261 \ +--advertise-addr=${domain}:8261 \ --config=/etc/dm-master/dm-master.toml \ " @@ -443,7 +443,7 @@ join=${join%,} ARGS="${ARGS} --join=${join}" elif [[ ! -d {{ .DataDir }}/member/wal ]] then -until result=$(wget -qO- -T 3 http://${discovery_url}/new/${encoded_domain_url}/dm 2>/dev/null); do +until result=$(wget -qO- -T 3 ${discovery_url}/new/${encoded_domain_url}/dm 2>/dev/null); do echo "waiting for discovery service to return start args ..." sleep $((RANDOM % 5)) done From f4a641d808052f944671f90ca70ca30a5c346812 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Mon, 24 Aug 2020 20:55:36 +0800 Subject: [PATCH 16/37] fix dm-worker start bug --- pkg/dmapi/dmapi.go | 8 ++++---- pkg/dmapi/master_control.go | 2 +- pkg/label/label.go | 8 ++++++++ pkg/manager/member/dm_master_member_manager.go | 18 ++++++++---------- pkg/manager/member/dm_worker_member_manager.go | 10 +++++----- pkg/manager/member/template.go | 4 ++-- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index 2b8dfdf313..de4997fc6b 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -46,7 +46,7 @@ type ListMemberRespHeader struct { type MastersInfo struct { Name string `json:"name,omitempty"` - MemberID uint64 `json:"memberID,omitempty"` + MemberID string `json:"memberID,omitempty"` Alive bool `json:"alive,omitempty"` PeerURLs []string `json:"peerURLs,omitempty"` ClientURLs []string `json:"clientURLs,omitempty"` @@ -118,7 +118,7 @@ func (mc *masterClient) GetMasters() ([]*MastersInfo, error) { listMemberResp := &MastersResp{} err = json.Unmarshal(body, listMemberResp) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to unmarshal list masters resp: %s, err: %s", body, err) } if !listMemberResp.Result { return nil, fmt.Errorf("unable to list masters info, err: %s", listMemberResp.Msg) @@ -140,7 +140,7 @@ func (mc *masterClient) GetWorkers() ([]*WorkersInfo, error) { listMemberResp := &WorkerResp{} err = json.Unmarshal(body, listMemberResp) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to unmarshal list workers resp: %s, err: %s", body, err) } if !listMemberResp.Result { return nil, fmt.Errorf("unable to list workers info, err: %s", listMemberResp.Msg) @@ -162,7 +162,7 @@ func (mc *masterClient) GetLeader() (MembersLeader, error) { listMemberResp := &LeaderResp{} err = json.Unmarshal(body, listMemberResp) if err != nil { - return MembersLeader{}, err + return MembersLeader{}, fmt.Errorf("unable to unmarshal list leader resp: %s, err: %s", body, err) } if !listMemberResp.Result { return MembersLeader{}, fmt.Errorf("unable to get leader info, err: %s", listMemberResp.Msg) diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go index c4c8671fbe..0a08aa409b 100644 --- a/pkg/dmapi/master_control.go +++ b/pkg/dmapi/master_control.go @@ -82,7 +82,7 @@ func masterClientKey(scheme string, namespace Namespace, clusterName string) str // MasterClientURL builds the url of master client func MasterClientURL(namespace Namespace, clusterName string, scheme string) string { - return fmt.Sprintf("%s://%s-master.%s:8261", scheme, clusterName, string(namespace)) + return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, string(namespace)) } // FakeMasterControl implements a fake version of MasterControlInterface. diff --git a/pkg/label/label.go b/pkg/label/label.go index b110e9a9f0..e088f908fb 100644 --- a/pkg/label/label.go +++ b/pkg/label/label.go @@ -175,6 +175,14 @@ func New() Label { } } +// NewDM initialize a new Label for components of dm cluster +func NewDM() Label { + return Label{ + NameLabelKey: "dm-cluster", + ManagedByLabelKey: TiDBOperator, + } +} + // NewInitializer initialize a new Label for Jobs of TiDB initializer func NewInitializer() Label { return Label{ diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 43e3028980..c5025df3eb 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -17,7 +17,6 @@ import ( "fmt" "path" "path/filepath" - "strconv" "strings" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" @@ -316,21 +315,20 @@ func (mmm *masterMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set masterStatus := map[string]v1alpha1.MasterMember{} for _, master := range mastersInfo { id := master.MemberID - memberID := strconv.FormatUint(id, 10) var clientURL string if len(master.ClientURLs) > 0 { clientURL = master.ClientURLs[0] } name := master.Name if len(name) == 0 { - klog.Warningf("dm-master member: [%d] doesn't have a name, and can't get it from clientUrls: [%s], dm-master Info: [%v] in [%s/%s]", + klog.Warningf("dm-master member: [%s] doesn't have a name, and can't get it from clientUrls: [%s], dm-master Info: [%v] in [%s/%s]", id, master.ClientURLs, master, ns, dcName) continue } status := v1alpha1.MasterMember{ Name: name, - ID: memberID, + ID: id, ClientURL: clientURL, Health: master.Alive, } @@ -379,7 +377,7 @@ func (mmm *masterMemberManager) getNewMasterServiceForDMCluster(dc *v1alpha1.DMC dcName := dc.Name svcName := controller.DMMasterMemberName(dcName) instanceName := dc.GetInstanceName() - masterSelector := label.New().Instance(instanceName).DMMaster() + masterSelector := label.NewDM().Instance(instanceName).DMMaster() masterLabels := masterSelector.Copy().UsedByEndUser().Labels() ports := []corev1.ServicePort{ @@ -433,7 +431,7 @@ func getNewMasterHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Ser tcName := dc.Name svcName := controller.DMMasterPeerMemberName(tcName) instanceName := dc.GetInstanceName() - masterSelector := label.New().Instance(instanceName).DMMaster() + masterSelector := label.NewDM().Instance(instanceName).DMMaster() masterLabels := masterSelector.Copy().UsedByPeer().Labels() return &corev1.Service{ @@ -464,7 +462,7 @@ func (mmm *masterMemberManager) masterStatefulSetIsUpgrading(set *apps.StatefulS return true, nil } instanceName := dc.GetInstanceName() - selector, err := label.New(). + selector, err := label.NewDM(). Instance(instanceName). DMMaster(). Selector() @@ -555,7 +553,7 @@ func getNewMasterSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( return nil, fmt.Errorf("cannot parse storage request for dm-master, dmcluster %s/%s, error: %v", dc.Namespace, dc.Name, err) } - masterLabel := label.New().Instance(instanceName).DMMaster() + masterLabel := label.NewDM().Instance(instanceName).DMMaster() setName := controller.DMMasterMemberName(dcName) podAnnotations := CombineAnnotations(controller.AnnProm(8261), baseMasterSpec.Annotations()) stsAnnotations := getStsAnnotations(dc.Annotations, label.DMMasterLabelVal) @@ -686,7 +684,7 @@ func getMasterConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { if err != nil { return nil, err } - klog.Info("start to render dm-master start script") + startScript, err := RenderDMMasterStartScript(&DMMasterStartScriptModel{ Scheme: dc.Scheme(), DataDir: filepath.Join(dmMasterDataVolumeMountPath, dc.Spec.Master.DataSubDir), @@ -697,7 +695,7 @@ func getMasterConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { } instanceName := dc.GetInstanceName() - masterLabel := label.New().Instance(instanceName).DMMaster().Labels() + masterLabel := label.NewDM().Instance(instanceName).DMMaster().Labels() cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: controller.DMMasterMemberName(dc.Name), diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index 1bbac7671c..bd4bc0ce94 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -143,7 +143,7 @@ func getNewWorkerHeadlessServiceForDMCluster(dc *v1alpha1.DMCluster) *corev1.Ser dcName := dc.Name instanceName := dc.GetInstanceName() svcName := controller.DMWorkerPeerMemberName(dcName) - svcLabel := label.New().Instance(instanceName).DMWorker().Labels() + svcLabel := label.NewDM().Instance(instanceName).DMWorker().Labels() svc := corev1.Service{ ObjectMeta: metav1.ObjectMeta{ @@ -275,7 +275,7 @@ func (wmm *workerMemberManager) workerStatefulSetIsUpgrading(set *apps.StatefulS return true, nil } instanceName := dc.GetInstanceName() - selector, err := label.New(). + selector, err := label.NewDM(). Instance(instanceName). DMWorker(). Selector() @@ -368,7 +368,7 @@ func getNewWorkerSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( return nil, fmt.Errorf("cannot parse storage request for dm-worker, dmcluster %s/%s, error: %v", dc.Namespace, dc.Name, err) } - workerLabel := label.New().Instance(instanceName).DMWorker() + workerLabel := label.NewDM().Instance(instanceName).DMWorker() setName := controller.DMWorkerPeerMemberName(dcName) podAnnotations := CombineAnnotations(controller.AnnProm(8262), baseWorkerSpec.Annotations()) stsAnnotations := getStsAnnotations(dc.Annotations, label.DMWorkerLabelVal) @@ -496,14 +496,14 @@ func getWorkerConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { } startScript, err := RenderDMWorkerStartScript(&DMWorkerStartScriptModel{ DataDir: filepath.Join(dmWorkerDataVolumeMountPath, dc.Spec.Worker.DataSubDir), - MasterAddress: dc.Scheme() + "://" + controller.DMMasterMemberName(dc.Name) + ":8261", + MasterAddress: controller.DMMasterMemberName(dc.Name) + ":8261", }) if err != nil { return nil, err } instanceName := dc.GetInstanceName() - workerLabel := label.New().Instance(instanceName).DMWorker().Labels() + workerLabel := label.NewDM().Instance(instanceName).DMWorker().Labels() cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: controller.DMWorkerPeerMemberName(dc.Name), diff --git a/pkg/manager/member/template.go b/pkg/manager/member/template.go index 05bd68382f..311b0958d6 100644 --- a/pkg/manager/member/template.go +++ b/pkg/manager/member/template.go @@ -499,10 +499,10 @@ fi # Use HOSTNAME if POD_NAME is unset for backward compatibility. POD_NAME=${POD_NAME:-$HOSTNAME} +# TODO: dm-worker will support data-dir in the future ARGS="--join={{ .MasterAddress }} \ --advertise-addr=${POD_NAME}.${HEADLESS_SERVICE_NAME}.${NAMESPACE}.svc:8262 \ ---addr=0.0.0.0:8262 \ ---data-dir={{ .DataDir }} \ +--worker-addr=0.0.0.0:8262 \ --config=/etc/dm-worker/dm-worker.toml " From be4fd5e6f3739a8a3d090622829e16636872d7dd Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 13:41:27 +0800 Subject: [PATCH 17/37] add more column info --- manifests/crd.yaml | 43 ++++++++++++ manifests/dm/dm-cluster.yaml | 4 +- pkg/apis/pingcap/v1alpha1/types.go | 1 + pkg/discovery/discovery.go | 3 +- .../member/dm_worker_member_manager.go | 5 ++ pkg/util/crdutil.go | 68 +++++++++++++++++++ 6 files changed, 121 insertions(+), 3 deletions(-) diff --git a/manifests/crd.yaml b/manifests/crd.yaml index 9f76aa73ef..ba2f1de2f7 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -11293,6 +11293,49 @@ metadata: creationTimestamp: null name: dmclusters.pingcap.com spec: + additionalPrinterColumns: + - JSONPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - JSONPath: .status.master.image + description: The image for dm-master cluster + name: Master + type: string + - JSONPath: .spec.master.requests.storage + description: The storage size specified for dm-master node + name: Storage + type: string + - JSONPath: .status.master.statefulSet.readyReplicas + description: The desired replicas number of dm-master cluster + name: Ready + type: integer + - JSONPath: .spec.master.replicas + description: The desired replicas number of dm-master cluster + name: Desire + type: integer + - JSONPath: .status.worker.image + description: The image for dm-worker cluster + name: Worker + type: string + - JSONPath: .spec.worker.requests.storage + description: The storage size specified for dm-worker node + name: Storage + type: string + - JSONPath: .status.worker.statefulSet.readyReplicas + description: The ready replicas number of dm-worker cluster + name: Ready + type: integer + - JSONPath: .spec.worker.replicas + description: The desired replicas number of dm-worker cluster + name: Desire + type: integer + - JSONPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - JSONPath: .metadata.creationTimestamp + name: Age + type: date group: pingcap.com names: kind: DMCluster diff --git a/manifests/dm/dm-cluster.yaml b/manifests/dm/dm-cluster.yaml index 350bffce0b..0e3fc5e4c0 100644 --- a/manifests/dm/dm-cluster.yaml +++ b/manifests/dm/dm-cluster.yaml @@ -13,7 +13,7 @@ spec: address: "http://basic-discovery.demo.svc:10261" master: baseImage: pingcap/dm - replicas: 1 + replicas: 3 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage requests: @@ -21,7 +21,7 @@ spec: config: {} worker: baseImage: pingcap/dm - replicas: 1 + replicas: 3 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage requests: diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 3c3182ca7f..992f467a48 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -1752,6 +1752,7 @@ type WorkerStatus struct { Phase MemberPhase `json:"phase,omitempty"` StatefulSet *apps.StatefulSetStatus `json:"statefulSet,omitempty"` Members map[string]WorkerMember `json:"members,omitempty"` + Image string `json:"image,omitempty"` } // WorkerMember is dm-Worker member status diff --git a/pkg/discovery/discovery.go b/pkg/discovery/discovery.go index b9bffb3e40..a6f9cfa568 100644 --- a/pkg/discovery/discovery.go +++ b/pkg/discovery/discovery.go @@ -174,7 +174,8 @@ func (td *tidbDiscovery) DiscoverDM(advertisePeerUrl string) (string, error) { mastersArr := make([]string, 0) for _, master := range mastersInfos { - mastersArr = append(mastersArr, master.ClientURLs[0]) + memberURL := strings.ReplaceAll(master.PeerURLs[0], ":8291", ":8261") + mastersArr = append(mastersArr, memberURL) } delete(currentCluster.peers, podName) return fmt.Sprintf("--join=%s", strings.Join(mastersArr, ",")), nil diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index bd4bc0ce94..a5f905109b 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -267,6 +267,11 @@ func (wmm *workerMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set dc.Status.Worker.Synced = true dc.Status.Worker.Members = workerStatus + dc.Status.Worker.Image = "" + c := filterContainer(set, "dm-worker") + if c != nil { + dc.Status.Worker.Image = c.Image + } return nil } diff --git a/pkg/util/crdutil.go b/pkg/util/crdutil.go index f61ec774f4..6637957657 100644 --- a/pkg/util/crdutil.go +++ b/pkg/util/crdutil.go @@ -101,6 +101,66 @@ var ( Description: "The desired replicas number of TiDB cluster", JSONPath: ".spec.tidb.replicas", } + dmClusteradditionalPrinterColumns []extensionsobj.CustomResourceColumnDefinition + dmClusterReadyColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Ready", + Type: "string", + JSONPath: `.status.conditions[?(@.type=="Ready")].status`, + } + dmClusterStatusMessageColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Status", + Type: "string", + JSONPath: `.status.conditions[?(@.type=="Ready")].message`, + Priority: 1, + } + dmClusterMasterColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Master", + Type: "string", + Description: "The image for dm-master cluster", + JSONPath: ".status.master.image", + } + dmClusterMasterStorageColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Storage", + Type: "string", + Description: "The storage size specified for dm-master node", + JSONPath: ".spec.master.requests.storage", + } + dmClusterMasterReadyColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Ready", + Type: "integer", + Description: "The desired replicas number of dm-master cluster", + JSONPath: ".status.master.statefulSet.readyReplicas", + } + dmClusterMasterDesireColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Desire", + Type: "integer", + Description: "The desired replicas number of dm-master cluster", + JSONPath: ".spec.master.replicas", + } + dmClusterWorkerColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Worker", + Type: "string", + Description: "The image for dm-worker cluster", + JSONPath: ".status.worker.image", + } + dmClusterWorkerStorageColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Storage", + Type: "string", + Description: "The storage size specified for dm-worker node", + JSONPath: ".spec.worker.requests.storage", + } + dmClusterWorkerReadyColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Ready", + Type: "integer", + Description: "The ready replicas number of dm-worker cluster", + JSONPath: ".status.worker.statefulSet.readyReplicas", + } + dmClusterWorkerDesireColumn = extensionsobj.CustomResourceColumnDefinition{ + Name: "Desire", + Type: "integer", + Description: "The desired replicas number of dm-worker cluster", + JSONPath: ".spec.worker.replicas", + } backupAdditionalPrinterColumns []extensionsobj.CustomResourceColumnDefinition backupPathColumn = extensionsobj.CustomResourceColumnDefinition{ Name: "BackupPath", @@ -232,6 +292,11 @@ func init() { tidbClusterPDColumn, tidbClusterPDStorageColumn, tidbClusterPDReadyColumn, tidbClusterPDDesireColumn, tidbClusterTiKVColumn, tidbClusterTiKVStorageColumn, tidbClusterTiKVReadyColumn, tidbClusterTiKVDesireColumn, tidbClusterTiDBColumn, tidbClusterTiDBReadyColumn, tidbClusterTiDBDesireColumn, tidbClusterStatusMessageColumn, ageColumn) + dmClusteradditionalPrinterColumns = append(dmClusteradditionalPrinterColumns, + dmClusterReadyColumn, + dmClusterMasterColumn, dmClusterMasterStorageColumn, dmClusterMasterReadyColumn, dmClusterMasterDesireColumn, + dmClusterWorkerColumn, dmClusterWorkerStorageColumn, dmClusterWorkerReadyColumn, dmClusterWorkerDesireColumn, + dmClusterStatusMessageColumn, ageColumn) backupAdditionalPrinterColumns = append(backupAdditionalPrinterColumns, backupPathColumn, backupBackupSizeColumn, backupCommitTSColumn, backupStartedColumn, backupCompletedColumn, ageColumn) restoreAdditionalPrinterColumns = append(restoreAdditionalPrinterColumns, restoreStartedColumn, restoreCompletedColumn, restoreCommitTSColumn, ageColumn) bksAdditionalPrinterColumns = append(bksAdditionalPrinterColumns, bksScheduleColumn, bksMaxBackups, bksLastBackup, bksLastBackupTime, ageColumn) @@ -289,6 +354,9 @@ func addAdditionalPrinterColumnsForCRD(crd *extensionsobj.CustomResourceDefiniti case v1alpha1.DefaultCrdKinds.TiDBCluster.Kind: crd.Spec.AdditionalPrinterColumns = tidbClusteradditionalPrinterColumns break + case v1alpha1.DefaultCrdKinds.DMCluster.Kind: + crd.Spec.AdditionalPrinterColumns = dmClusteradditionalPrinterColumns + break case v1alpha1.DefaultCrdKinds.Backup.Kind: crd.Spec.AdditionalPrinterColumns = backupAdditionalPrinterColumns break From f7c70bd5443c5ae3f90efbb959480a3ca5992411 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 14:00:58 +0800 Subject: [PATCH 18/37] fix ut --- pkg/discovery/discovery_test.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go index dd1fda36ae..a318b1e920 100644 --- a/pkg/discovery/discovery_test.go +++ b/pkg/discovery/discovery_test.go @@ -608,7 +608,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8291"}, }, }, nil }, @@ -637,10 +637,10 @@ func TestDiscoveryDMDiscovery(t *testing.T) { getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - ClientURLs: []string{"demo-dm-master-0.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer:8291"}, }, { - ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8291"}, }, }, nil }, @@ -671,13 +671,13 @@ func TestDiscoveryDMDiscovery(t *testing.T) { getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - ClientURLs: []string{"demo-dm-master-0.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer:8291"}, }, { - ClientURLs: []string{"demo-dm-master-1.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer:8291"}, }, { - ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8291"}, }, }, nil }, @@ -706,16 +706,16 @@ func TestDiscoveryDMDiscovery(t *testing.T) { getMastersFn: func() ([]*dmapi.MastersInfo, error) { return []*dmapi.MastersInfo{ { - ClientURLs: []string{"demo-dm-master-0.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-0.demo-dm-master-peer:8291"}, }, { - ClientURLs: []string{"demo-dm-master-1.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-1.demo-dm-master-peer:8291"}, }, { - ClientURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-2.demo-dm-master-peer:8291"}, }, { - ClientURLs: []string{"demo-dm-master-3.demo-dm-master-peer:8261"}, + PeerURLs: []string{"demo-dm-master-3.demo-dm-master-peer:8291"}, }, }, nil }, From 08f469593a121b0bae7edb539f5224674cc11f9f Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 14:20:31 +0800 Subject: [PATCH 19/37] fix verify --- docs/api-references/docs.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 64a3b8a65f..a2c7c277d8 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -19000,6 +19000,16 @@ map[string]github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.WorkerMemb
    +image
    + +string + +
    +

    From e2249f98f32a3bdb2f8ac280d52775086c79900b Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 14:50:25 +0800 Subject: [PATCH 20/37] fix verify again --- .../member/dm_master_member_manager.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index c5025df3eb..7615ff5721 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -485,15 +485,16 @@ func (mmm *masterMemberManager) masterStatefulSetIsUpgrading(set *apps.StatefulS return false, nil } -func getDMFailureReplicas(dc *v1alpha1.DMCluster) int { - failureReplicas := 0 - for _, failureMember := range dc.Status.Master.FailureMembers { - if failureMember.MemberDeleted { - failureReplicas++ - } - } - return failureReplicas -} +// TODO: uncomment it after dm failover is supported +//func getDMFailureReplicas(dc *v1alpha1.DMCluster) int { +// failureReplicas := 0 +// for _, failureMember := range dc.Status.Master.FailureMembers { +// if failureMember.MemberDeleted { +// failureReplicas++ +// } +// } +// return failureReplicas +//} func getNewMasterSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) (*apps.StatefulSet, error) { ns := dc.Namespace From 161b862d30cf39b27b5f81aa6927ef9bcd7f77a3 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 18:05:54 +0800 Subject: [PATCH 21/37] address comments --- examples/dm/README.md | 65 +++++++++++++++++++ {manifests => examples}/dm/dm-cluster.yaml | 13 ++-- .../pingcap/v1alpha1/defaulting/dmcluster.go | 3 + pkg/apis/pingcap/v1alpha1/dmcluster.go | 40 +++++++++--- pkg/apis/pingcap/v1alpha1/register.go | 3 +- pkg/apis/pingcap/v1alpha1/types.go | 16 +++++ .../pingcap/v1alpha1/validation/validation.go | 13 +++- pkg/controller/controller_utils.go | 2 +- .../dmcluster/dm_cluster_condition_updater.go | 3 + .../dmcluster/dm_cluster_control.go | 7 +- .../dmcluster/dm_cluster_controller.go | 2 +- pkg/label/label.go | 2 + .../member/dm_master_member_manager.go | 16 ++++- .../member/dm_worker_member_manager.go | 22 +++++-- pkg/manager/member/template.go | 4 +- pkg/manager/member/utils.go | 2 + pkg/util/crdutil.go | 4 +- 17 files changed, 178 insertions(+), 39 deletions(-) create mode 100644 examples/dm/README.md rename {manifests => examples}/dm/dm-cluster.yaml (64%) diff --git a/examples/dm/README.md b/examples/dm/README.md new file mode 100644 index 0000000000..802052a055 --- /dev/null +++ b/examples/dm/README.md @@ -0,0 +1,65 @@ +# A Basic DM cluster + +> **Note:** +> +> This setup is for test or demo purpose only and **IS NOT** applicable for critical environment. Refer to the [Documents](https://pingcap.com/docs/stable/tidb-in-kubernetes/deploy/prerequisites/) for production setup. + +The following steps will create a DM cluster. + +**Prerequisites**: +- Has TiDB operator `v1.2.0` or higher version installed. [Doc](https://pingcap.com/docs/stable/tidb-in-kubernetes/deploy/tidb-operator/) +- Has default `StorageClass` configured, and there are enough PVs (by default, 6 PVs are required) of that storageClass: + + This could by verified by the following command: + + ```bash + > kubectl get storageclass + ``` + + The output is similar to this: + + ```bash + NAME PROVISIONER AGE + standard (default) kubernetes.io/gce-pd 1d + gold kubernetes.io/gce-pd 1d + ``` + + Alternatively, you could specify the storageClass explicitly by modifying `tidb-cluster.yaml`. + +## Install + +The following commands is assumed to be executed in this directory. + +Install the cluster: + +```bash +> kubectl -n apply -f ./ +``` + +Wait for cluster Pods ready: + +```bash +watch kubectl -n get pod +``` + +## Explore + +Explore the DM master interface: + +```bash +> kubectl -n port-forward svc/basic-dm-master 8261:8261 &>/tmp/pf-dm.log & +> dmctl --master-addr 127.0.0.1:8261 list-member +``` + +## Destroy + +```bash +> kubectl -n delete -f ./ +``` + +The PVCs used by DM cluster will not be deleted in the above process, therefore, the PVs will be not be released neither. You can delete PVCs and release the PVs by the following command: + +```bash +> kubectl -n delete pvc -l app.kubernetes.io/instance=basic,app.kubernetes.io/managed-by=tidb-operator +``` + diff --git a/manifests/dm/dm-cluster.yaml b/examples/dm/dm-cluster.yaml similarity index 64% rename from manifests/dm/dm-cluster.yaml rename to examples/dm/dm-cluster.yaml index 0e3fc5e4c0..5ccacbe0f2 100644 --- a/manifests/dm/dm-cluster.yaml +++ b/examples/dm/dm-cluster.yaml @@ -1,6 +1,3 @@ -# IT IS NOT SUITABLE FOR PRODUCTION USE. -# This YAML describes a basic TiDB cluster with minimum resource requirements, -# which should be able to run in any Kubernetes cluster with storage support. apiVersion: pingcap.com/v1alpha1 kind: DMCluster metadata: @@ -10,20 +7,20 @@ spec: version: v2.0.0-beta.2 pvReclaimPolicy: Delete discovery: - address: "http://basic-discovery.demo.svc:10261" + address: "http://basic-discovery.demo:10261" master: baseImage: pingcap/dm replicas: 3 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage - requests: - storage: "1Gi" + storageSize: "1Gi" + requests: {} config: {} worker: baseImage: pingcap/dm replicas: 3 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage - requests: - storage: "1Gi" + storageSize: "1Gi" + requests: {} config: {} diff --git a/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go b/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go index 315af8388a..f26c3c0720 100644 --- a/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go @@ -67,4 +67,7 @@ func setWorkerSpecDefault(dc *v1alpha1.DMCluster) { dc.Spec.Worker.BaseImage = defaultWorkerImage } } + if dc.Spec.Worker.MaxFailoverCount == nil { + dc.Spec.Worker.MaxFailoverCount = pointer.Int32Ptr(3) + } } diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go index 8fc4cc5abd..84c9883d24 100644 --- a/pkg/apis/pingcap/v1alpha1/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -16,10 +16,10 @@ package v1alpha1 import ( "fmt" "strings" - - "github.com/pingcap/tidb-operator/pkg/label" ) +var latestImageVersion = "latest" + func (dc *DMCluster) Scheme() string { if dc.IsTLSClusterEnabled() { return "https" @@ -27,6 +27,14 @@ func (dc *DMCluster) Scheme() string { return "http" } +func (dc *DMCluster) Timezone() string { + tz := dc.Spec.Timezone + if tz == "" { + return defaultTimeZone + } + return tz +} + func (dc *DMCluster) IsTLSClusterEnabled() bool { return dc.Spec.TLSCluster != nil && dc.Spec.TLSCluster.Enabled } @@ -44,6 +52,19 @@ func (dc *DMCluster) MasterAllMembersReady() bool { return true } +func (dc *DMCluster) WorkerAllMembersReady() bool { + if int(dc.WorkerStsDesiredReplicas()) != len(dc.Status.Worker.Members) { + return false + } + + for _, member := range dc.Status.Worker.Members { + if member.Stage == "offline" { + return false + } + } + return true +} + func (dc *DMCluster) MasterStsDesiredReplicas() int32 { return dc.Spec.Master.Replicas + int32(len(dc.Status.Master.FailureMembers)) } @@ -57,13 +78,6 @@ func (dc *DMCluster) WorkerStsDesiredReplicas() int32 { } func (dc *DMCluster) GetInstanceName() string { - labels := dc.ObjectMeta.GetLabels() - // Keep backward compatibility for helm. - // This introduce a hidden danger that change this label will trigger rolling-update of most of the components - // TODO(aylei): disallow mutation of this label or adding this label with value other than the cluster name in ValidateUpdate() - if inst, ok := labels[label.InstanceLabelKey]; ok { - return inst - } return dc.Name } @@ -76,6 +90,9 @@ func (dc *DMCluster) MasterImage() string { if version == nil { version = &dc.Spec.Version } + if version == nil { + version = &latestImageVersion + } image = fmt.Sprintf("%s:%s", baseImage, *version) } return image @@ -90,6 +107,9 @@ func (dc *DMCluster) WorkerImage() string { if version == nil { version = &dc.Spec.Version } + if version == nil { + version = &latestImageVersion + } image = fmt.Sprintf("%s:%s", baseImage, *version) } return image @@ -102,7 +122,7 @@ func (dc *DMCluster) MasterVersion() string { return image[colonIdx+1:] } - return "latest" + return latestImageVersion } func (dc *DMCluster) MasterUpgrading() bool { diff --git a/pkg/apis/pingcap/v1alpha1/register.go b/pkg/apis/pingcap/v1alpha1/register.go index 9861937fb8..47d929fe6f 100644 --- a/pkg/apis/pingcap/v1alpha1/register.go +++ b/pkg/apis/pingcap/v1alpha1/register.go @@ -51,7 +51,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { Scheme = scheme scheme.AddKnownTypes(SchemeGroupVersion, &TidbCluster{}, - &DMCluster{}, &TidbClusterList{}, &Backup{}, &BackupList{}, @@ -71,6 +70,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &TiDBGroupList{}, &TiKVGroup{}, &TiKVGroupList{}, + &DMCluster{}, + &DMClusterList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 992f467a48..f3e2ead797 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -1617,6 +1617,11 @@ type MasterSpec struct { // +optional StorageClassName *string `json:"storageClassName,omitempty"` + // StorageSize is the request storage size for dm-master. + // Defaults to "10Gi". + // +optional + StorageSize string `json:"storageSize,omitempty"` + // Subdirectory within the volume to store dm-master Data. By default, the data // is stored in the root directory of volume which is mounted at // /var/lib/dm-master. @@ -1661,11 +1666,22 @@ type WorkerSpec struct { // +optional BaseImage string `json:"baseImage,omitempty"` + // MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. + // Optional: Defaults to 3 + // +kubebuilder:validation:Minimum=0 + // +optional + MaxFailoverCount *int32 `json:"maxFailoverCount,omitempty"` + // The storageClassName of the persistent volume for dm-worker data storage. // Defaults to Kubernetes default storage class. // +optional StorageClassName *string `json:"storageClassName,omitempty"` + // StorageSize is the request storage size for dm-worker. + // Defaults to "10Gi". + // +optional + StorageSize string `json:"storageSize,omitempty"` + // Subdirectory within the volume to store dm-worker Data. By default, the data // is stored in the root directory of volume which is mounted at // /var/lib/dm-worker. diff --git a/pkg/apis/pingcap/v1alpha1/validation/validation.go b/pkg/apis/pingcap/v1alpha1/validation/validation.go index 9ca665996a..37086176eb 100644 --- a/pkg/apis/pingcap/v1alpha1/validation/validation.go +++ b/pkg/apis/pingcap/v1alpha1/validation/validation.go @@ -51,7 +51,7 @@ func ValidateDMCluster(dc *v1alpha1.DMCluster) field.ErrorList { // validate metadata fldPath := field.NewPath("metadata") // validate metadata/annotations - allErrs = append(allErrs, validateAnnotations(dc.ObjectMeta.Annotations, fldPath.Child("annotations"))...) + allErrs = append(allErrs, validateDMAnnotations(dc.ObjectMeta.Annotations, fldPath.Child("annotations"))...) // validate spec allErrs = append(allErrs, validateDMClusterSpec(&dc.Spec, field.NewPath("spec"))...) return allErrs @@ -77,6 +77,15 @@ func validateAnnotations(anns map[string]string, fldPath *field.Path) field.Erro return allErrs } +func validateDMAnnotations(anns map[string]string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + allErrs = append(allErrs, apivalidation.ValidateAnnotations(anns, fldPath)...) + for _, key := range []string{label.AnnDMMasterDeleteSlots, label.AnnDMWorkerDeleteSlots} { + allErrs = append(allErrs, validateDeleteSlots(anns, key, fldPath.Child(key))...) + } + return allErrs +} + func validateTiDBClusterSpec(spec *v1alpha1.TidbClusterSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if spec.PD != nil { @@ -223,14 +232,12 @@ func validateDMClusterSpec(spec *v1alpha1.DMClusterSpec, fldPath *field.Path) fi func validateMasterSpec(spec *v1alpha1.MasterSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validateComponentSpec(&spec.ComponentSpec, fldPath)...) - allErrs = append(allErrs, validateRequestsStorage(spec.ResourceRequirements.Requests, fldPath)...) return allErrs } func validateWorkerSpec(spec *v1alpha1.WorkerSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validateComponentSpec(&spec.ComponentSpec, fldPath)...) - allErrs = append(allErrs, validateRequestsStorage(spec.ResourceRequirements.Requests, fldPath)...) return allErrs } diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index 1827aa2067..000f10f0a5 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -325,7 +325,7 @@ func DMMasterPeerMemberName(clusterName string) string { // DMWorkerPeerMemberName returns dm-worker peer service name func DMWorkerPeerMemberName(clusterName string) string { - return fmt.Sprintf("%s-dm-worker-peer", clusterName) + return fmt.Sprintf("%s-dm-worker", clusterName) } // AnnProm adds annotations for prometheus scraping metrics diff --git a/pkg/controller/dmcluster/dm_cluster_condition_updater.go b/pkg/controller/dmcluster/dm_cluster_condition_updater.go index be97cdf9f9..00c82b80f3 100644 --- a/pkg/controller/dmcluster/dm_cluster_condition_updater.go +++ b/pkg/controller/dmcluster/dm_cluster_condition_updater.go @@ -60,6 +60,9 @@ func (u *dmClusterConditionUpdater) updateReadyCondition(dc *v1alpha1.DMCluster) case !dc.MasterAllMembersReady(): reason = utildmcluster.MasterUnhealthy message = "dm-master(s) are not healthy" + case !dc.WorkerAllMembersReady(): + reason = utildmcluster.MasterUnhealthy + message = "some dm-worker(s) are not up yet" default: status = v1.ConditionTrue reason = utildmcluster.Ready diff --git a/pkg/controller/dmcluster/dm_cluster_control.go b/pkg/controller/dmcluster/dm_cluster_control.go index ea764cf13b..88bf417127 100644 --- a/pkg/controller/dmcluster/dm_cluster_control.go +++ b/pkg/controller/dmcluster/dm_cluster_control.go @@ -119,6 +119,7 @@ func (dcc *defaultDMClusterControl) validate(dc *v1alpha1.DMCluster) bool { } func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) error { + var errs []error // TODO: implement reclaimPolicyManager // syncing all PVs managed by operator's reclaim policy to Retain // if err := dcc.reclaimPolicyManager.Sync(dc); err != nil { @@ -155,7 +156,7 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // - scale out/in the dm-master cluster // - failover the dm-master cluster if err := dcc.masterMemberManager.Sync(dc); err != nil { - return err + errs = append(errs, err) } // works that should do to making the dm-worker cluster current state match the desired state: @@ -167,7 +168,7 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // - scale out/in the dm-worker cluster // - failover the dm-worker cluster if err := dcc.workerMemberManager.Sync(dc); err != nil { - return err + errs = append(errs, err) } // TODO: syncing labels for dm: syncing the labels from Pod to PVC and PV, these labels include: @@ -193,5 +194,5 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // syncing the some tidbcluster status attributes // - sync tidbmonitor reference // return dcc.tidbClusterStatusManager.Sync(dc) - return nil + return errorutils.NewAggregate(errs) } diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index d2c1afbbc2..f66853d799 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -348,7 +348,7 @@ func (dcc *Controller) resolveDMClusterFromSet(namespace string, set *apps.State // We can't look up by UID, so look up by Name and then verify UID. // Don't even try to look up by Name if it's the wrong Kind. - if controllerRef.Kind != controller.ControllerKind.Kind { + if controllerRef.Kind != controller.DMControllerKind.Kind { return nil } dc, err := dcc.dcLister.DMClusters(namespace).Get(controllerRef.Name) diff --git a/pkg/label/label.go b/pkg/label/label.go index e088f908fb..51868112de 100644 --- a/pkg/label/label.go +++ b/pkg/label/label.go @@ -106,6 +106,8 @@ const ( AnnTiFlashDeleteSlots = "tiflash.tidb.pingcap.com/delete-slots" // DMMasterDeleteSlots is annotation key of dm-master delete slots. AnnDMMasterDeleteSlots = "dm-master.tidb.pingcap.com/delete-slots" + // DMWorkerDeleteSlots is annotation key of dm-worker delete slots. + AnnDMWorkerDeleteSlots = "dm-worker.tidb.pingcap.com/delete-slots" // AnnTiDBLastAutoScalingTimestamp is annotation key of tidbcluster to indicate the last timestamp for tidb auto-scaling AnnTiDBLastAutoScalingTimestamp = "tidb.tidb.pingcap.com/last-autoscaling-timestamp" diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 7615ff5721..9574423b3a 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -29,6 +29,7 @@ import ( apps "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" v1 "k8s.io/client-go/listers/apps/v1" @@ -42,6 +43,8 @@ const ( dmMasterDataVolumeMountPath = "/var/lib/dm-master" // dmMasterClusterCertPath is where the cert for inter-cluster communication stored (if any) dmMasterClusterCertPath = "/var/lib/dm-master-tls" + // DefaultStorageSize is the default pvc request storage size for dm + DefaultStorageSize = "10Gi" ) type masterMemberManager struct { @@ -549,10 +552,19 @@ func getNewMasterSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( }) } - storageRequest, err := controller.ParseStorageRequest(dc.Spec.Master.Requests) + storageSize := DefaultStorageSize + if dc.Spec.Master.StorageSize != "" { + storageSize = dc.Spec.Master.StorageSize + } + rs, err := resource.ParseQuantity(storageSize) if err != nil { return nil, fmt.Errorf("cannot parse storage request for dm-master, dmcluster %s/%s, error: %v", dc.Namespace, dc.Name, err) } + storageRequest := corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: rs, + }, + } masterLabel := label.NewDM().Instance(instanceName).DMMaster() setName := controller.DMMasterMemberName(dcName) @@ -602,7 +614,7 @@ func getNewMasterSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( }, { Name: "TZ", - Value: dc.Spec.Timezone, + Value: dc.Timezone(), }, } diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index a5f905109b..de6808d898 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -18,24 +18,23 @@ import ( "path" "path/filepath" - "github.com/pingcap/tidb-operator/pkg/util" - - "k8s.io/utils/pointer" - "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/controller" "github.com/pingcap/tidb-operator/pkg/dmapi" "github.com/pingcap/tidb-operator/pkg/label" "github.com/pingcap/tidb-operator/pkg/manager" + "github.com/pingcap/tidb-operator/pkg/util" apps "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" v1 "k8s.io/client-go/listers/apps/v1" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" + "k8s.io/utils/pointer" ) const ( @@ -234,6 +233,8 @@ func (wmm *workerMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set } if upgrading { dc.Status.Worker.Phase = v1alpha1.UpgradePhase + } else if dc.WorkerStsDesiredReplicas() != *set.Spec.Replicas { + dc.Status.Worker.Phase = v1alpha1.ScalePhase } else { dc.Status.Worker.Phase = v1alpha1.NormalPhase } @@ -368,10 +369,19 @@ func getNewWorkerSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( }) } - storageRequest, err := controller.ParseStorageRequest(dc.Spec.Worker.Requests) + storageSize := DefaultStorageSize + if dc.Spec.Worker.StorageSize != "" { + storageSize = dc.Spec.Worker.StorageSize + } + rs, err := resource.ParseQuantity(storageSize) if err != nil { return nil, fmt.Errorf("cannot parse storage request for dm-worker, dmcluster %s/%s, error: %v", dc.Namespace, dc.Name, err) } + storageRequest := corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: rs, + }, + } workerLabel := label.NewDM().Instance(instanceName).DMWorker() setName := controller.DMWorkerPeerMemberName(dcName) @@ -416,7 +426,7 @@ func getNewWorkerSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( }, { Name: "TZ", - Value: dc.Spec.Timezone, + Value: dc.Timezone(), }, } diff --git a/pkg/manager/member/template.go b/pkg/manager/member/template.go index 311b0958d6..846e4f3c9d 100644 --- a/pkg/manager/member/template.go +++ b/pkg/manager/member/template.go @@ -416,7 +416,7 @@ fi if nslookup ${domain} 2>/dev/null then -echo "nslookup domain ${domain}.svc success" +echo "nslookup domain ${domain} success" break else echo "nslookup domain ${domain} failed" >&2 @@ -501,7 +501,7 @@ fi POD_NAME=${POD_NAME:-$HOSTNAME} # TODO: dm-worker will support data-dir in the future ARGS="--join={{ .MasterAddress }} \ ---advertise-addr=${POD_NAME}.${HEADLESS_SERVICE_NAME}.${NAMESPACE}.svc:8262 \ +--advertise-addr=${POD_NAME}.${HEADLESS_SERVICE_NAME}:8262 \ --worker-addr=0.0.0.0:8262 \ --config=/etc/dm-worker/dm-worker.toml " diff --git a/pkg/manager/member/utils.go b/pkg/manager/member/utils.go index 0798687880..9290ef8e39 100644 --- a/pkg/manager/member/utils.go +++ b/pkg/manager/member/utils.go @@ -266,6 +266,8 @@ func getStsAnnotations(tcAnns map[string]string, component string) map[string]st key = label.AnnTiFlashDeleteSlots case label.DMMasterLabelVal: key = label.AnnDMMasterDeleteSlots + case label.DMWorkerLabelVal: + key = label.AnnDMWorkerDeleteSlots default: return anns } diff --git a/pkg/util/crdutil.go b/pkg/util/crdutil.go index 6637957657..2e1ed55940 100644 --- a/pkg/util/crdutil.go +++ b/pkg/util/crdutil.go @@ -123,7 +123,7 @@ var ( Name: "Storage", Type: "string", Description: "The storage size specified for dm-master node", - JSONPath: ".spec.master.requests.storage", + JSONPath: ".spec.master.storageSize", } dmClusterMasterReadyColumn = extensionsobj.CustomResourceColumnDefinition{ Name: "Ready", @@ -147,7 +147,7 @@ var ( Name: "Storage", Type: "string", Description: "The storage size specified for dm-worker node", - JSONPath: ".spec.worker.requests.storage", + JSONPath: ".spec.worker.storageSize", } dmClusterWorkerReadyColumn = extensionsobj.CustomResourceColumnDefinition{ Name: "Ready", From d3da80800806310703c485c7eb820d3a34badc05 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 18:27:05 +0800 Subject: [PATCH 22/37] regenerate code --- docs/api-references/docs.md | 39 +++++++++++++++++++ manifests/crd.yaml | 11 +++++- .../pingcap/v1alpha1/openapi_generated.go | 21 ++++++++++ .../pingcap/v1alpha1/zz_generated.deepcopy.go | 5 +++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index a2c7c277d8..2a2025b49d 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -6442,6 +6442,19 @@ Defaults to Kubernetes default storage class.

    +storageSize
    + +string + + + +(Optional) +

    StorageSize is the request storage size for dm-master. +Defaults to “10Gi”.

    + + + + dataSubDir
    string @@ -18892,6 +18905,19 @@ string +maxFailoverCount
    + +int32 + + + +(Optional) +

    MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. +Optional: Defaults to 3

    + + + + storageClassName
    string @@ -18905,6 +18931,19 @@ Defaults to Kubernetes default storage class.

    +storageSize
    + +string + + + +(Optional) +

    StorageSize is the request storage size for dm-worker. +Defaults to “10Gi”.

    + + + + dataSubDir
    string diff --git a/manifests/crd.yaml b/manifests/crd.yaml index ba2f1de2f7..54e0c69d31 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -11301,7 +11301,7 @@ spec: description: The image for dm-master cluster name: Master type: string - - JSONPath: .spec.master.requests.storage + - JSONPath: .spec.master.storageSize description: The storage size specified for dm-master node name: Storage type: string @@ -11317,7 +11317,7 @@ spec: description: The image for dm-worker cluster name: Worker type: string - - JSONPath: .spec.worker.requests.storage + - JSONPath: .spec.worker.storageSize description: The storage size specified for dm-worker node name: Storage type: string @@ -13124,6 +13124,8 @@ spec: service: {} storageClassName: type: string + storageSize: + type: string terminationGracePeriodSeconds: format: int64 type: integer @@ -14612,6 +14614,9 @@ spec: type: array limits: type: object + maxFailoverCount: + format: int32 + type: integer nodeSelector: type: object podSecurityContext: @@ -14676,6 +14681,8 @@ spec: type: string storageClassName: type: string + storageSize: + type: string terminationGracePeriodSeconds: format: int64 type: integer diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index e1db10cc80..44772069c4 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -2629,6 +2629,13 @@ func schema_pkg_apis_pingcap_v1alpha1_MasterSpec(ref common.ReferenceCallback) c Format: "", }, }, + "storageSize": { + SchemaProps: spec.SchemaProps{ + Description: "StorageSize is the request storage size for dm-master. Defaults to \"10Gi\".", + Type: []string{"string"}, + Format: "", + }, + }, "dataSubDir": { SchemaProps: spec.SchemaProps{ Description: "Subdirectory within the volume to store dm-master Data. By default, the data is stored in the root directory of volume which is mounted at /var/lib/dm-master. Specifying this will change the data directory to a subdirectory, e.g. /var/lib/dm-master/data if you set the value to \"data\". It's dangerous to change this value for a running cluster as it will upgrade your cluster to use a new storage directory. Defaults to \"\" (volume's root).", @@ -11063,6 +11070,13 @@ func schema_pkg_apis_pingcap_v1alpha1_WorkerSpec(ref common.ReferenceCallback) c Format: "", }, }, + "maxFailoverCount": { + SchemaProps: spec.SchemaProps{ + Description: "MaxFailoverCount limit the max replicas could be added in failover, 0 means no failover. Optional: Defaults to 3", + Type: []string{"integer"}, + Format: "int32", + }, + }, "storageClassName": { SchemaProps: spec.SchemaProps{ Description: "The storageClassName of the persistent volume for dm-worker data storage. Defaults to Kubernetes default storage class.", @@ -11070,6 +11084,13 @@ func schema_pkg_apis_pingcap_v1alpha1_WorkerSpec(ref common.ReferenceCallback) c Format: "", }, }, + "storageSize": { + SchemaProps: spec.SchemaProps{ + Description: "StorageSize is the request storage size for dm-worker. Defaults to \"10Gi\".", + Type: []string{"string"}, + Format: "", + }, + }, "dataSubDir": { SchemaProps: spec.SchemaProps{ Description: "Subdirectory within the volume to store dm-worker Data. By default, the data is stored in the root directory of volume which is mounted at /var/lib/dm-worker. Specifying this will change the data directory to a subdirectory, e.g. /var/lib/dm-worker/data if you set the value to \"data\". It's dangerous to change this value for a running cluster as it will upgrade your cluster to use a new storage directory. Defaults to \"\" (volume's root).", diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index 48306447dd..05c330046a 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -8089,6 +8089,11 @@ func (in *WorkerSpec) DeepCopyInto(out *WorkerSpec) { *out = *in in.ComponentSpec.DeepCopyInto(&out.ComponentSpec) in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements) + if in.MaxFailoverCount != nil { + in, out := &in.MaxFailoverCount, &out.MaxFailoverCount + *out = new(int32) + **out = **in + } if in.StorageClassName != nil { in, out := &in.StorageClassName, &out.StorageClassName *out = new(string) From 8e52fbb8a0d9c123a81b77570aac341b18077dd1 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 25 Aug 2020 23:55:29 +0800 Subject: [PATCH 23/37] address comments --- examples/dm/README.md | 6 +-- examples/dm/dm-cluster.yaml | 4 +- .../pingcap/v1alpha1/defaulting/dmcluster.go | 7 --- pkg/apis/pingcap/v1alpha1/dmcluster.go | 43 +++++++------------ pkg/controller/controller_utils.go | 7 ++- .../dmcluster/dm_cluster_control.go | 8 ++++ .../dmcluster/dm_cluster_controller.go | 23 ++++++++++ pkg/dmapi/master_control.go | 4 +- .../member/dm_master_member_manager.go | 9 +--- .../member/dm_worker_member_manager.go | 13 ++---- pkg/manager/member/pvc_resizer.go | 32 ++++++++++++++ 11 files changed, 98 insertions(+), 58 deletions(-) diff --git a/examples/dm/README.md b/examples/dm/README.md index 802052a055..1f9c232929 100644 --- a/examples/dm/README.md +++ b/examples/dm/README.md @@ -8,7 +8,7 @@ The following steps will create a DM cluster. **Prerequisites**: - Has TiDB operator `v1.2.0` or higher version installed. [Doc](https://pingcap.com/docs/stable/tidb-in-kubernetes/deploy/tidb-operator/) -- Has default `StorageClass` configured, and there are enough PVs (by default, 6 PVs are required) of that storageClass: +- Has default `StorageClass` configured, and there are enough PVs (by default, 2 PVs are required) of that storageClass: This could by verified by the following command: @@ -24,7 +24,7 @@ The following steps will create a DM cluster. gold kubernetes.io/gce-pd 1d ``` - Alternatively, you could specify the storageClass explicitly by modifying `tidb-cluster.yaml`. + Alternatively, you could specify the storageClass explicitly by modifying `dm-cluster.yaml`. ## Install @@ -47,7 +47,7 @@ watch kubectl -n get pod Explore the DM master interface: ```bash -> kubectl -n port-forward svc/basic-dm-master 8261:8261 &>/tmp/pf-dm.log & +> kubectl -n port-forward svc/basic-dm-master 8261:8261 > dmctl --master-addr 127.0.0.1:8261 list-member ``` diff --git a/examples/dm/dm-cluster.yaml b/examples/dm/dm-cluster.yaml index 5ccacbe0f2..3b4b0f780c 100644 --- a/examples/dm/dm-cluster.yaml +++ b/examples/dm/dm-cluster.yaml @@ -10,7 +10,7 @@ spec: address: "http://basic-discovery.demo:10261" master: baseImage: pingcap/dm - replicas: 3 + replicas: 1 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage storageSize: "1Gi" @@ -18,7 +18,7 @@ spec: config: {} worker: baseImage: pingcap/dm - replicas: 3 + replicas: 1 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage storageSize: "1Gi" diff --git a/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go b/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go index f26c3c0720..c227f93f7e 100644 --- a/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/defaulting/dmcluster.go @@ -16,7 +16,6 @@ package defaulting import ( "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" corev1 "k8s.io/api/core/v1" - "k8s.io/utils/pointer" ) const ( @@ -56,9 +55,6 @@ func setMasterSpecDefault(dc *v1alpha1.DMCluster) { dc.Spec.Master.BaseImage = defaultMasterImage } } - if dc.Spec.Master.MaxFailoverCount == nil { - dc.Spec.Master.MaxFailoverCount = pointer.Int32Ptr(3) - } } func setWorkerSpecDefault(dc *v1alpha1.DMCluster) { @@ -67,7 +63,4 @@ func setWorkerSpecDefault(dc *v1alpha1.DMCluster) { dc.Spec.Worker.BaseImage = defaultWorkerImage } } - if dc.Spec.Worker.MaxFailoverCount == nil { - dc.Spec.Worker.MaxFailoverCount = pointer.Int32Ptr(3) - } } diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go index 84c9883d24..1716ca14b0 100644 --- a/pkg/apis/pingcap/v1alpha1/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -18,8 +18,6 @@ import ( "strings" ) -var latestImageVersion = "latest" - func (dc *DMCluster) Scheme() string { if dc.IsTLSClusterEnabled() { return "https" @@ -69,6 +67,7 @@ func (dc *DMCluster) MasterStsDesiredReplicas() int32 { return dc.Spec.Master.Replicas + int32(len(dc.Status.Master.FailureMembers)) } +// TODO: support fail-over func (dc *DMCluster) WorkerStsDesiredReplicas() int32 { if dc.Spec.Worker == nil { return 0 @@ -82,35 +81,25 @@ func (dc *DMCluster) GetInstanceName() string { } func (dc *DMCluster) MasterImage() string { - image := dc.Spec.Master.Image - baseImage := dc.Spec.Master.BaseImage - // base image takes higher priority - if baseImage != "" { - version := dc.Spec.Master.Version - if version == nil { - version = &dc.Spec.Version - } - if version == nil { - version = &latestImageVersion - } - image = fmt.Sprintf("%s:%s", baseImage, *version) + image := dc.Spec.Master.BaseImage + version := dc.Spec.Master.Version + if version == nil { + version = &dc.Spec.Version + } + if *version != "" { + image = fmt.Sprintf("%s:%s", image, *version) } return image } func (dc *DMCluster) WorkerImage() string { - image := dc.Spec.Worker.Image - baseImage := dc.Spec.Worker.BaseImage - // base image takes higher priority - if baseImage != "" { - version := dc.Spec.Worker.Version - if version == nil { - version = &dc.Spec.Version - } - if version == nil { - version = &latestImageVersion - } - image = fmt.Sprintf("%s:%s", baseImage, *version) + image := dc.Spec.Worker.BaseImage + version := dc.Spec.Worker.Version + if version == nil { + version = &dc.Spec.Version + } + if *version != "" { + image = fmt.Sprintf("%s:%s", image, *version) } return image } @@ -122,7 +111,7 @@ func (dc *DMCluster) MasterVersion() string { return image[colonIdx+1:] } - return latestImageVersion + return "latest" } func (dc *DMCluster) MasterUpgrading() bool { diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index 000f10f0a5..aa5b21eac9 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -323,9 +323,14 @@ func DMMasterPeerMemberName(clusterName string) string { return fmt.Sprintf("%s-dm-master-peer", clusterName) } +// DMWorkerMemberName returns dm-worker member name +func DMWorkerMemberName(clusterName string) string { + return fmt.Sprintf("%s-dm-worker", clusterName) +} + // DMWorkerPeerMemberName returns dm-worker peer service name func DMWorkerPeerMemberName(clusterName string) string { - return fmt.Sprintf("%s-dm-worker", clusterName) + return fmt.Sprintf("%s-dm-worker-peer", clusterName) } // AnnProm adds annotations for prometheus scraping metrics diff --git a/pkg/controller/dmcluster/dm_cluster_control.go b/pkg/controller/dmcluster/dm_cluster_control.go index 88bf417127..dd3b55bbbb 100644 --- a/pkg/controller/dmcluster/dm_cluster_control.go +++ b/pkg/controller/dmcluster/dm_cluster_control.go @@ -45,6 +45,7 @@ func NewDefaultDMClusterControl( //metaManager manager.DMManager, //orphanPodsCleaner member.OrphanPodsCleaner, pvcCleaner member.PVCCleanerInterface, + pvcResizer member.PVCResizerInterface, //podRestarter member.PodRestarter, conditionUpdater DMClusterConditionUpdater, recorder record.EventRecorder) ControlInterface { @@ -57,6 +58,7 @@ func NewDefaultDMClusterControl( //orphanPodsCleaner, pvcCleaner, //podRestarter, + pvcResizer, conditionUpdater, recorder, } @@ -71,6 +73,7 @@ type defaultDMClusterControl struct { //orphanPodsCleaner member.OrphanPodsCleaner pvcCleaner member.PVCCleanerInterface //podRestarter member.PodRestarter + pvcResizer member.PVCResizerInterface conditionUpdater DMClusterConditionUpdater recorder record.EventRecorder } @@ -194,5 +197,10 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // syncing the some tidbcluster status attributes // - sync tidbmonitor reference // return dcc.tidbClusterStatusManager.Sync(dc) + + // resize PVC if necessary + if err := dcc.pvcResizer.ResizeDM(dc); err != nil { + errs = append(errs, err) + } return errorutils.NewAggregate(errs) } diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index f66853d799..078594ce4d 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -17,6 +17,7 @@ import ( "fmt" "time" + "github.com/Masterminds/semver" perrors "github.com/pingcap/errors" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" @@ -25,6 +26,7 @@ import ( "github.com/pingcap/tidb-operator/pkg/controller" "github.com/pingcap/tidb-operator/pkg/dmapi" mm "github.com/pingcap/tidb-operator/pkg/manager/member" + apps "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -85,6 +87,7 @@ func NewController( pvcInformer := kubeInformerFactory.Core().V1().PersistentVolumeClaims() pvInformer := kubeInformerFactory.Core().V1().PersistentVolumes() podInformer := kubeInformerFactory.Core().V1().Pods() + scInformer := kubeInformerFactory.Storage().V1().StorageClasses() //nodeInformer := kubeInformerFactory.Core().V1().Nodes() //secretInformer := kubeInformerFactory.Core().V1().Secrets() @@ -150,6 +153,11 @@ func NewController( pvInformer.Lister(), pvControl, ), + mm.NewPVCResizer( + kubeCli, + pvcInformer, + scInformer, + ), //mm.NewDMClusterStatusManager(kubeCli, cli, scalerInformer.Lister(), tikvGroupInformer.Lister()), //podRestarter, &dmClusterConditionUpdater{}, @@ -245,6 +253,12 @@ func (dcc *Controller) sync(key string) error { if err != nil { return err } + clusterVersionLT2, err := clusterVersionLessThan2(dc.MasterVersion()) + if err != nil { + klog.V(4).Infof("cluster version: %s is not semantic versioning compatible", dc.MasterVersion()) + } else if clusterVersionLT2 { + return fmt.Errorf("dm-operator only supports to deploy dm-2.0") + } return dcc.syncDMCluster(dc.DeepCopy()) } @@ -362,3 +376,12 @@ func (dcc *Controller) resolveDMClusterFromSet(namespace string, set *apps.State } return dc } + +func clusterVersionLessThan2(version string) (bool, error) { + v, err := semver.NewVersion(version) + if err != nil { + return true, err + } + + return v.Major() < 2, nil +} diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go index 0a08aa409b..8278a003de 100644 --- a/pkg/dmapi/master_control.go +++ b/pkg/dmapi/master_control.go @@ -19,6 +19,8 @@ import ( "net/http" "sync" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/pdapi" "github.com/pingcap/tidb-operator/pkg/util" @@ -82,7 +84,7 @@ func masterClientKey(scheme string, namespace Namespace, clusterName string) str // MasterClientURL builds the url of master client func MasterClientURL(namespace Namespace, clusterName string, scheme string) string { - return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, string(namespace)) + return fmt.Sprintf("%s://%s.%s:8261", scheme, controller.DMMasterMemberName(clusterName), string(namespace)) } // FakeMasterControl implements a fake version of MasterControlInterface. diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 9574423b3a..132ca26a56 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -85,13 +85,6 @@ func NewMasterMemberManager(masterControl dmapi.MasterControlInterface, } func (mmm *masterMemberManager) Sync(dc *v1alpha1.DMCluster) error { - clusterVersionLT2, err := clusterVersionLessThan2(dc.MasterVersion()) - if err != nil { - klog.V(4).Infof("cluster version: %s is not semantic versioning compatible", dc.MasterVersion()) - } else if clusterVersionLT2 { - return fmt.Errorf("dm-operator only supports to deploy dm-2.0") - } - // Sync dm-master Service if err := mmm.syncMasterServiceForDMCluster(dc); err != nil { return err @@ -324,7 +317,7 @@ func (mmm *masterMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set } name := master.Name if len(name) == 0 { - klog.Warningf("dm-master member: [%s] doesn't have a name, and can't get it from clientUrls: [%s], dm-master Info: [%v] in [%s/%s]", + klog.Warningf("dm-master member: [%s] doesn't have a name, clientUrls: [%s], dm-master Info: [%#v] in [%s/%s]", id, master.ClientURLs, master, ns, dcName) continue } diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index de6808d898..c09a08c52b 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -172,9 +172,9 @@ func (wmm *workerMemberManager) syncWorkerStatefulSetForDMCluster(dc *v1alpha1.D ns := dc.GetNamespace() dcName := dc.GetName() - oldStsTmp, err := wmm.setLister.StatefulSets(ns).Get(controller.DMWorkerPeerMemberName(dcName)) + oldStsTmp, err := wmm.setLister.StatefulSets(ns).Get(controller.DMWorkerMemberName(dcName)) if err != nil && !errors.IsNotFound(err) { - return fmt.Errorf("syncWorkerStatefulSetForDMCluster: failed to get sts %s for cluster %s/%s, error: %s", controller.DMWorkerPeerMemberName(dcName), ns, dcName, err) + return fmt.Errorf("syncWorkerStatefulSetForDMCluster: failed to get sts %s for cluster %s/%s, error: %s", controller.DMWorkerMemberName(dcName), ns, dcName, err) } stsNotExist := errors.IsNotFound(err) @@ -211,11 +211,6 @@ func (wmm *workerMemberManager) syncWorkerStatefulSetForDMCluster(dc *v1alpha1.D return nil } - if dc.MasterUpgrading() { - klog.Warningf("dm-master is upgrading, skipping upgrade dm-worker") - return nil - } - return updateStatefulSet(wmm.setControl, dc, newSts, oldSts) } @@ -384,7 +379,7 @@ func getNewWorkerSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( } workerLabel := label.NewDM().Instance(instanceName).DMWorker() - setName := controller.DMWorkerPeerMemberName(dcName) + setName := controller.DMWorkerMemberName(dcName) podAnnotations := CombineAnnotations(controller.AnnProm(8262), baseWorkerSpec.Annotations()) stsAnnotations := getStsAnnotations(dc.Annotations, label.DMWorkerLabelVal) @@ -521,7 +516,7 @@ func getWorkerConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { workerLabel := label.NewDM().Instance(instanceName).DMWorker().Labels() cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: controller.DMWorkerPeerMemberName(dc.Name), + Name: controller.DMWorkerMemberName(dc.Name), Namespace: dc.Namespace, Labels: workerLabel, OwnerReferences: []metav1.OwnerReference{controller.GetDMOwnerRef(dc)}, diff --git a/pkg/manager/member/pvc_resizer.go b/pkg/manager/member/pvc_resizer.go index fbebd11e01..fb7bb76a02 100644 --- a/pkg/manager/member/pvc_resizer.go +++ b/pkg/manager/member/pvc_resizer.go @@ -63,6 +63,7 @@ import ( // type PVCResizerInterface interface { Resize(*v1alpha1.TidbCluster) error + ResizeDM(*v1alpha1.DMCluster) error } var ( @@ -70,6 +71,9 @@ var ( tikvRequirement = util.MustNewRequirement(label.ComponentLabelKey, selection.Equals, []string{label.TiKVLabelVal}) tiflashRequirement = util.MustNewRequirement(label.ComponentLabelKey, selection.Equals, []string{label.TiFlashLabelVal}) pumpRequirement = util.MustNewRequirement(label.ComponentLabelKey, selection.Equals, []string{label.PumpLabelVal}) + + dmMasterRequirement = util.MustNewRequirement(label.ComponentLabelKey, selection.Equals, []string{label.DMMasterLabelVal}) + dmWorkerRequirement = util.MustNewRequirement(label.ComponentLabelKey, selection.Equals, []string{label.DMWorkerLabelVal}) ) type pvcResizer struct { @@ -125,6 +129,30 @@ func (p *pvcResizer) Resize(tc *v1alpha1.TidbCluster) error { return nil } +func (p *pvcResizer) ResizeDM(dc *v1alpha1.DMCluster) error { + selector, err := label.New().Instance(dc.GetInstanceName()).Selector() + if err != nil { + return err + } + // patch dm-master PVCs + if masterRs, err := resource.ParseQuantity(dc.Spec.Master.StorageSize); err == nil { + err = p.patchPVCs(dc.GetNamespace(), selector.Add(*dmMasterRequirement), masterRs, "") + if err != nil { + return err + } + } + // patch dm-worker PVCs + if dc.Spec.Worker != nil { + if workerRs, err := resource.ParseQuantity(dc.Spec.Worker.StorageSize); err == nil { + err = p.patchPVCs(dc.GetNamespace(), selector.Add(*dmWorkerRequirement), workerRs, "") + if err != nil { + return err + } + } + } + return nil +} + func (p *pvcResizer) isVolumeExpansionSupported(storageClassName string) (bool, error) { sc, err := p.scLister.Get(storageClassName) if err != nil { @@ -201,6 +229,10 @@ func (f *fakePVCResizer) Resize(_ *v1alpha1.TidbCluster) error { return nil } +func (f *fakePVCResizer) ResizeDM(_ *v1alpha1.DMCluster) error { + return nil +} + func NewFakePVCResizer() PVCResizerInterface { return &fakePVCResizer{} } From f1b6029c44d4e3855f092ccd306e850b8fcd603d Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 26 Aug 2020 10:37:38 +0800 Subject: [PATCH 24/37] fix import cycle problem --- examples/dm/README.md | 4 ++-- pkg/controller/dmcluster/dm_cluster_controller.go | 3 ++- pkg/dmapi/master_control.go | 7 ++----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/dm/README.md b/examples/dm/README.md index 1f9c232929..6acb0e8208 100644 --- a/examples/dm/README.md +++ b/examples/dm/README.md @@ -47,8 +47,8 @@ watch kubectl -n get pod Explore the DM master interface: ```bash -> kubectl -n port-forward svc/basic-dm-master 8261:8261 -> dmctl --master-addr 127.0.0.1:8261 list-member +> kubectl exec -ti -n -dm-master-0 -- /bin/sh +> ./dmctl --master-addr -dm-master.:8261 list-member ``` ## Destroy diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index 078594ce4d..0154d8b088 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -257,7 +257,8 @@ func (dcc *Controller) sync(key string) error { if err != nil { klog.V(4).Infof("cluster version: %s is not semantic versioning compatible", dc.MasterVersion()) } else if clusterVersionLT2 { - return fmt.Errorf("dm-operator only supports to deploy dm-2.0") + klog.Errorf("dm version %s not supported, dm-operator only supports to deploy dm-2.0", dc.MasterVersion()) + return nil } return dcc.syncDMCluster(dc.DeepCopy()) diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go index 8278a003de..ade625a8e2 100644 --- a/pkg/dmapi/master_control.go +++ b/pkg/dmapi/master_control.go @@ -19,14 +19,11 @@ import ( "net/http" "sync" - "github.com/pingcap/tidb-operator/pkg/controller" - "github.com/pingcap/tidb-operator/pkg/pdapi" - "github.com/pingcap/tidb-operator/pkg/util" - "k8s.io/klog" "k8s.io/client-go/kubernetes" + "k8s.io/klog" ) // Namespace is a newtype of a string @@ -84,7 +81,7 @@ func masterClientKey(scheme string, namespace Namespace, clusterName string) str // MasterClientURL builds the url of master client func MasterClientURL(namespace Namespace, clusterName string, scheme string) string { - return fmt.Sprintf("%s://%s.%s:8261", scheme, controller.DMMasterMemberName(clusterName), string(namespace)) + return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, string(namespace)) } // FakeMasterControl implements a fake version of MasterControlInterface. From 84a6309c5150e067b5f2eebcfb4fc5345d3ca2c6 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 26 Aug 2020 10:59:06 +0800 Subject: [PATCH 25/37] fix check --- pkg/manager/member/pd_member_manager.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkg/manager/member/pd_member_manager.go b/pkg/manager/member/pd_member_manager.go index 94ae7217b9..b1d27d3253 100644 --- a/pkg/manager/member/pd_member_manager.go +++ b/pkg/manager/member/pd_member_manager.go @@ -827,15 +827,6 @@ func clusterVersionGreaterThanOrEqualTo4(version string) (bool, error) { return v.Major() >= 4, nil } -func clusterVersionLessThan2(version string) (bool, error) { - v, err := semver.NewVersion(version) - if err != nil { - return true, err - } - - return v.Major() < 2, nil -} - func (pmm *pdMemberManager) collectUnjoinedMembers(tc *v1alpha1.TidbCluster, set *apps.StatefulSet, pdStatus map[string]v1alpha1.PDMember) error { podSelector, podSelectErr := metav1.LabelSelectorAsSelector(set.Spec.Selector) if podSelectErr != nil { From 5ab015d5f5cf2add9a0132f412506383a9dd5008 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 26 Aug 2020 11:15:01 +0800 Subject: [PATCH 26/37] address comments --- examples/dm/README.md | 2 +- pkg/controller/dmcluster/dm_cluster_controller.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dm/README.md b/examples/dm/README.md index 6acb0e8208..e5bfddb22d 100644 --- a/examples/dm/README.md +++ b/examples/dm/README.md @@ -48,7 +48,7 @@ Explore the DM master interface: ```bash > kubectl exec -ti -n -dm-master-0 -- /bin/sh -> ./dmctl --master-addr -dm-master.:8261 list-member +> /dmctl --master-addr 127.0.0.1:8261 list-member ``` ## Destroy diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index 0154d8b088..e17b16dd71 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -257,7 +257,7 @@ func (dcc *Controller) sync(key string) error { if err != nil { klog.V(4).Infof("cluster version: %s is not semantic versioning compatible", dc.MasterVersion()) } else if clusterVersionLT2 { - klog.Errorf("dm version %s not supported, dm-operator only supports to deploy dm-2.0", dc.MasterVersion()) + klog.Errorf("dm version %s not supported, only support to deploy dm from v2.0", dc.MasterVersion()) return nil } From c33746e530742d9686aa126012fb5dc903c3c008 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 26 Aug 2020 17:43:47 +0800 Subject: [PATCH 27/37] support graceful upgrade for dm-master --- pkg/apis/pingcap/v1alpha1/dmcluster.go | 12 ++ .../dmcluster/dm_cluster_controller.go | 5 +- pkg/controller/dmmaster_control.go | 5 + pkg/dmapi/dmapi.go | 35 +++- pkg/dmapi/fake_dmapi.go | 16 +- pkg/dmapi/master_control.go | 29 +++- .../member/dm_master_member_manager.go | 39 +++-- pkg/manager/member/dm_master_upgrader.go | 150 ++++++++++++++++++ pkg/manager/member/upgrader.go | 5 + pkg/manager/member/utils.go | 4 + pkg/util/http/httputil.go | 22 +++ 11 files changed, 289 insertions(+), 33 deletions(-) create mode 100644 pkg/manager/member/dm_master_upgrader.go diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go index 1716ca14b0..cd48d44c6f 100644 --- a/pkg/apis/pingcap/v1alpha1/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -67,6 +67,14 @@ func (dc *DMCluster) MasterStsDesiredReplicas() int32 { return dc.Spec.Master.Replicas + int32(len(dc.Status.Master.FailureMembers)) } +func (dc *DMCluster) MasterStsActualReplicas() int32 { + stsStatus := dc.Status.Master.StatefulSet + if stsStatus == nil { + return 0 + } + return stsStatus.Replicas +} + // TODO: support fail-over func (dc *DMCluster) WorkerStsDesiredReplicas() int32 { if dc.Spec.Worker == nil { @@ -118,6 +126,10 @@ func (dc *DMCluster) MasterUpgrading() bool { return dc.Status.Master.Phase == UpgradePhase } +func (dc *DMCluster) MasterScaling() bool { + return dc.Status.Master.Phase == ScalePhase +} + func (dc *DMCluster) MasterIsAvailable() bool { lowerLimit := dc.Spec.Master.Replicas/2 + 1 if int32(len(dc.Status.Master.Members)) < lowerLimit { diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index e17b16dd71..0e920b5583 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -97,8 +97,9 @@ func NewController( svcControl := controller.NewRealServiceControl(kubeCli, svcInformer.Lister(), recorder) pvControl := controller.NewRealPVControl(kubeCli, pvcInformer.Lister(), pvInformer.Lister(), recorder) pvcControl := controller.NewRealPVCControl(kubeCli, recorder, pvcInformer.Lister()) - // podControl := controller.NewRealPodControl(kubeCli, masterControl, podInformer.Lister(), recorder) + //podControl := controller.NewRealPodControl(kubeCli, nil, podInformer.Lister(), recorder) typedControl := controller.NewTypedControl(controller.NewRealGenericControl(genericCli, recorder)) + masterUpgrader := mm.NewMasterUpgrader(masterControl, podInformer.Lister()) dcc := &Controller{ kubeClient: kubeCli, @@ -109,13 +110,13 @@ func NewController( masterControl, setControl, svcControl, - // podControl, typedControl, setInformer.Lister(), svcInformer.Lister(), podInformer.Lister(), epsInformer.Lister(), pvcInformer.Lister(), + masterUpgrader, ), mm.NewWorkerMemberManager( masterControl, diff --git a/pkg/controller/dmmaster_control.go b/pkg/controller/dmmaster_control.go index 6e39d5af6d..94f33ef4ff 100644 --- a/pkg/controller/dmmaster_control.go +++ b/pkg/controller/dmmaster_control.go @@ -23,6 +23,11 @@ func GetMasterClient(dmControl dmapi.MasterControlInterface, dc *v1alpha1.DMClus return dmControl.GetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), dc.IsTLSClusterEnabled()) } +// GetMasterClient gets the master client from the DMCluster +func GetMasterPeerClient(dmControl dmapi.MasterControlInterface, dc *v1alpha1.DMCluster, podName string) dmapi.MasterClient { + return dmControl.GetMasterPeerClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), podName, dc.IsTLSClusterEnabled()) +} + // NewFakeMasterClient creates a fake master client that is set as the master client func NewFakeMasterClient(dmControl *dmapi.FakeMasterControl, dc *v1alpha1.DMCluster) *dmapi.FakeMasterClient { masterClient := dmapi.NewFakeMasterClient() diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index de4997fc6b..78cfabc379 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -33,13 +33,15 @@ type MasterClient interface { GetMasters() ([]*MastersInfo, error) GetWorkers() ([]*WorkersInfo, error) GetLeader() (MembersLeader, error) + EvictLeader() error } var ( membersPrefix = "apis/v1alpha1/members" + leaderPrefix = "apis/v1alpha1/leader" ) -type ListMemberRespHeader struct { +type RespHeader struct { Result bool `json:"result,omitempty"` Msg string `json:"msg,omitempty"` } @@ -88,18 +90,18 @@ type ListMemberLeader struct { } type MastersResp struct { - ListMemberRespHeader `json:",inline"` - ListMemberResp []*ListMemberMaster `json:"members,omitempty"` + RespHeader `json:",inline"` + ListMemberResp []*ListMemberMaster `json:"members,omitempty"` } type WorkerResp struct { - ListMemberRespHeader `json:",inline"` - ListMemberResp []*ListMemberWorker `json:"members,omitempty"` + RespHeader `json:",inline"` + ListMemberResp []*ListMemberWorker `json:"members,omitempty"` } type LeaderResp struct { - ListMemberRespHeader `json:",inline"` - ListMemberResp []*ListMemberLeader `json:"members,omitempty"` + RespHeader `json:",inline"` + ListMemberResp []*ListMemberLeader `json:"members,omitempty"` } // masterClient is default implementation of MasterClient @@ -174,6 +176,25 @@ func (mc *masterClient) GetLeader() (MembersLeader, error) { return listMemberResp.ListMemberResp[0].MembersLeader, nil } +func (mc *masterClient) EvictLeader() error { + query := "/1" + apiURL := fmt.Sprintf("%s/%s%s", mc.url, leaderPrefix, query) + body, err := httputil.PutBodyOK(mc.httpClient, apiURL) + if err != nil { + return err + } + evictLeaderResp := &RespHeader{} + err = json.Unmarshal(body, evictLeaderResp) + if err != nil { + return fmt.Errorf("unable to unmarshal evict leader resp: %s, err: %s", body, err) + } + if !evictLeaderResp.Result { + return fmt.Errorf("unable to evict leader leader, err: %s", evictLeaderResp.Msg) + } + + return nil +} + // NewMasterClient returns a new MasterClient func NewMasterClient(url string, timeout time.Duration, tlsConfig *tls.Config) MasterClient { var disableKeepalive bool diff --git a/pkg/dmapi/fake_dmapi.go b/pkg/dmapi/fake_dmapi.go index b32643462a..8eb2a251ac 100644 --- a/pkg/dmapi/fake_dmapi.go +++ b/pkg/dmapi/fake_dmapi.go @@ -20,9 +20,10 @@ import ( type ActionType string const ( - GetMastersActionType ActionType = "GetMasters" - GetWorkersActionType ActionType = "GetWorkers" - GetLeaderActionType ActionType = "GetLeader" + GetMastersActionType ActionType = "GetMasters" + GetWorkersActionType ActionType = "GetWorkers" + GetLeaderActionType ActionType = "GetLeader" + EvictLeaderActionType ActionType = "EvictLeader" ) type NotFoundReaction struct { @@ -92,3 +93,12 @@ func (pc *FakeMasterClient) GetLeader() (MembersLeader, error) { } return result.(MembersLeader), nil } + +func (pc *FakeMasterClient) EvictLeader() error { + action := &Action{} + _, err := pc.fakeAPI(EvictLeaderActionType, action) + if err != nil { + return err + } + return err +} diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go index ade625a8e2..a8cae6eda1 100644 --- a/pkg/dmapi/master_control.go +++ b/pkg/dmapi/master_control.go @@ -32,7 +32,8 @@ type Namespace pdapi.Namespace // MasterControlInterface is an interface that knows how to manage and get dm cluster's master client type MasterControlInterface interface { // GetMasterClient provides MasterClient of the dm cluster. - GetMasterClient(namespace Namespace, tcName string, tlsEnabled bool) MasterClient + GetMasterClient(namespace Namespace, dcName string, tlsEnabled bool) MasterClient + GetMasterPeerClient(namespace Namespace, dcName, podName string, tlsEnabled bool) MasterClient } // defaultMasterControl is the default implementation of MasterControlInterface. @@ -74,6 +75,28 @@ func (mc *defaultMasterControl) GetMasterClient(namespace Namespace, dcName stri return mc.masterClients[key] } +func (mc *defaultMasterControl) GetMasterPeerClient(namespace Namespace, dcName string, podName string, tlsEnabled bool) MasterClient { + mc.mutex.Lock() + defer mc.mutex.Unlock() + + var tlsConfig *tls.Config + var err error + var scheme = "http" + + if tlsEnabled { + scheme = "https" + tlsConfig, err = pdapi.GetTLSConfig(mc.kubeCli, pdapi.Namespace(namespace), dcName, util.ClusterClientTLSSecretName(dcName)) + if err != nil { + klog.Errorf("Unable to get tls config for dm cluster %q, master client may not work: %v", dcName, err) + return &masterClient{url: MasterPeerClientURL(namespace, dcName, podName, scheme), httpClient: &http.Client{Timeout: DefaultTimeout}} + } + + return NewMasterClient(MasterPeerClientURL(namespace, dcName, podName, scheme), DefaultTimeout, tlsConfig) + } + + return &masterClient{url: MasterPeerClientURL(namespace, dcName, podName, scheme), httpClient: &http.Client{Timeout: DefaultTimeout}} +} + // masterClientKey returns the master client key func masterClientKey(scheme string, namespace Namespace, clusterName string) string { return fmt.Sprintf("%s.%s.%s", scheme, clusterName, string(namespace)) @@ -84,6 +107,10 @@ func MasterClientURL(namespace Namespace, clusterName string, scheme string) str return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, string(namespace)) } +func MasterPeerClientURL(namespace Namespace, clusterName, podName, scheme string) string { + return fmt.Sprintf("%s://%s.%s-dm-master-peer.%s:8261", scheme, podName, clusterName, string(namespace)) +} + // FakeMasterControl implements a fake version of MasterControlInterface. type FakeMasterControl struct { defaultMasterControl diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 132ca26a56..b97340a79d 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -48,40 +48,40 @@ const ( ) type masterMemberManager struct { - masterControl dmapi.MasterControlInterface - setControl controller.StatefulSetControlInterface - svcControl controller.ServiceControlInterface - //podControl controller.PodControlInterface - typedControl controller.TypedControlInterface - setLister v1.StatefulSetLister - svcLister corelisters.ServiceLister - podLister corelisters.PodLister - epsLister corelisters.EndpointsLister - pvcLister corelisters.PersistentVolumeClaimLister + masterControl dmapi.MasterControlInterface + setControl controller.StatefulSetControlInterface + svcControl controller.ServiceControlInterface + typedControl controller.TypedControlInterface + setLister v1.StatefulSetLister + svcLister corelisters.ServiceLister + podLister corelisters.PodLister + epsLister corelisters.EndpointsLister + pvcLister corelisters.PersistentVolumeClaimLister + masterUpgrader DMUpgrader } // NewMasterMemberManager returns a *masterMemberManager func NewMasterMemberManager(masterControl dmapi.MasterControlInterface, setControl controller.StatefulSetControlInterface, svcControl controller.ServiceControlInterface, - //podControl controller.PodControlInterface, typedControl controller.TypedControlInterface, setLister v1.StatefulSetLister, svcLister corelisters.ServiceLister, podLister corelisters.PodLister, epsLister corelisters.EndpointsLister, - pvcLister corelisters.PersistentVolumeClaimLister) manager.DMManager { + pvcLister corelisters.PersistentVolumeClaimLister, + masterUpgrader DMUpgrader) manager.DMManager { return &masterMemberManager{ masterControl, setControl, svcControl, - //podControl, typedControl, setLister, svcLister, podLister, epsLister, - pvcLister} + pvcLister, + masterUpgrader} } func (mmm *masterMemberManager) Sync(dc *v1alpha1.DMCluster) error { @@ -237,12 +237,11 @@ func (mmm *masterMemberManager) syncMasterStatefulSetForDMCluster(dc *v1alpha1.D } } - // TODO: dm add rolling update later - // if !templateEqual(newMasterSet, oldMasterSet) || dc.Status.Master.Phase == v1alpha1.UpgradePhase { - // if err := mmm.masterUpgrader.Upgrade(dc, oldMasterSet, newMasterSet); err != nil { - // return err - // } - // } + if !templateEqual(newMasterSet, oldMasterSet) || dc.Status.Master.Phase == v1alpha1.UpgradePhase { + if err := mmm.masterUpgrader.Upgrade(dc, oldMasterSet, newMasterSet); err != nil { + return err + } + } // TODO: dm add scaler //if err := mmm.masterScaler.Scale(dc, oldMasterSet, newMasterSet); err != nil { diff --git a/pkg/manager/member/dm_master_upgrader.go b/pkg/manager/member/dm_master_upgrader.go new file mode 100644 index 0000000000..2be7a202b2 --- /dev/null +++ b/pkg/manager/member/dm_master_upgrader.go @@ -0,0 +1,150 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package member + +import ( + "fmt" + + "github.com/pingcap/advanced-statefulset/client/apis/apps/v1/helper" + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/dmapi" + + apps "k8s.io/api/apps/v1" + corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/klog" +) + +type masterUpgrader struct { + masterControl dmapi.MasterControlInterface + podLister corelisters.PodLister +} + +// NewMasterUpgrader returns a masterUpgrader +func NewMasterUpgrader(masterControl dmapi.MasterControlInterface, + podLister corelisters.PodLister) DMUpgrader { + return &masterUpgrader{ + masterControl: masterControl, + podLister: podLister, + } +} + +func (mu *masterUpgrader) Upgrade(dc *v1alpha1.DMCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + return mu.gracefulUpgrade(dc, oldSet, newSet) +} + +func (mu *masterUpgrader) gracefulUpgrade(dc *v1alpha1.DMCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + ns := dc.GetNamespace() + dcName := dc.GetName() + if !dc.Status.Master.Synced { + return fmt.Errorf("dmcluster: [%s/%s]'s dm-master status sync failed, can not to be upgraded", ns, dcName) + } + if dc.MasterScaling() { + klog.Infof("DMCluster: [%s/%s]'s dm-master is scaling, can not upgrade dm-master", ns, dcName) + _, podSpec, err := GetLastAppliedConfig(oldSet) + if err != nil { + return err + } + newSet.Spec.Template.Spec = *podSpec + return nil + } + + dc.Status.Master.Phase = v1alpha1.UpgradePhase + if !templateEqual(newSet, oldSet) { + return nil + } + + if dc.Status.Master.StatefulSet.UpdateRevision == dc.Status.Master.StatefulSet.CurrentRevision { + return nil + } + + if oldSet.Spec.UpdateStrategy.Type == apps.OnDeleteStatefulSetStrategyType || oldSet.Spec.UpdateStrategy.RollingUpdate == nil { + // Manually bypass tidb-operator to modify statefulset directly, such as modify dm-master statefulset's RollingUpdate straregy to OnDelete strategy, + // or set RollingUpdate to nil, skip tidb-operator's rolling update logic in order to speed up the upgrade in the test environment occasionally. + // If we encounter this situation, we will let the native statefulset controller do the upgrade completely, which may be unsafe for upgrading dm-master. + // Therefore, in the production environment, we should try to avoid modifying the dm-master statefulset update strategy directly. + newSet.Spec.UpdateStrategy = oldSet.Spec.UpdateStrategy + klog.Warningf("tidbcluster: [%s/%s] dm-master statefulset %s UpdateStrategy has been modified manually", ns, dcName, oldSet.GetName()) + return nil + } + + setUpgradePartition(newSet, *oldSet.Spec.UpdateStrategy.RollingUpdate.Partition) + podOrdinals := helper.GetPodOrdinals(*oldSet.Spec.Replicas, oldSet).List() + for _i := len(podOrdinals) - 1; _i >= 0; _i-- { + i := podOrdinals[_i] + podName := DMMasterPodName(dcName, i) + pod, err := mu.podLister.Pods(ns).Get(podName) + if err != nil { + return fmt.Errorf("gracefulUpgrade: failed to get pods %s for cluster %s/%s, error: %s", podName, ns, dcName, err) + } + + revision, exist := pod.Labels[apps.ControllerRevisionHashLabelKey] + if !exist { + return controller.RequeueErrorf("tidbcluster: [%s/%s]'s dm-master pod: [%s] has no label: %s", ns, dcName, podName, apps.ControllerRevisionHashLabelKey) + } + + if revision == dc.Status.Master.StatefulSet.UpdateRevision { + if member, exist := dc.Status.Master.Members[podName]; !exist || !member.Health { + return controller.RequeueErrorf("tidbcluster: [%s/%s]'s dm-master upgraded pod: [%s] is not ready", ns, dcName, podName) + } + continue + } + + if controller.PodWebhookEnabled { + setUpgradePartition(newSet, i) + return nil + } + + return mu.upgradeMasterPod(dc, i, newSet) + } + + return nil +} + +func (mu *masterUpgrader) upgradeMasterPod(dc *v1alpha1.DMCluster, ordinal int32, newSet *apps.StatefulSet) error { + ns := dc.GetNamespace() + dcName := dc.GetName() + upgradePodName := DMMasterPodName(dcName, ordinal) + if dc.Status.Master.Leader.Name == upgradePodName && dc.MasterStsActualReplicas() > 1 { + err := mu.evictMasterLeader(dc, upgradePodName) + if err != nil { + klog.Errorf("dm-master upgrader: failed to evict dm-master %s's leader: %v", upgradePodName, err) + return err + } + klog.Infof("dm-master upgrader: evict dm-master %s's leader successfully", upgradePodName) + return controller.RequeueErrorf("dmcluster: [%s/%s]'s dm-master member: evicting [%s]'s leader", ns, dcName, upgradePodName) + } + + setUpgradePartition(newSet, ordinal) + return nil +} + +func (mu *masterUpgrader) evictMasterLeader(dc *v1alpha1.DMCluster, podName string) error { + return controller.GetMasterPeerClient(mu.masterControl, dc, podName).EvictLeader() +} + +type fakeMasterUpgrader struct{} + +// NewFakeMasterUpgrader returns a fakeMasterUpgrader +func NewFakeMasterUpgrader() DMUpgrader { + return &fakeMasterUpgrader{} +} + +func (fmu *fakeMasterUpgrader) Upgrade(dc *v1alpha1.DMCluster, _ *apps.StatefulSet, _ *apps.StatefulSet) error { + if !dc.Status.Master.Synced { + return fmt.Errorf("dmcluster: dm-master status sync failed,can not to be upgraded") + } + dc.Status.Master.Phase = v1alpha1.UpgradePhase + return nil +} diff --git a/pkg/manager/member/upgrader.go b/pkg/manager/member/upgrader.go index 33f7a6a47d..6d3d353bc5 100644 --- a/pkg/manager/member/upgrader.go +++ b/pkg/manager/member/upgrader.go @@ -23,3 +23,8 @@ type Upgrader interface { // Upgrade upgrade the cluster Upgrade(*v1alpha1.TidbCluster, *apps.StatefulSet, *apps.StatefulSet) error } + +// Upgrader implements the logic for upgrading the dm cluster. +type DMUpgrader interface { + Upgrade(*v1alpha1.DMCluster, *apps.StatefulSet, *apps.StatefulSet) error +} diff --git a/pkg/manager/member/utils.go b/pkg/manager/member/utils.go index 9290ef8e39..a63b7fcdcb 100644 --- a/pkg/manager/member/utils.go +++ b/pkg/manager/member/utils.go @@ -179,6 +179,10 @@ func TiKVGroupPodName(tgName string, ordinal int32) string { return fmt.Sprintf("%s-%d", controller.TiKVGroupMemberName(tgName), ordinal) } +func DMMasterPodName(dcName string, ordinal int32) string { + return fmt.Sprintf("%s-%d", controller.DMMasterMemberName(dcName), ordinal) +} + // CombineAnnotations merges two annotations maps func CombineAnnotations(a, b map[string]string) map[string]string { if a == nil { diff --git a/pkg/util/http/httputil.go b/pkg/util/http/httputil.go index 0733c18ac0..976bf595d5 100644 --- a/pkg/util/http/httputil.go +++ b/pkg/util/http/httputil.go @@ -57,3 +57,25 @@ func GetBodyOK(httpClient *http.Client, apiURL string) ([]byte, error) { } return body, err } + +// PutBodyOK returns the body or an error if the response is not okay +func PutBodyOK(httpClient *http.Client, apiURL string) ([]byte, error) { + req, err := http.NewRequest("PUT", apiURL, nil) + if err != nil { + return nil, err + } + res, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer DeferClose(res.Body) + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return nil, err + } + if res.StatusCode >= 400 { + errMsg := fmt.Errorf("Error response %v URL %s,body response: %s", res.StatusCode, apiURL, string(body[:])) + return nil, errMsg + } + return body, err +} From f23a3362374dc0bc150d9019187fafd91c739513 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Thu, 27 Aug 2020 10:38:29 +0800 Subject: [PATCH 28/37] address comments --- pkg/controller/dmmaster_control.go | 6 +++--- pkg/discovery/discovery.go | 2 +- pkg/discovery/discovery_test.go | 2 +- pkg/dmapi/dmapi.go | 2 +- pkg/dmapi/master_control.go | 25 +++++++++++------------- pkg/manager/member/dm_master_upgrader.go | 12 ++++++------ 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/pkg/controller/dmmaster_control.go b/pkg/controller/dmmaster_control.go index 94f33ef4ff..e2c6ef1e21 100644 --- a/pkg/controller/dmmaster_control.go +++ b/pkg/controller/dmmaster_control.go @@ -20,17 +20,17 @@ import ( // GetMasterClient gets the master client from the DMCluster func GetMasterClient(dmControl dmapi.MasterControlInterface, dc *v1alpha1.DMCluster) dmapi.MasterClient { - return dmControl.GetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), dc.IsTLSClusterEnabled()) + return dmControl.GetMasterClient(dc.GetNamespace(), dc.GetName(), dc.IsTLSClusterEnabled()) } // GetMasterClient gets the master client from the DMCluster func GetMasterPeerClient(dmControl dmapi.MasterControlInterface, dc *v1alpha1.DMCluster, podName string) dmapi.MasterClient { - return dmControl.GetMasterPeerClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), podName, dc.IsTLSClusterEnabled()) + return dmControl.GetMasterPeerClient(dc.GetNamespace(), dc.GetName(), podName, dc.IsTLSClusterEnabled()) } // NewFakeMasterClient creates a fake master client that is set as the master client func NewFakeMasterClient(dmControl *dmapi.FakeMasterControl, dc *v1alpha1.DMCluster) *dmapi.FakeMasterClient { masterClient := dmapi.NewFakeMasterClient() - dmControl.SetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), masterClient) + dmControl.SetMasterClient(dc.GetNamespace(), dc.GetName(), masterClient) return masterClient } diff --git a/pkg/discovery/discovery.go b/pkg/discovery/discovery.go index a6f9cfa568..5cb56dba56 100644 --- a/pkg/discovery/discovery.go +++ b/pkg/discovery/discovery.go @@ -166,7 +166,7 @@ func (td *tidbDiscovery) DiscoverDM(advertisePeerUrl string) (string, error) { return fmt.Sprintf("--initial-cluster=%s=%s://%s", podName, dc.Scheme(), advertisePeerUrl), nil } - masterClient := td.masterControl.GetMasterClient(dmapi.Namespace(dc.GetNamespace()), dc.GetName(), dc.IsTLSClusterEnabled()) + masterClient := td.masterControl.GetMasterClient(dc.GetNamespace(), dc.GetName(), dc.IsTLSClusterEnabled()) mastersInfos, err := masterClient.GetMasters() if err != nil { return "", err diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go index a318b1e920..1010897dbe 100644 --- a/pkg/discovery/discovery_test.go +++ b/pkg/discovery/discovery_test.go @@ -419,7 +419,7 @@ func TestDiscoveryDMDiscovery(t *testing.T) { masterClient := dmapi.NewFakeMasterClient() if test.dc != nil { cli.PingcapV1alpha1().DMClusters(test.dc.Namespace).Create(test.dc) - fakeMasterControl.SetMasterClient(dmapi.Namespace(test.dc.GetNamespace()), test.dc.GetName(), masterClient) + fakeMasterControl.SetMasterClient(test.dc.GetNamespace(), test.dc.GetName(), masterClient) } masterClient.AddReaction(dmapi.GetMastersActionType, func(action *dmapi.Action) (interface{}, error) { return test.getMastersFn() diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index 78cfabc379..54fae8b138 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -189,7 +189,7 @@ func (mc *masterClient) EvictLeader() error { return fmt.Errorf("unable to unmarshal evict leader resp: %s, err: %s", body, err) } if !evictLeaderResp.Result { - return fmt.Errorf("unable to evict leader leader, err: %s", evictLeaderResp.Msg) + return fmt.Errorf("unable to evict leader, err: %s", evictLeaderResp.Msg) } return nil diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go index a8cae6eda1..a6d1cd14ed 100644 --- a/pkg/dmapi/master_control.go +++ b/pkg/dmapi/master_control.go @@ -26,14 +26,11 @@ import ( "k8s.io/klog" ) -// Namespace is a newtype of a string -type Namespace pdapi.Namespace - // MasterControlInterface is an interface that knows how to manage and get dm cluster's master client type MasterControlInterface interface { // GetMasterClient provides MasterClient of the dm cluster. - GetMasterClient(namespace Namespace, dcName string, tlsEnabled bool) MasterClient - GetMasterPeerClient(namespace Namespace, dcName, podName string, tlsEnabled bool) MasterClient + GetMasterClient(namespace string, dcName string, tlsEnabled bool) MasterClient + GetMasterPeerClient(namespace string, dcName, podName string, tlsEnabled bool) MasterClient } // defaultMasterControl is the default implementation of MasterControlInterface. @@ -49,7 +46,7 @@ func NewDefaultMasterControl(kubeCli kubernetes.Interface) MasterControlInterfac } // GetMasterClient provides a MasterClient of real dm-master cluster, if the MasterClient not existing, it will create new one. -func (mc *defaultMasterControl) GetMasterClient(namespace Namespace, dcName string, tlsEnabled bool) MasterClient { +func (mc *defaultMasterControl) GetMasterClient(namespace string, dcName string, tlsEnabled bool) MasterClient { mc.mutex.Lock() defer mc.mutex.Unlock() @@ -75,7 +72,7 @@ func (mc *defaultMasterControl) GetMasterClient(namespace Namespace, dcName stri return mc.masterClients[key] } -func (mc *defaultMasterControl) GetMasterPeerClient(namespace Namespace, dcName string, podName string, tlsEnabled bool) MasterClient { +func (mc *defaultMasterControl) GetMasterPeerClient(namespace string, dcName string, podName string, tlsEnabled bool) MasterClient { mc.mutex.Lock() defer mc.mutex.Unlock() @@ -98,17 +95,17 @@ func (mc *defaultMasterControl) GetMasterPeerClient(namespace Namespace, dcName } // masterClientKey returns the master client key -func masterClientKey(scheme string, namespace Namespace, clusterName string) string { - return fmt.Sprintf("%s.%s.%s", scheme, clusterName, string(namespace)) +func masterClientKey(scheme string, namespace string, clusterName string) string { + return fmt.Sprintf("%s.%s.%s", scheme, clusterName, namespace) } // MasterClientURL builds the url of master client -func MasterClientURL(namespace Namespace, clusterName string, scheme string) string { - return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, string(namespace)) +func MasterClientURL(namespace string, clusterName string, scheme string) string { + return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, namespace) } -func MasterPeerClientURL(namespace Namespace, clusterName, podName, scheme string) string { - return fmt.Sprintf("%s://%s.%s-dm-master-peer.%s:8261", scheme, podName, clusterName, string(namespace)) +func MasterPeerClientURL(namespace string, clusterName, podName, scheme string) string { + return fmt.Sprintf("%s://%s.%s-dm-master-peer.%s:8261", scheme, podName, clusterName, namespace) } // FakeMasterControl implements a fake version of MasterControlInterface. @@ -122,6 +119,6 @@ func NewFakeMasterControl(kubeCli kubernetes.Interface) *FakeMasterControl { } } -func (fmc *FakeMasterControl) SetMasterClient(namespace Namespace, tcName string, masterClient MasterClient) { +func (fmc *FakeMasterControl) SetMasterClient(namespace string, tcName string, masterClient MasterClient) { fmc.defaultMasterControl.masterClients[masterClientKey("http", namespace, tcName)] = masterClient } diff --git a/pkg/manager/member/dm_master_upgrader.go b/pkg/manager/member/dm_master_upgrader.go index 2be7a202b2..990a21a150 100644 --- a/pkg/manager/member/dm_master_upgrader.go +++ b/pkg/manager/member/dm_master_upgrader.go @@ -91,20 +91,20 @@ func (mu *masterUpgrader) gracefulUpgrade(dc *v1alpha1.DMCluster, oldSet *apps.S revision, exist := pod.Labels[apps.ControllerRevisionHashLabelKey] if !exist { - return controller.RequeueErrorf("tidbcluster: [%s/%s]'s dm-master pod: [%s] has no label: %s", ns, dcName, podName, apps.ControllerRevisionHashLabelKey) + return controller.RequeueErrorf("dmcluster: [%s/%s]'s dm-master pod: [%s] has no label: %s", ns, dcName, podName, apps.ControllerRevisionHashLabelKey) } if revision == dc.Status.Master.StatefulSet.UpdateRevision { if member, exist := dc.Status.Master.Members[podName]; !exist || !member.Health { - return controller.RequeueErrorf("tidbcluster: [%s/%s]'s dm-master upgraded pod: [%s] is not ready", ns, dcName, podName) + return controller.RequeueErrorf("dmcluster: [%s/%s]'s dm-master upgraded pod: [%s] is not ready", ns, dcName, podName) } continue } - if controller.PodWebhookEnabled { - setUpgradePartition(newSet, i) - return nil - } + //if controller.PodWebhookEnabled { + // setUpgradePartition(newSet, i) + // return nil + //} return mu.upgradeMasterPod(dc, i, newSet) } From cdc031aaaa3b30c0745b5a3fbb0032500090a44c Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Fri, 28 Aug 2020 15:12:11 +0800 Subject: [PATCH 29/37] add dm-master scaler --- pkg/apis/pingcap/v1alpha1/crd_kinds.go | 4 +- .../dmcluster/dm_cluster_controller.go | 2 + pkg/dmapi/dmapi.go | 30 +++ pkg/dmapi/fake_dmapi.go | 25 ++- .../member/dm_master_member_manager.go | 10 +- pkg/manager/member/dm_master_scaler.go | 208 ++++++++++++++++++ pkg/manager/member/pd_scaler.go | 40 ++-- pkg/manager/member/scaler.go | 15 +- pkg/manager/member/tiflash_scaler.go | 41 ++-- .../member/tikv_group_member_manager.go | 4 +- pkg/manager/member/tikv_member_manager.go | 4 +- pkg/manager/member/tikv_scaler.go | 12 +- pkg/util/http/httputil.go | 14 +- 13 files changed, 346 insertions(+), 63 deletions(-) create mode 100644 pkg/manager/member/dm_master_scaler.go diff --git a/pkg/apis/pingcap/v1alpha1/crd_kinds.go b/pkg/apis/pingcap/v1alpha1/crd_kinds.go index cbb63f0d00..b4b38bd5ad 100644 --- a/pkg/apis/pingcap/v1alpha1/crd_kinds.go +++ b/pkg/apis/pingcap/v1alpha1/crd_kinds.go @@ -26,7 +26,7 @@ const ( TiDBClusterKindKey = "tidbcluster" DMClusterName = "dmclusters" - DMCLusterKind = "DMCluster" + DMClusterKind = "DMCluster" DMClusterKindKey = "dmcluster" BackupName = "backups" @@ -89,7 +89,7 @@ type CrdKinds struct { var DefaultCrdKinds = CrdKinds{ KindsString: "", TiDBCluster: CrdKind{Plural: TiDBClusterName, Kind: TiDBClusterKind, ShortNames: []string{"tc"}, SpecName: SpecPath + TiDBClusterKind}, - DMCluster: CrdKind{Plural: DMClusterName, Kind: DMCLusterKind, ShortNames: []string{"dc"}, SpecName: SpecPath + DMCLusterKind}, + DMCluster: CrdKind{Plural: DMClusterName, Kind: DMClusterKind, ShortNames: []string{"dc"}, SpecName: SpecPath + DMClusterKind}, Backup: CrdKind{Plural: BackupName, Kind: BackupKind, ShortNames: []string{"bk"}, SpecName: SpecPath + BackupKind}, Restore: CrdKind{Plural: RestoreName, Kind: RestoreKind, ShortNames: []string{"rt"}, SpecName: SpecPath + RestoreKind}, BackupSchedule: CrdKind{Plural: BackupScheduleName, Kind: BackupScheduleKind, ShortNames: []string{"bks"}, SpecName: SpecPath + BackupScheduleKind}, diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index 0e920b5583..db171a461c 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -99,6 +99,7 @@ func NewController( pvcControl := controller.NewRealPVCControl(kubeCli, recorder, pvcInformer.Lister()) //podControl := controller.NewRealPodControl(kubeCli, nil, podInformer.Lister(), recorder) typedControl := controller.NewTypedControl(controller.NewRealGenericControl(genericCli, recorder)) + masterScaler := mm.NewMasterScaler(masterControl, pvcInformer.Lister(), pvcControl) masterUpgrader := mm.NewMasterUpgrader(masterControl, podInformer.Lister()) dcc := &Controller{ @@ -116,6 +117,7 @@ func NewController( podInformer.Lister(), epsInformer.Lister(), pvcInformer.Lister(), + masterScaler, masterUpgrader, ), mm.NewWorkerMemberManager( diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index 54fae8b138..c9a3f93d94 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -34,6 +34,8 @@ type MasterClient interface { GetWorkers() ([]*WorkersInfo, error) GetLeader() (MembersLeader, error) EvictLeader() error + DeleteMaster(name string) error + DeleteWorker(name string) error } var ( @@ -195,6 +197,34 @@ func (mc *masterClient) EvictLeader() error { return nil } +func (mc *masterClient) deleteMember(query string) error { + apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) + body, err := httputil.PutBodyOK(mc.httpClient, apiURL) + if err != nil { + return err + } + deleteMemeberResp := &RespHeader{} + err = json.Unmarshal(body, deleteMemeberResp) + if err != nil { + return fmt.Errorf("unable to unmarshal delete member resp: %s, query: %s, err: %s", body, query, err) + } + if !deleteMemeberResp.Result { + return fmt.Errorf("unable to delete member, query: %s, err: %s", query, deleteMemeberResp.Msg) + } + + return nil +} + +func (mc *masterClient) DeleteMaster(name string) error { + query := "/master/" + name + return mc.deleteMember(query) +} + +func (mc *masterClient) DeleteWorker(name string) error { + query := "/worker/" + name + return mc.deleteMember(query) +} + // NewMasterClient returns a new MasterClient func NewMasterClient(url string, timeout time.Duration, tlsConfig *tls.Config) MasterClient { var disableKeepalive bool diff --git a/pkg/dmapi/fake_dmapi.go b/pkg/dmapi/fake_dmapi.go index 8eb2a251ac..90fbedab27 100644 --- a/pkg/dmapi/fake_dmapi.go +++ b/pkg/dmapi/fake_dmapi.go @@ -20,10 +20,12 @@ import ( type ActionType string const ( - GetMastersActionType ActionType = "GetMasters" - GetWorkersActionType ActionType = "GetWorkers" - GetLeaderActionType ActionType = "GetLeader" - EvictLeaderActionType ActionType = "EvictLeader" + GetMastersActionType ActionType = "GetMasters" + GetWorkersActionType ActionType = "GetWorkers" + GetLeaderActionType ActionType = "GetLeader" + EvictLeaderActionType ActionType = "EvictLeader" + DeleteMasterActionType ActionType = "DeleteMaster" + DeleteWorkerActionType ActionType = "DeleteWorker" ) type NotFoundReaction struct { @@ -97,8 +99,17 @@ func (pc *FakeMasterClient) GetLeader() (MembersLeader, error) { func (pc *FakeMasterClient) EvictLeader() error { action := &Action{} _, err := pc.fakeAPI(EvictLeaderActionType, action) - if err != nil { - return err - } + return err +} + +func (pc *FakeMasterClient) DeleteMaster(_ string) error { + action := &Action{} + _, err := pc.fakeAPI(DeleteMasterActionType, action) + return err +} + +func (pc *FakeMasterClient) DeleteWorker(_ string) error { + action := &Action{} + _, err := pc.fakeAPI(DeleteWorkerActionType, action) return err } diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index b97340a79d..20639953bb 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -57,6 +57,7 @@ type masterMemberManager struct { podLister corelisters.PodLister epsLister corelisters.EndpointsLister pvcLister corelisters.PersistentVolumeClaimLister + masterScaler Scaler masterUpgrader DMUpgrader } @@ -70,6 +71,7 @@ func NewMasterMemberManager(masterControl dmapi.MasterControlInterface, podLister corelisters.PodLister, epsLister corelisters.EndpointsLister, pvcLister corelisters.PersistentVolumeClaimLister, + masterScaler Scaler, masterUpgrader DMUpgrader) manager.DMManager { return &masterMemberManager{ masterControl, @@ -81,6 +83,7 @@ func NewMasterMemberManager(masterControl dmapi.MasterControlInterface, podLister, epsLister, pvcLister, + masterScaler, masterUpgrader} } @@ -243,10 +246,9 @@ func (mmm *masterMemberManager) syncMasterStatefulSetForDMCluster(dc *v1alpha1.D } } - // TODO: dm add scaler - //if err := mmm.masterScaler.Scale(dc, oldMasterSet, newMasterSet); err != nil { - // return err - //} + if err := mmm.masterScaler.Scale(dc, oldMasterSet, newMasterSet); err != nil { + return err + } // TODO: dm add auto failover // if mmm.autoFailover { diff --git a/pkg/manager/member/dm_master_scaler.go b/pkg/manager/member/dm_master_scaler.go new file mode 100644 index 0000000000..bb3238e7d5 --- /dev/null +++ b/pkg/manager/member/dm_master_scaler.go @@ -0,0 +1,208 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package member + +import ( + "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/pingcap/tidb-operator/pkg/label" + + "github.com/pingcap/advanced-statefulset/client/apis/apps/v1/helper" + + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/dmapi" + apps "k8s.io/api/apps/v1" + corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/klog" +) + +type masterScaler struct { + generalScaler + masterControl dmapi.MasterControlInterface +} + +// NewMasterScaler returns a DMScaler +func NewMasterScaler(masterControl dmapi.MasterControlInterface, + pvcLister corelisters.PersistentVolumeClaimLister, + pvcControl controller.PVCControlInterface) Scaler { + return &masterScaler{ + generalScaler: generalScaler{ + pvcLister: pvcLister, + pvcControl: pvcControl, + }, + masterControl: masterControl, + } +} + +func (msd *masterScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + scaling, _, _, _ := scaleOne(oldSet, newSet) + if scaling > 0 { + return msd.ScaleOut(meta, oldSet, newSet) + } else if scaling < 0 { + return msd.ScaleIn(meta, oldSet, newSet) + } + return msd.SyncAutoScalerAnn(meta, oldSet) +} + +func (msd *masterScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + dc, ok := meta.(*v1alpha1.DMCluster) + if !ok { + return nil + } + + _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) + resetReplicas(newSet, oldSet) + ns := dc.GetNamespace() + dcName := dc.GetName() + if dc.MasterUpgrading() { + return nil + } + + klog.Infof("scaling out dm-master statefulset %s/%s, ordinal: %d (replicas: %d, delete slots: %v)", oldSet.Namespace, oldSet.Name, ordinal, replicas, deleteSlots.List()) + _, err := msd.deleteDeferDeletingPVC(dc, oldSet.GetName(), v1alpha1.DMMasterMemberType, ordinal) + if err != nil { + return err + } + + if !dc.Status.Master.Synced { + return fmt.Errorf("DMCluster: %s/%s's dm-master status sync failed, can't scale out now", ns, dcName) + } + + if len(dc.Status.Master.FailureMembers) != 0 { + setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + return nil + } + + healthCount := 0 + totalCount := *oldSet.Spec.Replicas + podOrdinals := helper.GetPodOrdinals(*oldSet.Spec.Replicas, oldSet).List() + for _, i := range podOrdinals { + podName := ordinalPodName(v1alpha1.DMMasterMemberType, dcName, i) + if member, ok := dc.Status.Master.Members[podName]; ok && member.Health { + healthCount++ + } + } + if healthCount < int(totalCount) { + return fmt.Errorf("DMCluster: %s/%s's dm-master %d/%d is ready, can't scale out now", + ns, dcName, healthCount, totalCount) + } + + setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + return nil +} + +// We need remove member from cluster before reducing statefulset replicas +// only remove one member at a time when scale down +func (msd *masterScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + dc, ok := meta.(*v1alpha1.DMCluster) + if !ok { + return nil + } + + ns := dc.GetNamespace() + dcName := dc.GetName() + _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) + resetReplicas(newSet, oldSet) + memberName := ordinalPodName(v1alpha1.DMMasterMemberType, dcName, ordinal) + setName := oldSet.GetName() + + if dc.MasterUpgrading() { + return nil + } + + if !dc.Status.Master.Synced { + return fmt.Errorf("DMCluster: %s/%s's dm-master status sync failed, can't scale in now", ns, dcName) + } + + klog.Infof("scaling in dm-master statefulset %s/%s, ordinal: %d (replicas: %d, delete slots: %v)", oldSet.Namespace, oldSet.Name, ordinal, replicas, deleteSlots.List()) + + if controller.PodWebhookEnabled { + setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + return nil + } + + // If the dm-master pod was dm-master leader during scale-in, we would evict dm-master leader first + // If the dm-master statefulSet would be scale-in to zero and the dm-master-0 was going to be deleted, + // we would directly deleted the dm-master-0 without dm-master leader evict + if ordinal > 0 { + if dc.Status.Master.Leader.Name == memberName { + masterPeerClient := controller.GetMasterPeerClient(msd.masterControl, dc, memberName) + err := masterPeerClient.EvictLeader() + if err != nil { + return err + } + return controller.RequeueErrorf("dc [%s/%s]'s dm-master pod[%s/%s] is transferring dm-master leader, can't scale-in now", ns, dcName, ns, memberName) + } + } + + masterClient := controller.GetMasterClient(msd.masterControl, dc) + err := masterClient.DeleteMaster(memberName) + if err != nil { + klog.Errorf("dm-master scale in: failed to delete member %s, %v", memberName, err) + return err + } + klog.Infof("dm-master scale in: delete member %s successfully", memberName) + + // double check whether member deleted after delete member + mastersInfo, err := masterClient.GetMasters() + if err != nil { + klog.Errorf("dm-master scale in: failed to get dm-masters %s, %v", memberName, err) + return err + } + + existed := false + for _, member := range mastersInfo { + if member.Name == memberName { + existed = true + break + } + } + if existed { + err = fmt.Errorf("dm-master scale in: dm-master %s still exist after being deleted", memberName) + klog.Error(err) + return err + } + + pvcName := ordinalPVCName(v1alpha1.DMMasterMemberType, setName, ordinal) + pvc, err := msd.pvcLister.PersistentVolumeClaims(ns).Get(pvcName) + if err != nil { + return fmt.Errorf("dm-master.ScaleIn: failed to get pvc %s for cluster %s/%s, error: %s", pvcName, ns, dcName, err) + } + + if pvc.Annotations == nil { + pvc.Annotations = map[string]string{} + } + now := time.Now().Format(time.RFC3339) + pvc.Annotations[label.AnnPVCDeferDeleting] = now + + _, err = msd.pvcControl.UpdatePVC(dc, pvc) + if err != nil { + klog.Errorf("dm-master scale in: failed to set pvc %s/%s annotation: %s to %s", + ns, pvcName, label.AnnPVCDeferDeleting, now) + return err + } + klog.Infof("dm-master scale in: set pvc %s/%s annotation: %s to %s", + ns, pvcName, label.AnnPVCDeferDeleting, now) + + setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + return nil +} + +func (msd *masterScaler) SyncAutoScalerAnn(meta metav1.Object, oldSet *apps.StatefulSet) error { + return nil +} diff --git a/pkg/manager/member/pd_scaler.go b/pkg/manager/member/pd_scaler.go index 281c3156e6..ccc697ed11 100644 --- a/pkg/manager/member/pd_scaler.go +++ b/pkg/manager/member/pd_scaler.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/tidb-operator/pkg/label" "github.com/pingcap/tidb-operator/pkg/pdapi" apps "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" ) @@ -31,26 +32,32 @@ import ( type pdScaler struct { generalScaler + pdControl pdapi.PDControlInterface } // NewPDScaler returns a Scaler func NewPDScaler(pdControl pdapi.PDControlInterface, pvcLister corelisters.PersistentVolumeClaimLister, pvcControl controller.PVCControlInterface) Scaler { - return &pdScaler{generalScaler{pdControl, pvcLister, pvcControl}} + return &pdScaler{generalScaler{pvcLister, pvcControl}, pdControl} } -func (psd *pdScaler) Scale(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (psd *pdScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { scaling, _, _, _ := scaleOne(oldSet, newSet) if scaling > 0 { - return psd.ScaleOut(tc, oldSet, newSet) + return psd.ScaleOut(meta, oldSet, newSet) } else if scaling < 0 { - return psd.ScaleIn(tc, oldSet, newSet) + return psd.ScaleIn(meta, oldSet, newSet) } - return psd.SyncAutoScalerAnn(tc, oldSet) + return psd.SyncAutoScalerAnn(meta, oldSet) } -func (psd *pdScaler) ScaleOut(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (psd *pdScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + tc, ok := meta.(*v1alpha1.TidbCluster) + if !ok { + return nil + } + _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) resetReplicas(newSet, oldSet) ns := tc.GetNamespace() @@ -94,7 +101,12 @@ func (psd *pdScaler) ScaleOut(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet // We need remove member from cluster before reducing statefulset replicas // only remove one member at a time when scale down -func (psd *pdScaler) ScaleIn(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (psd *pdScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + tc, ok := meta.(*v1alpha1.TidbCluster) + if !ok { + return nil + } + ns := tc.GetNamespace() tcName := tc.GetName() _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) @@ -189,7 +201,7 @@ func (psd *pdScaler) ScaleIn(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, return nil } -func (psd *pdScaler) SyncAutoScalerAnn(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet) error { +func (psd *pdScaler) SyncAutoScalerAnn(meta metav1.Object, actual *apps.StatefulSet) error { return nil } @@ -200,25 +212,25 @@ func NewFakePDScaler() Scaler { return &fakePDScaler{} } -func (fsd *fakePDScaler) Scale(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (fsd *fakePDScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { if *newSet.Spec.Replicas > *oldSet.Spec.Replicas { - return fsd.ScaleOut(tc, oldSet, newSet) + return fsd.ScaleOut(meta, oldSet, newSet) } else if *newSet.Spec.Replicas < *oldSet.Spec.Replicas { - return fsd.ScaleIn(tc, oldSet, newSet) + return fsd.ScaleIn(meta, oldSet, newSet) } return nil } -func (fsd *fakePDScaler) ScaleOut(_ *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (fsd *fakePDScaler) ScaleOut(_ metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { setReplicasAndDeleteSlots(newSet, *oldSet.Spec.Replicas+1, nil) return nil } -func (fsd *fakePDScaler) ScaleIn(_ *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (fsd *fakePDScaler) ScaleIn(_ metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { setReplicasAndDeleteSlots(newSet, *oldSet.Spec.Replicas-1, nil) return nil } -func (fsd *fakePDScaler) SyncAutoScalerAnn(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet) error { +func (fsd *fakePDScaler) SyncAutoScalerAnn(tc metav1.Object, actual *apps.StatefulSet) error { return nil } diff --git a/pkg/manager/member/scaler.go b/pkg/manager/member/scaler.go index 5093d1b2e4..52ce757d11 100644 --- a/pkg/manager/member/scaler.go +++ b/pkg/manager/member/scaler.go @@ -22,7 +22,6 @@ import ( "github.com/pingcap/tidb-operator/pkg/controller" "github.com/pingcap/tidb-operator/pkg/features" "github.com/pingcap/tidb-operator/pkg/label" - "github.com/pingcap/tidb-operator/pkg/pdapi" apps "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -40,17 +39,16 @@ const ( // Scaler implements the logic for scaling out or scaling in the cluster. type Scaler interface { // Scale scales the cluster. It does nothing if scaling is not needed. - Scale(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet, desired *apps.StatefulSet) error + Scale(meta metav1.Object, actual *apps.StatefulSet, desired *apps.StatefulSet) error // ScaleOut scales out the cluster - ScaleOut(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet, desired *apps.StatefulSet) error + ScaleOut(meta metav1.Object, actual *apps.StatefulSet, desired *apps.StatefulSet) error // ScaleIn scales in the cluster - ScaleIn(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet, desired *apps.StatefulSet) error + ScaleIn(meta metav1.Object, actual *apps.StatefulSet, desired *apps.StatefulSet) error // SyncAutoScalerAnn would sync Ann created by AutoScaler - SyncAutoScalerAnn(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet) error + SyncAutoScalerAnn(meta metav1.Object, actual *apps.StatefulSet) error } type generalScaler struct { - pdControl pdapi.PDControlInterface pvcLister corelisters.PersistentVolumeClaimLister pvcControl controller.PVCControlInterface } @@ -74,6 +72,11 @@ func (gs *generalScaler) deleteDeferDeletingPVC(controller runtime.Object, l = label.NewGroup().Instance(meta.GetName()) // TODO: support sync meta info into TiKVGroup resources (pod/pvc) kind = v1alpha1.TiKVGroupKind + case *v1alpha1.DMCluster: + podName = ordinalPodName(memberType, meta.GetName(), ordinal) + l = label.New().Instance(meta.GetName()) + l[label.AnnPodNameKey] = podName + kind = v1alpha1.DMClusterKind default: kind = controller.GetObjectKind().GroupVersionKind().Kind return nil, fmt.Errorf("%s[%s/%s] has unknown controller", kind, ns, meta.GetName()) diff --git a/pkg/manager/member/tiflash_scaler.go b/pkg/manager/member/tiflash_scaler.go index ee1af6a42b..ae34a89e25 100644 --- a/pkg/manager/member/tiflash_scaler.go +++ b/pkg/manager/member/tiflash_scaler.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/tidb-operator/pkg/label" "github.com/pingcap/tidb-operator/pkg/pdapi" apps "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" podutil "k8s.io/kubernetes/pkg/api/v1/pod" @@ -30,6 +31,7 @@ import ( type tiflashScaler struct { generalScaler + pdControl pdapi.PDControlInterface podLister corelisters.PodLister } @@ -38,21 +40,26 @@ func NewTiFlashScaler(pdControl pdapi.PDControlInterface, pvcLister corelisters.PersistentVolumeClaimLister, pvcControl controller.PVCControlInterface, podLister corelisters.PodLister) Scaler { - return &tiflashScaler{generalScaler{pdControl, pvcLister, pvcControl}, podLister} + return &tiflashScaler{generalScaler{pvcLister, pvcControl}, pdControl, podLister} } -func (tfs *tiflashScaler) Scale(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (tfs *tiflashScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { scaling, _, _, _ := scaleOne(oldSet, newSet) if scaling > 0 { - return tfs.ScaleOut(tc, oldSet, newSet) + return tfs.ScaleOut(meta, oldSet, newSet) } else if scaling < 0 { - return tfs.ScaleIn(tc, oldSet, newSet) + return tfs.ScaleIn(meta, oldSet, newSet) } // we only sync auto scaler annotations when we are finishing syncing scaling - return tfs.SyncAutoScalerAnn(tc, oldSet) + return tfs.SyncAutoScalerAnn(meta, oldSet) } -func (tfs *tiflashScaler) ScaleOut(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (tfs *tiflashScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + tc, ok := meta.(*v1alpha1.TidbCluster) + if !ok { + return nil + } + _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) resetReplicas(newSet, oldSet) if tc.TiFlashUpgrading() { @@ -69,7 +76,12 @@ func (tfs *tiflashScaler) ScaleOut(tc *v1alpha1.TidbCluster, oldSet *apps.Statef return nil } -func (tfs *tiflashScaler) ScaleIn(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (tfs *tiflashScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + tc, ok := meta.(*v1alpha1.TidbCluster) + if !ok { + return nil + } + ns := tc.GetNamespace() tcName := tc.GetName() // we can only remove one member at a time when scaling in @@ -165,8 +177,7 @@ func (tfs *tiflashScaler) ScaleIn(tc *v1alpha1.TidbCluster, oldSet *apps.Statefu } // SyncAutoScalerAnn reclaims the auto-scaling-out slots if the target pods no longer exist -func (tfs *tiflashScaler) SyncAutoScalerAnn(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet) error { - +func (tfs *tiflashScaler) SyncAutoScalerAnn(meta metav1.Object, actual *apps.StatefulSet) error { return nil } @@ -177,25 +188,25 @@ func NewFakeTiFlashScaler() Scaler { return &fakeTiFlashScaler{} } -func (fsd *fakeTiFlashScaler) Scale(tc *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (fsd *fakeTiFlashScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { if *newSet.Spec.Replicas > *oldSet.Spec.Replicas { - return fsd.ScaleOut(tc, oldSet, newSet) + return fsd.ScaleOut(meta, oldSet, newSet) } else if *newSet.Spec.Replicas < *oldSet.Spec.Replicas { - return fsd.ScaleIn(tc, oldSet, newSet) + return fsd.ScaleIn(meta, oldSet, newSet) } return nil } -func (fsd *fakeTiFlashScaler) ScaleOut(_ *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (fsd *fakeTiFlashScaler) ScaleOut(_ metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { setReplicasAndDeleteSlots(newSet, *oldSet.Spec.Replicas+1, nil) return nil } -func (fsd *fakeTiFlashScaler) ScaleIn(_ *v1alpha1.TidbCluster, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { +func (fsd *fakeTiFlashScaler) ScaleIn(_ metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { setReplicasAndDeleteSlots(newSet, *oldSet.Spec.Replicas-1, nil) return nil } -func (fsd *fakeTiFlashScaler) SyncAutoScalerAnn(tc *v1alpha1.TidbCluster, actual *apps.StatefulSet) error { +func (fsd *fakeTiFlashScaler) SyncAutoScalerAnn(meta metav1.Object, actual *apps.StatefulSet) error { return nil } diff --git a/pkg/manager/member/tikv_group_member_manager.go b/pkg/manager/member/tikv_group_member_manager.go index 5b85bf0295..6fcf1c404c 100644 --- a/pkg/manager/member/tikv_group_member_manager.go +++ b/pkg/manager/member/tikv_group_member_manager.go @@ -64,7 +64,7 @@ type tikvGroupMemberManager struct { svcControl controller.ServiceControlInterface setControl controller.StatefulSetControlInterface typedControl controller.TypedControlInterface - tikvGroupScaler TiKVScaler + tikvGroupScaler Scaler tikvGroupUpgrader *TikvGroupUpgrader pdControl pdapi.PDControlInterface } @@ -77,7 +77,7 @@ func NewTiKVGroupMemberManager( svcControl controller.ServiceControlInterface, setControl controller.StatefulSetControlInterface, typedControl controller.TypedControlInterface, - tikvGroupScaler TiKVScaler, + tikvGroupScaler Scaler, tikvUpgrader *TikvGroupUpgrader, pdControl pdapi.PDControlInterface) manager.TiKVGroupManager { return &tikvGroupMemberManager{ diff --git a/pkg/manager/member/tikv_member_manager.go b/pkg/manager/member/tikv_member_manager.go index 4ea507d86d..68fea88929 100644 --- a/pkg/manager/member/tikv_member_manager.go +++ b/pkg/manager/member/tikv_member_manager.go @@ -64,7 +64,7 @@ type tikvMemberManager struct { nodeLister corelisters.NodeLister autoFailover bool tikvFailover Failover - tikvScaler TiKVScaler + tikvScaler Scaler tikvUpgrader TiKVUpgrader recorder record.EventRecorder tikvStatefulSetIsUpgradingFn func(corelisters.PodLister, pdapi.PDControlInterface, *apps.StatefulSet, *v1alpha1.TidbCluster) (bool, error) @@ -82,7 +82,7 @@ func NewTiKVMemberManager( nodeLister corelisters.NodeLister, autoFailover bool, tikvFailover Failover, - tikvScaler TiKVScaler, + tikvScaler Scaler, tikvUpgrader TiKVUpgrader, recorder record.EventRecorder) manager.Manager { kvmm := tikvMemberManager{ diff --git a/pkg/manager/member/tikv_scaler.go b/pkg/manager/member/tikv_scaler.go index b0b9582e63..33f54828c3 100644 --- a/pkg/manager/member/tikv_scaler.go +++ b/pkg/manager/member/tikv_scaler.go @@ -33,15 +33,9 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" ) -type TiKVScaler interface { - Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error - ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error - ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error - SyncAutoScalerAnn(meta metav1.Object, actual *apps.StatefulSet) error -} - type tikvScaler struct { generalScaler + pdControl pdapi.PDControlInterface podLister corelisters.PodLister } @@ -50,7 +44,7 @@ func NewTiKVScaler(pdControl pdapi.PDControlInterface, pvcLister corelisters.PersistentVolumeClaimLister, pvcControl controller.PVCControlInterface, podLister corelisters.PodLister) *tikvScaler { - return &tikvScaler{generalScaler{pdControl, pvcLister, pvcControl}, podLister} + return &tikvScaler{generalScaler{pvcLister, pvcControl}, pdControl, podLister} } func (tsd *tikvScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { @@ -257,7 +251,7 @@ func (tsd *tikvScaler) SyncAutoScalerAnn(meta metav1.Object, actual *apps.Statef type fakeTiKVScaler struct{} // NewFakeTiKVScaler returns a fake tikv Scaler -func NewFakeTiKVScaler() TiKVScaler { +func NewFakeTiKVScaler() Scaler { return &fakeTiKVScaler{} } diff --git a/pkg/util/http/httputil.go b/pkg/util/http/httputil.go index 976bf595d5..e3a71fdbea 100644 --- a/pkg/util/http/httputil.go +++ b/pkg/util/http/httputil.go @@ -58,9 +58,19 @@ func GetBodyOK(httpClient *http.Client, apiURL string) ([]byte, error) { return body, err } -// PutBodyOK returns the body or an error if the response is not okay +// PutBodyOK will PUT and returns the body or an error if the response is not okay func PutBodyOK(httpClient *http.Client, apiURL string) ([]byte, error) { - req, err := http.NewRequest("PUT", apiURL, nil) + return DoBodyOK(httpClient, apiURL, "PUT") +} + +// DeleteBodyOK will DELETE and returns the body or an error if the response is not okay +func DeleteBodyOK(httpClient *http.Client, apiURL string) ([]byte, error) { + return DoBodyOK(httpClient, apiURL, "DELETE") +} + +// DoBodyOK returns the body or an error if the response is not okay +func DoBodyOK(httpClient *http.Client, apiURL, method string) ([]byte, error) { + req, err := http.NewRequest(method, apiURL, nil) if err != nil { return nil, err } From bb94d5efdc5a0f318fbfc20a72a3ecb680079a21 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Fri, 28 Aug 2020 17:36:36 +0800 Subject: [PATCH 30/37] tmp --- examples/dm/dm-cluster.yaml | 4 ++-- pkg/dmapi/dmapi.go | 2 +- pkg/manager/member/dm_worker_member_manager.go | 13 +++++++++++++ pkg/manager/member/scaler.go | 5 +++-- pkg/manager/member/template.go | 3 ++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/examples/dm/dm-cluster.yaml b/examples/dm/dm-cluster.yaml index 3b4b0f780c..5ccacbe0f2 100644 --- a/examples/dm/dm-cluster.yaml +++ b/examples/dm/dm-cluster.yaml @@ -10,7 +10,7 @@ spec: address: "http://basic-discovery.demo:10261" master: baseImage: pingcap/dm - replicas: 1 + replicas: 3 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage storageSize: "1Gi" @@ -18,7 +18,7 @@ spec: config: {} worker: baseImage: pingcap/dm - replicas: 1 + replicas: 3 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage storageSize: "1Gi" diff --git a/pkg/dmapi/dmapi.go b/pkg/dmapi/dmapi.go index c9a3f93d94..5cb4e57b75 100644 --- a/pkg/dmapi/dmapi.go +++ b/pkg/dmapi/dmapi.go @@ -199,7 +199,7 @@ func (mc *masterClient) EvictLeader() error { func (mc *masterClient) deleteMember(query string) error { apiURL := fmt.Sprintf("%s/%s%s", mc.url, membersPrefix, query) - body, err := httputil.PutBodyOK(mc.httpClient, apiURL) + body, err := httputil.DeleteBodyOK(mc.httpClient, apiURL) if err != nil { return err } diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index c09a08c52b..e5f3d40bec 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -259,6 +259,19 @@ func (wmm *workerMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set } workerStatus[name] = status + + // offline the workers that already been scaled-in + if status.Stage == "offline" { + ordinal, err := util.GetOrdinalFromPodName(worker.Name) + if err != nil { + klog.Errorf("invalid worker name %s, can't offline this worker automatically, err: %s", worker.Name, err) + } else if ordinal >= dc.WorkerStsDesiredReplicas() { + err := dmClient.DeleteWorker(name) + if err != nil { + klog.Errorf("fail to remove worker %s, err: %s", worker.Name, err) + } + } + } } dc.Status.Worker.Synced = true diff --git a/pkg/manager/member/scaler.go b/pkg/manager/member/scaler.go index 52ce757d11..3ebcc3413b 100644 --- a/pkg/manager/member/scaler.go +++ b/pkg/manager/member/scaler.go @@ -74,8 +74,9 @@ func (gs *generalScaler) deleteDeferDeletingPVC(controller runtime.Object, kind = v1alpha1.TiKVGroupKind case *v1alpha1.DMCluster: podName = ordinalPodName(memberType, meta.GetName(), ordinal) - l = label.New().Instance(meta.GetName()) - l[label.AnnPodNameKey] = podName + l = label.NewDM().Instance(meta.GetName()) + // just delete all defer Deleting pvc for convenience. Or dm have to support sync meta info labels for pod/pvc which seems unnecessary + // l[label.AnnPodNameKey] = podName kind = v1alpha1.DMClusterKind default: kind = controller.GetObjectKind().GroupVersionKind().Kind diff --git a/pkg/manager/member/template.go b/pkg/manager/member/template.go index 846e4f3c9d..01be1a6a83 100644 --- a/pkg/manager/member/template.go +++ b/pkg/manager/member/template.go @@ -500,7 +500,8 @@ fi # Use HOSTNAME if POD_NAME is unset for backward compatibility. POD_NAME=${POD_NAME:-$HOSTNAME} # TODO: dm-worker will support data-dir in the future -ARGS="--join={{ .MasterAddress }} \ +ARGS="--name=${POD_NAME} \ +--join={{ .MasterAddress }} \ --advertise-addr=${POD_NAME}.${HEADLESS_SERVICE_NAME}:8262 \ --worker-addr=0.0.0.0:8262 \ --config=/etc/dm-worker/dm-worker.toml From d5cfc314ed651efd9c8600e1400fd0c244f6b2b8 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Mon, 31 Aug 2020 10:32:00 +0800 Subject: [PATCH 31/37] support scale dm cluster --- pkg/apis/pingcap/v1alpha1/dmcluster.go | 8 ++ .../dmcluster/dm_cluster_control.go | 91 ++++++------- .../dmcluster/dm_cluster_controller.go | 28 ++-- pkg/manager/manager.go | 2 +- .../member/dm_master_member_manager.go | 2 +- .../member/dm_worker_member_manager.go | 2 +- pkg/manager/member/orphan_pods_cleaner.go | 36 +++-- pkg/manager/member/pod_restarter.go | 34 +++-- pkg/manager/member/pvc_cleaner.go | 123 +++++++++++------- pkg/manager/meta/reclaim_policy_manager.go | 16 +++ 10 files changed, 215 insertions(+), 127 deletions(-) diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go index cd48d44c6f..909379c11c 100644 --- a/pkg/apis/pingcap/v1alpha1/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -33,6 +33,14 @@ func (dc *DMCluster) Timezone() string { return tz } +func (dc *DMCluster) IsPVReclaimEnabled() bool { + enabled := dc.Spec.EnablePVReclaim + if enabled == nil { + return defaultEnablePVReclaim + } + return *enabled +} + func (dc *DMCluster) IsTLSClusterEnabled() bool { return dc.Spec.TLSCluster != nil && dc.Spec.TLSCluster.Enabled } diff --git a/pkg/controller/dmcluster/dm_cluster_control.go b/pkg/controller/dmcluster/dm_cluster_control.go index dd3b55bbbb..70e271b319 100644 --- a/pkg/controller/dmcluster/dm_cluster_control.go +++ b/pkg/controller/dmcluster/dm_cluster_control.go @@ -41,23 +41,23 @@ func NewDefaultDMClusterControl( dcControl controller.DMClusterControlInterface, masterMemberManager manager.DMManager, workerMemberManager manager.DMManager, - //reclaimPolicyManager manager.DMManager, + reclaimPolicyManager manager.DMManager, //metaManager manager.DMManager, - //orphanPodsCleaner member.OrphanPodsCleaner, + orphanPodsCleaner member.OrphanPodsCleaner, pvcCleaner member.PVCCleanerInterface, pvcResizer member.PVCResizerInterface, - //podRestarter member.PodRestarter, + podRestarter member.PodRestarter, conditionUpdater DMClusterConditionUpdater, recorder record.EventRecorder) ControlInterface { return &defaultDMClusterControl{ dcControl, masterMemberManager, workerMemberManager, - //reclaimPolicyManager, + reclaimPolicyManager, //metaManager, - //orphanPodsCleaner, + orphanPodsCleaner, pvcCleaner, - //podRestarter, + podRestarter, pvcResizer, conditionUpdater, recorder, @@ -65,17 +65,17 @@ func NewDefaultDMClusterControl( } type defaultDMClusterControl struct { - dcControl controller.DMClusterControlInterface - masterMemberManager manager.DMManager - workerMemberManager manager.DMManager - //reclaimPolicyManager manager.DMManager + dcControl controller.DMClusterControlInterface + masterMemberManager manager.DMManager + workerMemberManager manager.DMManager + reclaimPolicyManager manager.DMManager //metaManager manager.DMManager - //orphanPodsCleaner member.OrphanPodsCleaner - pvcCleaner member.PVCCleanerInterface - //podRestarter member.PodRestarter - pvcResizer member.PVCResizerInterface - conditionUpdater DMClusterConditionUpdater - recorder record.EventRecorder + orphanPodsCleaner member.OrphanPodsCleaner + pvcCleaner member.PVCCleanerInterface + podRestarter member.PodRestarter + pvcResizer member.PVCResizerInterface + conditionUpdater DMClusterConditionUpdater + recorder record.EventRecorder } // UpdateStatefulSet executes the core logic loop for a dmcluster. @@ -123,29 +123,25 @@ func (dcc *defaultDMClusterControl) validate(dc *v1alpha1.DMCluster) bool { func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) error { var errs []error - // TODO: implement reclaimPolicyManager - // syncing all PVs managed by operator's reclaim policy to Retain - // if err := dcc.reclaimPolicyManager.Sync(dc); err != nil { - // return err - // } + if err := dcc.reclaimPolicyManager.SyncDM(dc); err != nil { + return err + } - // TODO: add orphanPodsCleaner for dm cluster - // cleaning all orphan pods(pd, tikv or tiflash which don't have a related PVC) managed by operator - // skipReasons, err := dcc.orphanPodsCleaner.Clean(dc) - // if err != nil { - // return err - // } - // if klog.V(10) { - // for podName, reason := range skipReasons { - // klog.Infof("pod %s of cluster %s/%s is skipped, reason %q", podName, dc.Namespace, dc.Name, reason) - // } - // } + // cleaning all orphan pods(dm-master or dm-worker which don't have a related PVC) managed by operator + skipReasons, err := dcc.orphanPodsCleaner.Clean(dc) + if err != nil { + return err + } + if klog.V(10) { + for podName, reason := range skipReasons { + klog.Infof("pod %s of cluster %s/%s is skipped, reason %q", podName, dc.Namespace, dc.Name, reason) + } + } - // TODO: restarted pods in dm cluster // sync all the pods which need to be restarted - // if err := dcc.podRestarter.Sync(dc); err != nil { - // return err - // } + if err := dcc.podRestarter.Sync(dc); err != nil { + return err + } // works that should do to making the dm-master cluster current state match the desired state: // - create or update the dm-master service @@ -158,7 +154,7 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // - upgrade the dm-master cluster // - scale out/in the dm-master cluster // - failover the dm-master cluster - if err := dcc.masterMemberManager.Sync(dc); err != nil { + if err := dcc.masterMemberManager.SyncDM(dc); err != nil { errs = append(errs, err) } @@ -170,7 +166,7 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // - upgrade the dm-worker cluster // - scale out/in the dm-worker cluster // - failover the dm-worker cluster - if err := dcc.workerMemberManager.Sync(dc); err != nil { + if err := dcc.workerMemberManager.SyncDM(dc); err != nil { errs = append(errs, err) } @@ -182,16 +178,15 @@ func (dcc *defaultDMClusterControl) updateDMCluster(dc *v1alpha1.DMCluster) erro // return err // } - // TODO: clean pods cleaning the pod scheduling annotation for dm cluster - // pvcSkipReasons, err := dcc.pvcCleaner.Clean(dc) - // if err != nil { - // return err - // } - // if klog.V(10) { - // for pvcName, reason := range pvcSkipReasons { - // klog.Infof("pvc %s of cluster %s/%s is skipped, reason %q", pvcName, dc.Namespace, dc.Name, reason) - // } - // } + pvcSkipReasons, err := dcc.pvcCleaner.Clean(dc) + if err != nil { + return err + } + if klog.V(10) { + for pvcName, reason := range pvcSkipReasons { + klog.Infof("pvc %s of cluster %s/%s is skipped, reason %q", pvcName, dc.Namespace, dc.Name, reason) + } + } // TODO: sync dm cluster attributes // syncing the some tidbcluster status attributes diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index db171a461c..03e0af70b4 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb-operator/pkg/controller" "github.com/pingcap/tidb-operator/pkg/dmapi" mm "github.com/pingcap/tidb-operator/pkg/manager/member" + "github.com/pingcap/tidb-operator/pkg/manager/meta" apps "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -97,10 +98,11 @@ func NewController( svcControl := controller.NewRealServiceControl(kubeCli, svcInformer.Lister(), recorder) pvControl := controller.NewRealPVControl(kubeCli, pvcInformer.Lister(), pvInformer.Lister(), recorder) pvcControl := controller.NewRealPVCControl(kubeCli, recorder, pvcInformer.Lister()) - //podControl := controller.NewRealPodControl(kubeCli, nil, podInformer.Lister(), recorder) + podControl := controller.NewRealPodControl(kubeCli, nil, podInformer.Lister(), recorder) typedControl := controller.NewTypedControl(controller.NewRealGenericControl(genericCli, recorder)) masterScaler := mm.NewMasterScaler(masterControl, pvcInformer.Lister(), pvcControl) masterUpgrader := mm.NewMasterUpgrader(masterControl, podInformer.Lister()) + podRestarter := mm.NewPodRestarter(kubeCli, podInformer.Lister()) dcc := &Controller{ kubeClient: kubeCli, @@ -129,11 +131,11 @@ func NewController( svcInformer.Lister(), podInformer.Lister(), ), - //meta.NewReclaimPolicyManager( - // pvcInformer.Lister(), - // pvInformer.Lister(), - // pvControl, - //), + meta.NewReclaimPolicyDMManager( + pvcInformer.Lister(), + pvInformer.Lister(), + pvControl, + ), //meta.NewMetaManager( // pvcInformer.Lister(), // pvcControl, @@ -142,12 +144,12 @@ func NewController( // podInformer.Lister(), // podControl, //), - //mm.NewOrphanPodsCleaner( - // podInformer.Lister(), - // podControl, - // pvcInformer.Lister(), - // kubeCli, - //), + mm.NewOrphanPodsCleaner( + podInformer.Lister(), + podControl, + pvcInformer.Lister(), + kubeCli, + ), mm.NewRealPVCCleaner( kubeCli, podInformer.Lister(), @@ -162,7 +164,7 @@ func NewController( scInformer, ), //mm.NewDMClusterStatusManager(kubeCli, cli, scalerInformer.Lister(), tikvGroupInformer.Lister()), - //podRestarter, + podRestarter, &dmClusterConditionUpdater{}, recorder, ), diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go index 3cd6df597f..611e544ac3 100644 --- a/pkg/manager/manager.go +++ b/pkg/manager/manager.go @@ -31,5 +31,5 @@ type TiKVGroupManager interface { type DMManager interface { // Sync implements the logic for syncing dmcluster. - Sync(*v1alpha1.DMCluster) error + SyncDM(*v1alpha1.DMCluster) error } diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 20639953bb..41f8354de5 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -87,7 +87,7 @@ func NewMasterMemberManager(masterControl dmapi.MasterControlInterface, masterUpgrader} } -func (mmm *masterMemberManager) Sync(dc *v1alpha1.DMCluster) error { +func (mmm *masterMemberManager) SyncDM(dc *v1alpha1.DMCluster) error { // Sync dm-master Service if err := mmm.syncMasterServiceForDMCluster(dc); err != nil { return err diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index e5f3d40bec..bb834a9a05 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -76,7 +76,7 @@ func NewWorkerMemberManager(masterControl dmapi.MasterControlInterface, } } -func (wmm *workerMemberManager) Sync(dc *v1alpha1.DMCluster) error { +func (wmm *workerMemberManager) SyncDM(dc *v1alpha1.DMCluster) error { ns := dc.GetNamespace() dcName := dc.GetName() diff --git a/pkg/manager/member/orphan_pods_cleaner.go b/pkg/manager/member/orphan_pods_cleaner.go index 5639b2965e..fabb35e10a 100644 --- a/pkg/manager/member/orphan_pods_cleaner.go +++ b/pkg/manager/member/orphan_pods_cleaner.go @@ -21,6 +21,8 @@ import ( "github.com/pingcap/tidb-operator/pkg/label" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" @@ -49,7 +51,7 @@ const ( // https://github.com/kubernetes/kubernetes/blob/84fe3db5cf58bf0fc8ff792b885465ceaf70a435/pkg/controller/statefulset/stateful_pod_control.go#L175-L199 // type OrphanPodsCleaner interface { - Clean(*v1alpha1.TidbCluster) (map[string]string, error) + Clean(metav1.Object) (map[string]string, error) } type orphanPodsCleaner struct { @@ -67,23 +69,39 @@ func NewOrphanPodsCleaner(podLister corelisters.PodLister, return &orphanPodsCleaner{podLister, podControl, pvcLister, kubeCli} } -func (opc *orphanPodsCleaner) Clean(tc *v1alpha1.TidbCluster) (map[string]string, error) { - ns := tc.GetNamespace() +func (opc *orphanPodsCleaner) Clean(meta metav1.Object) (map[string]string, error) { + ns := meta.GetNamespace() skipReason := map[string]string{} - selector, err := label.New().Instance(tc.GetInstanceName()).Selector() + var ( + selector labels.Selector + err error + podMeta runtime.Object + ) + switch meta.(type) { + case *v1alpha1.TidbCluster: + tc := meta.(*v1alpha1.TidbCluster) + selector, err = label.New().Instance(tc.GetInstanceName()).Selector() + podMeta = tc + case *v1alpha1.DMCluster: + dc := meta.(*v1alpha1.DMCluster) + selector, err = label.NewDM().Instance(dc.GetInstanceName()).Selector() + podMeta = dc + default: + err = fmt.Errorf("orphanPodsCleaner.Clean: unknown meta spec %s", meta) + } if err != nil { return skipReason, err } pods, err := opc.podLister.Pods(ns).List(selector) if err != nil { - return skipReason, fmt.Errorf("clean: failed to get pods list for cluster %s/%s, selector %s, error: %s", ns, tc.GetName(), selector, err) + return skipReason, fmt.Errorf("clean: failed to get pods list for cluster %s/%s, selector %s, error: %s", ns, meta.GetName(), selector, err) } for _, pod := range pods { podName := pod.GetName() l := label.Label(pod.Labels) - if !(l.IsPD() || l.IsTiKV() || l.IsTiFlash()) { + if !(l.IsPD() || l.IsTiKV() || l.IsTiFlash() || l.IsDMMaster() || l.IsDMMaster()) { skipReason[podName] = skipReasonOrphanPodsCleanerIsNotTarget continue } @@ -115,7 +133,7 @@ func (opc *orphanPodsCleaner) Clean(tc *v1alpha1.TidbCluster) (map[string]string continue } if !errors.IsNotFound(err) { - return skipReason, fmt.Errorf("clean: failed to get pvc %s for cluster %s/%s, error: %s", p, ns, tc.GetName(), err) + return skipReason, fmt.Errorf("clean: failed to get pvc %s for cluster %s/%s, error: %s", p, ns, meta.GetName(), err) } // if PVC not found in cache, re-check from apiserver directly to make sure the PVC really not exist _, err = opc.kubeCli.CoreV1().PersistentVolumeClaims(ns).Get(p, metav1.GetOptions{}) @@ -162,7 +180,7 @@ func (opc *orphanPodsCleaner) Clean(tc *v1alpha1.TidbCluster) (map[string]string // As the pod may be updated by kube-scheduler or other components // frequently, we should use the latest object here to avoid API // conflict. - err = opc.podControl.DeletePod(tc, apiPod) + err = opc.podControl.DeletePod(podMeta, apiPod) if err != nil { klog.Errorf("orphan pods cleaner: failed to clean orphan pod: %s/%s, %v", ns, podName, err) return skipReason, err @@ -186,7 +204,7 @@ func (fpc *FakeOrphanPodsCleaner) SetnOrphanPodCleanerError(err error) { fpc.err = err } -func (fpc *FakeOrphanPodsCleaner) Clean(_ *v1alpha1.TidbCluster) (map[string]string, error) { +func (fpc *FakeOrphanPodsCleaner) Clean(_ metav1.Object) (map[string]string, error) { return nil, fpc.err } diff --git a/pkg/manager/member/pod_restarter.go b/pkg/manager/member/pod_restarter.go index 3df04bc04d..d99b7850d1 100644 --- a/pkg/manager/member/pod_restarter.go +++ b/pkg/manager/member/pod_restarter.go @@ -21,12 +21,13 @@ import ( "github.com/pingcap/tidb-operator/pkg/label" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" corelisters "k8s.io/client-go/listers/core/v1" ) type PodRestarter interface { - Sync(tc *v1alpha1.TidbCluster) error + Sync(meta metav1.Object) error } type podRestarter struct { @@ -38,19 +39,32 @@ func NewPodRestarter(kubeCli kubernetes.Interface, podLister corelisters.PodList return &podRestarter{kubeCli: kubeCli, podLister: podLister} } -func (gr *podRestarter) Sync(tc *v1alpha1.TidbCluster) error { - - namespace := tc.Namespace - selector, err := label.New().Instance(tc.Name).Selector() +func (gr *podRestarter) Sync(meta metav1.Object) error { + namespace := meta.GetNamespace() + var ( + selector labels.Selector + err error + metaType string + ) + switch meta.(type) { + case *v1alpha1.TidbCluster: + selector, err = label.New().Instance(meta.GetName()).Selector() + metaType = "tc" + case *v1alpha1.DMCluster: + selector, err = label.NewDM().Instance(meta.GetName()).Selector() + metaType = "dc" + default: + err = fmt.Errorf("podRestarter.Sync: unknown meta spec %s", meta) + } if err != nil { return err } - tcPods, err := gr.podLister.Pods(namespace).List(selector) + metaPods, err := gr.podLister.Pods(namespace).List(selector) if err != nil { - return fmt.Errorf("podRestarter.Sync: failed to get pods list for cluster %s/%s, selector %s, error: %s", namespace, tc.GetName(), selector, err) + return fmt.Errorf("podRestarter.Sync: failed to get pods list for cluster %s/%s, selector %s, error: %s", namespace, meta.GetName(), selector, err) } requeue := false - for _, pod := range tcPods { + for _, pod := range metaPods { if _, existed := pod.Annotations[label.AnnPodDeferDeleting]; existed { requeue = true err = gr.restart(pod) @@ -60,7 +74,7 @@ func (gr *podRestarter) Sync(tc *v1alpha1.TidbCluster) error { } } if requeue { - return controller.RequeueErrorf("tc[%s/%s] is under restarting", namespace, tc.Name) + return controller.RequeueErrorf("%s[%s/%s] is under restarting", metaType, namespace, meta.GetName()) } return nil } @@ -83,6 +97,6 @@ func NewFakePodRestarter() *FakeRestarter { return &FakeRestarter{} } -func (fsr *FakeRestarter) Sync(tc *v1alpha1.TidbCluster) error { +func (fsr *FakeRestarter) Sync(meta metav1.Object) error { return nil } diff --git a/pkg/manager/member/pvc_cleaner.go b/pkg/manager/member/pvc_cleaner.go index a1289bc4ad..bc9b11ee59 100644 --- a/pkg/manager/member/pvc_cleaner.go +++ b/pkg/manager/member/pvc_cleaner.go @@ -22,6 +22,8 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" @@ -45,7 +47,7 @@ const ( // PVCCleaner implements the logic for cleaning the pvc related resource type PVCCleanerInterface interface { - Clean(*v1alpha1.TidbCluster) (map[string]string, error) + Clean(metav1.Object) (map[string]string, error) } type realPVCCleaner struct { @@ -75,33 +77,45 @@ func NewRealPVCCleaner( } } -func (rpc *realPVCCleaner) Clean(tc *v1alpha1.TidbCluster) (map[string]string, error) { - if skipReason, err := rpc.cleanScheduleLock(tc); err != nil { +func (rpc *realPVCCleaner) Clean(meta metav1.Object) (map[string]string, error) { + if skipReason, err := rpc.cleanScheduleLock(meta); err != nil { return skipReason, err } - return rpc.reclaimPV(tc) + return rpc.reclaimPV(meta) } // reclaimPV reclaims PV used by tidb cluster if necessary. -func (rpc *realPVCCleaner) reclaimPV(tc *v1alpha1.TidbCluster) (map[string]string, error) { - if !tc.IsPVReclaimEnabled() { - // PV reclaim is not enabled, return directly. - return nil, nil +func (rpc *realPVCCleaner) reclaimPV(meta metav1.Object) (map[string]string, error) { + var clusterType string + switch meta.(type) { + case *v1alpha1.TidbCluster: + tc := meta.(*v1alpha1.TidbCluster) + if !tc.IsPVReclaimEnabled() { + return nil, nil + } + clusterType = "tidbcluster" + case *v1alpha1.DMCluster: + dc := meta.(*v1alpha1.DMCluster) + if !dc.IsPVReclaimEnabled() { + return nil, nil + } + clusterType = "dmcluster" } - ns := tc.GetNamespace() - tcName := tc.GetName() + ns := meta.GetNamespace() + metaName := meta.GetName() skipReason := map[string]string{} - pvcs, err := rpc.listAllPVCs(tc) + pvcs, err := rpc.listAllPVCs(meta) if err != nil { return skipReason, err } + runtimeMeta := meta.(runtime.Object) for _, pvc := range pvcs { pvcName := pvc.GetName() l := label.Label(pvc.Labels) - if !(l.IsPD() || l.IsTiKV() || l.IsTiFlash()) { + if !(l.IsPD() || l.IsTiKV() || l.IsTiFlash() || l.IsDMMaster() || l.IsDMWorker()) { skipReason[pvcName] = skipReasonPVCCleanerIsNotTarget continue } @@ -139,7 +153,7 @@ func (rpc *realPVCCleaner) reclaimPV(tc *v1alpha1.TidbCluster) (map[string]strin continue } if !errors.IsNotFound(err) { - return skipReason, fmt.Errorf("cluster %s/%s get pvc %s pod %s from local cache failed, err: %v", ns, tcName, pvcName, podName, err) + return skipReason, fmt.Errorf("%s %s/%s get pvc %s pod %s from local cache failed, err: %v", clusterType, ns, metaName, pvcName, podName, err) } // if pod not found in cache, re-check from apiserver directly to make sure the pod really not exist @@ -150,7 +164,7 @@ func (rpc *realPVCCleaner) reclaimPV(tc *v1alpha1.TidbCluster) (map[string]strin continue } if !errors.IsNotFound(err) { - return skipReason, fmt.Errorf("cluster %s/%s get pvc %s pod %s from apiserver failed, err: %v", ns, tcName, pvcName, podName, err) + return skipReason, fmt.Errorf("%s %s/%s get pvc %s pod %s from apiserver failed, err: %v", clusterType, ns, metaName, pvcName, podName, err) } // Without pod reference this defer delete PVC, start to reclaim PV @@ -161,15 +175,15 @@ func (rpc *realPVCCleaner) reclaimPV(tc *v1alpha1.TidbCluster) (map[string]strin skipReason[pvcName] = skipReasonPVCCleanerNotFoundPV continue } - return skipReason, fmt.Errorf("cluster %s/%s get pvc %s pv %s failed, err: %v", ns, tcName, pvcName, pvName, err) + return skipReason, fmt.Errorf("%s %s/%s get pvc %s pv %s failed, err: %v", clusterType, ns, metaName, pvcName, pvName, err) } if pv.Spec.PersistentVolumeReclaimPolicy != corev1.PersistentVolumeReclaimDelete { - err := rpc.pvControl.PatchPVReclaimPolicy(tc, pv, corev1.PersistentVolumeReclaimDelete) + err := rpc.pvControl.PatchPVReclaimPolicy(runtimeMeta, pv, corev1.PersistentVolumeReclaimDelete) if err != nil { - return skipReason, fmt.Errorf("cluster %s/%s patch pv %s to %s failed, err: %v", ns, tcName, pvName, corev1.PersistentVolumeReclaimDelete, err) + return skipReason, fmt.Errorf("%s %s/%s patch pv %s to %s failed, err: %v", clusterType, ns, metaName, pvName, corev1.PersistentVolumeReclaimDelete, err) } - klog.Infof("cluster %s/%s patch pv %s to policy %s success", ns, tcName, pvName, corev1.PersistentVolumeReclaimDelete) + klog.Infof("%s %s/%s patch pv %s to policy %s success", clusterType, ns, metaName, pvName, corev1.PersistentVolumeReclaimDelete) } apiPVC, err := rpc.kubeCli.CoreV1().PersistentVolumeClaims(ns).Get(pvcName, metav1.GetOptions{}) @@ -178,7 +192,7 @@ func (rpc *realPVCCleaner) reclaimPV(tc *v1alpha1.TidbCluster) (map[string]strin skipReason[pvcName] = skipReasonPVCCleanerPVCNotFound continue } - return skipReason, fmt.Errorf("cluster %s/%s get pvc %s failed, err: %v", ns, tcName, pvcName, err) + return skipReason, fmt.Errorf("%s %s/%s get pvc %s failed, err: %v", clusterType, ns, metaName, pvcName, err) } if apiPVC.UID != pvc.UID || apiPVC.ResourceVersion != pvc.ResourceVersion { @@ -186,29 +200,37 @@ func (rpc *realPVCCleaner) reclaimPV(tc *v1alpha1.TidbCluster) (map[string]strin continue } - if err := rpc.pvcControl.DeletePVC(tc, pvc); err != nil { - return skipReason, fmt.Errorf("cluster %s/%s delete pvc %s failed, err: %v", ns, tcName, pvcName, err) + if err := rpc.pvcControl.DeletePVC(runtimeMeta, pvc); err != nil { + return skipReason, fmt.Errorf("%s %s/%s delete pvc %s failed, err: %v", clusterType, ns, metaName, pvcName, err) } - klog.Infof("cluster %s/%s reclaim pv %s success, pvc %s", ns, tcName, pvName, pvcName) + klog.Infof("%s %s/%s reclaim pv %s success, pvc %s", clusterType, ns, metaName, pvName, pvcName) } return skipReason, nil } // cleanScheduleLock cleans AnnPVCPodScheduling label if necessary. -func (rpc *realPVCCleaner) cleanScheduleLock(tc *v1alpha1.TidbCluster) (map[string]string, error) { - ns := tc.GetNamespace() - tcName := tc.GetName() +func (rpc *realPVCCleaner) cleanScheduleLock(meta metav1.Object) (map[string]string, error) { + ns := meta.GetNamespace() + metaName := meta.GetName() skipReason := map[string]string{} - pvcs, err := rpc.listAllPVCs(tc) + var clusterType string + switch meta.(type) { + case *v1alpha1.TidbCluster: + clusterType = "tidbcluster" + case *v1alpha1.DMCluster: + clusterType = "dmcluster" + } + pvcs, err := rpc.listAllPVCs(meta) if err != nil { return skipReason, err } + runtimeMeta := meta.(runtime.Object) for _, pvc := range pvcs { pvcName := pvc.GetName() l := label.Label(pvc.Labels) - if !(l.IsPD() || l.IsTiKV() || l.IsTiFlash()) { + if !(l.IsPD() || l.IsTiKV() || l.IsTiFlash() || l.IsDMMaster() || l.IsDMWorker()) { skipReason[pvcName] = skipReasonPVCCleanerIsNotTarget continue } @@ -216,14 +238,14 @@ func (rpc *realPVCCleaner) cleanScheduleLock(tc *v1alpha1.TidbCluster) (map[stri if pvc.Annotations[label.AnnPVCDeferDeleting] != "" { if _, exist := pvc.Annotations[label.AnnPVCPodScheduling]; !exist { // The defer deleting PVC without pod scheduling annotation, do nothing - klog.V(4).Infof("cluster %s/%s defer delete pvc %s has not pod scheduling annotation, skip clean", ns, tcName, pvcName) + klog.V(4).Infof("%s %s/%s defer delete pvc %s has not pod scheduling annotation, skip clean", clusterType, ns, metaName, pvcName) skipReason[pvcName] = skipReasonPVCCleanerDeferDeletePVCNotHasLock continue } // The defer deleting PVC has pod scheduling annotation, so we need to delete the pod scheduling annotation delete(pvc.Annotations, label.AnnPVCPodScheduling) - if _, err := rpc.pvcControl.UpdatePVC(tc, pvc); err != nil { - return skipReason, fmt.Errorf("cluster %s/%s remove pvc %s pod scheduling annotation faild, err: %v", ns, tcName, pvcName, err) + if _, err := rpc.pvcControl.UpdatePVC(runtimeMeta, pvc); err != nil { + return skipReason, fmt.Errorf("%s %s/%s remove pvc %s pod scheduling annotation faild, err: %v", clusterType, ns, metaName, pvcName, err) } continue } @@ -238,7 +260,7 @@ func (rpc *realPVCCleaner) cleanScheduleLock(tc *v1alpha1.TidbCluster) (map[stri pod, err := rpc.podLister.Pods(ns).Get(podName) if err != nil { if !errors.IsNotFound(err) { - return skipReason, fmt.Errorf("cluster %s/%s get pvc %s pod %s failed, err: %v", ns, tcName, pvcName, podName, err) + return skipReason, fmt.Errorf("%s %s/%s get pvc %s pod %s failed, err: %v", clusterType, ns, metaName, pvcName, podName, err) } skipReason[pvcName] = skipReasonPVCCleanerPodNotFound continue @@ -246,41 +268,54 @@ func (rpc *realPVCCleaner) cleanScheduleLock(tc *v1alpha1.TidbCluster) (map[stri if _, exist := pvc.Annotations[label.AnnPVCPodScheduling]; !exist { // The PVC without pod scheduling annotation, do nothing - klog.V(4).Infof("cluster %s/%s pvc %s has not pod scheduling annotation, skip clean", ns, tcName, pvcName) + klog.V(4).Infof("%s %s/%s pvc %s has not pod scheduling annotation, skip clean", clusterType, ns, metaName, pvcName) skipReason[pvcName] = skipReasonPVCCleanerPVCNotHasLock continue } if pvc.Status.Phase != corev1.ClaimBound || pod.Spec.NodeName == "" { // This pod has not been scheduled yet, no need to clean up the pvc pod schedule annotation - klog.V(4).Infof("cluster %s/%s pod %s has not been scheduled yet, skip clean pvc %s pod schedule annotation", ns, tcName, podName, pvcName) + klog.V(4).Infof("%s %s/%s pod %s has not been scheduled yet, skip clean pvc %s pod schedule annotation", clusterType, ns, metaName, podName, pvcName) skipReason[pvcName] = skipReasonPVCCleanerPodWaitingForScheduling continue } delete(pvc.Annotations, label.AnnPVCPodScheduling) - if _, err := rpc.pvcControl.UpdatePVC(tc, pvc); err != nil { - return skipReason, fmt.Errorf("cluster %s/%s remove pvc %s pod scheduling annotation faild, err: %v", ns, tcName, pvcName, err) + if _, err := rpc.pvcControl.UpdatePVC(runtimeMeta, pvc); err != nil { + return skipReason, fmt.Errorf("%s %s/%s remove pvc %s pod scheduling annotation faild, err: %v", clusterType, ns, metaName, pvcName, err) } - klog.Infof("cluster %s/%s, clean pvc %s pod scheduling annotation successfully", ns, tcName, pvcName) + klog.Infof("%s %s/%s, clean pvc %s pod scheduling annotation successfully", clusterType, ns, metaName, pvcName) } return skipReason, nil } // listAllPVCs lists all PVCs used by the given tidb cluster. -func (rpc *realPVCCleaner) listAllPVCs(tc *v1alpha1.TidbCluster) ([]*corev1.PersistentVolumeClaim, error) { - ns := tc.GetNamespace() - tcName := tc.GetName() - - selector, err := label.New().Instance(tc.GetInstanceName()).Selector() +func (rpc *realPVCCleaner) listAllPVCs(meta metav1.Object) ([]*corev1.PersistentVolumeClaim, error) { + ns := meta.GetNamespace() + metaName := meta.GetName() + + var ( + selector labels.Selector + err error + ) + switch meta.(type) { + case *v1alpha1.TidbCluster: + tc := meta.(*v1alpha1.TidbCluster) + selector, err = label.New().Instance(tc.GetInstanceName()).Selector() + case *v1alpha1.DMCluster: + dc := meta.(*v1alpha1.DMCluster) + selector, err = label.NewDM().Instance(dc.GetInstanceName()).Selector() + default: + err = fmt.Errorf("realPVCCleaner.listAllPVCs: unknown meta spec %s", meta) + } if err != nil { - return nil, fmt.Errorf("cluster %s/%s assemble label selector failed, err: %v", ns, tcName, err) + return nil, fmt.Errorf("cluster %s/%s assemble label selector failed, err: %v", ns, metaName, err) } pvcs, err := rpc.pvcLister.PersistentVolumeClaims(ns).List(selector) if err != nil { - return nil, fmt.Errorf("cluster %s/%s list pvc failed, selector: %s, err: %v", ns, tcName, selector, err) + return nil, fmt.Errorf("cluster %s/%s list pvc failed, selector: %s, err: %v", ns, metaName, selector, err) } return pvcs, nil } @@ -300,7 +335,7 @@ func (fpc *FakePVCCleaner) SetPVCCleanerError(err error) { fpc.err = err } -func (fpc *FakePVCCleaner) Clean(_ *v1alpha1.TidbCluster) (map[string]string, error) { +func (fpc *FakePVCCleaner) Clean(_ metav1.Object) (map[string]string, error) { return nil, fpc.err } diff --git a/pkg/manager/meta/reclaim_policy_manager.go b/pkg/manager/meta/reclaim_policy_manager.go index cf1ca73b72..d0315a99ce 100644 --- a/pkg/manager/meta/reclaim_policy_manager.go +++ b/pkg/manager/meta/reclaim_policy_manager.go @@ -66,6 +66,16 @@ func NewReclaimPolicyTiKVGroupManager(pvcLister corelisters.PersistentVolumeClai } } +func NewReclaimPolicyDMManager(pvcLister corelisters.PersistentVolumeClaimLister, + pvLister corelisters.PersistentVolumeLister, + pvControl controller.PVControlInterface) manager.DMManager { + return &reclaimPolicyManager{ + pvcLister, + pvLister, + pvControl, + } +} + func (rpm *reclaimPolicyManager) Sync(tc *v1alpha1.TidbCluster) error { return rpm.sync(v1alpha1.TiDBClusterKind, tc, tc.IsPVReclaimEnabled(), *tc.Spec.PVReclaimPolicy) } @@ -78,6 +88,10 @@ func (rpm *reclaimPolicyManager) SyncTiKVGroup(tg *v1alpha1.TiKVGroup, tc *v1alp return rpm.sync(v1alpha1.TiKVGroupKind, tg, tc.IsPVReclaimEnabled(), *tc.Spec.PVReclaimPolicy) } +func (rpm *reclaimPolicyManager) SyncDM(dc *v1alpha1.DMCluster) error { + return rpm.sync(v1alpha1.DMClusterKind, dc, dc.IsPVReclaimEnabled(), *dc.Spec.PVReclaimPolicy) +} + func (rpm *reclaimPolicyManager) sync(kind string, obj runtime.Object, isPVReclaimEnabled bool, policy corev1.PersistentVolumeReclaimPolicy) error { var ( meta = obj.(metav1.ObjectMetaAccessor).GetObjectMeta() @@ -94,6 +108,8 @@ func (rpm *reclaimPolicyManager) sync(kind string, obj runtime.Object, isPVRecla selector, err = label.NewMonitor().Instance(instanceName).Monitor().Selector() case v1alpha1.TiKVGroupKind: selector, err = label.NewGroup().Instance(instanceName).TiKV().Selector() + case v1alpha1.DMClusterKind: + selector, err = label.NewDM().Instance(instanceName).Selector() default: return fmt.Errorf("unsupported kind %s", kind) } From bf0db90db6070ad3e627ae469534e1ba09e0d197 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Mon, 31 Aug 2020 10:56:53 +0800 Subject: [PATCH 32/37] let scaling take precedence over upgrading --- examples/dm/dm-cluster.yaml | 4 +-- .../member/dm_master_member_manager.go | 28 +++++++++++++------ pkg/manager/member/dm_master_scaler.go | 7 ----- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/examples/dm/dm-cluster.yaml b/examples/dm/dm-cluster.yaml index 5ccacbe0f2..3b4b0f780c 100644 --- a/examples/dm/dm-cluster.yaml +++ b/examples/dm/dm-cluster.yaml @@ -10,7 +10,7 @@ spec: address: "http://basic-discovery.demo:10261" master: baseImage: pingcap/dm - replicas: 3 + replicas: 1 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage storageSize: "1Gi" @@ -18,7 +18,7 @@ spec: config: {} worker: baseImage: pingcap/dm - replicas: 3 + replicas: 1 # if storageClassName is not set, the default Storage Class of the Kubernetes cluster will be used # storageClassName: local-storage storageSize: "1Gi" diff --git a/pkg/manager/member/dm_master_member_manager.go b/pkg/manager/member/dm_master_member_manager.go index 41f8354de5..d250dcf45d 100644 --- a/pkg/manager/member/dm_master_member_manager.go +++ b/pkg/manager/member/dm_master_member_manager.go @@ -240,17 +240,19 @@ func (mmm *masterMemberManager) syncMasterStatefulSetForDMCluster(dc *v1alpha1.D } } - if !templateEqual(newMasterSet, oldMasterSet) || dc.Status.Master.Phase == v1alpha1.UpgradePhase { - if err := mmm.masterUpgrader.Upgrade(dc, oldMasterSet, newMasterSet); err != nil { - return err - } - } - + // Scaling takes precedence over upgrading because: + // - if a dm-master fails in the upgrading, users may want to delete it or add + // new replicas + // - it's ok to scale in the middle of upgrading (in statefulset controller + // scaling takes precedence over upgrading too) if err := mmm.masterScaler.Scale(dc, oldMasterSet, newMasterSet); err != nil { return err } // TODO: dm add auto failover + // Perform failover logic if necessary. Note that this will only update + // DMCluster status. The actual scaling performs in next sync loop (if a + // new replica needs to be added). // if mmm.autoFailover { // if mmm.shouldRecover(tc) { // mmm.masterFailover.Recover(tc) @@ -261,6 +263,12 @@ func (mmm *masterMemberManager) syncMasterStatefulSetForDMCluster(dc *v1alpha1.D // } // } + if !templateEqual(newMasterSet, oldMasterSet) || dc.Status.Master.Phase == v1alpha1.UpgradePhase { + if err := mmm.masterUpgrader.Upgrade(dc, oldMasterSet, newMasterSet); err != nil { + return err + } + } + return updateStatefulSet(mmm.setControl, dc, newMasterSet, oldMasterSet) } @@ -279,10 +287,12 @@ func (mmm *masterMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set if err != nil { return err } - if upgrading { - dc.Status.Master.Phase = v1alpha1.UpgradePhase - } else if dc.MasterStsDesiredReplicas() != *set.Spec.Replicas { + + // Scaling takes precedence over upgrading. + if dc.MasterStsDesiredReplicas() != *set.Spec.Replicas { dc.Status.Master.Phase = v1alpha1.ScalePhase + } else if upgrading { + dc.Status.Master.Phase = v1alpha1.UpgradePhase } else { dc.Status.Master.Phase = v1alpha1.NormalPhase } diff --git a/pkg/manager/member/dm_master_scaler.go b/pkg/manager/member/dm_master_scaler.go index bb3238e7d5..a8bbd2cafa 100644 --- a/pkg/manager/member/dm_master_scaler.go +++ b/pkg/manager/member/dm_master_scaler.go @@ -69,9 +69,6 @@ func (msd *masterScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, resetReplicas(newSet, oldSet) ns := dc.GetNamespace() dcName := dc.GetName() - if dc.MasterUpgrading() { - return nil - } klog.Infof("scaling out dm-master statefulset %s/%s, ordinal: %d (replicas: %d, delete slots: %v)", oldSet.Namespace, oldSet.Name, ordinal, replicas, deleteSlots.List()) _, err := msd.deleteDeferDeletingPVC(dc, oldSet.GetName(), v1alpha1.DMMasterMemberType, ordinal) @@ -121,10 +118,6 @@ func (msd *masterScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, n memberName := ordinalPodName(v1alpha1.DMMasterMemberType, dcName, ordinal) setName := oldSet.GetName() - if dc.MasterUpgrading() { - return nil - } - if !dc.Status.Master.Synced { return fmt.Errorf("DMCluster: %s/%s's dm-master status sync failed, can't scale in now", ns, dcName) } From f6e5a556383fd36a7c5c20d8f008407cc9335944 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Mon, 31 Aug 2020 11:33:56 +0800 Subject: [PATCH 33/37] fix ut --- pkg/manager/member/pd_scaler_test.go | 2 +- pkg/manager/member/tikv_scaler_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/manager/member/pd_scaler_test.go b/pkg/manager/member/pd_scaler_test.go index ae2a222227..93fe136091 100644 --- a/pkg/manager/member/pd_scaler_test.go +++ b/pkg/manager/member/pd_scaler_test.go @@ -432,7 +432,7 @@ func newFakePDScaler() (*pdScaler, *pdapi.FakePDControl, cache.Indexer, *control pdControl := pdapi.NewFakePDControl(kubeCli) pvcControl := controller.NewFakePVCControl(pvcInformer) - return &pdScaler{generalScaler{pdControl, pvcInformer.Lister(), pvcControl}}, + return &pdScaler{generalScaler{pvcInformer.Lister(), pvcControl}, pdControl}, pdControl, pvcInformer.Informer().GetIndexer(), pvcControl } diff --git a/pkg/manager/member/tikv_scaler_test.go b/pkg/manager/member/tikv_scaler_test.go index 9520fe97af..988c256d97 100644 --- a/pkg/manager/member/tikv_scaler_test.go +++ b/pkg/manager/member/tikv_scaler_test.go @@ -440,7 +440,7 @@ func newFakeTiKVScaler() (*tikvScaler, *pdapi.FakePDControl, cache.Indexer, cach pdControl := pdapi.NewFakePDControl(kubeCli) pvcControl := controller.NewFakePVCControl(pvcInformer) - return &tikvScaler{generalScaler{pdControl, pvcInformer.Lister(), pvcControl}, podInformer.Lister()}, + return &tikvScaler{generalScaler{pvcInformer.Lister(), pvcControl}, pdControl, podInformer.Lister()}, pdControl, pvcInformer.Informer().GetIndexer(), podInformer.Informer().GetIndexer(), pvcControl } From 57803d599407410b699a9a87d9ffd07c286e9f73 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Tue, 1 Sep 2020 17:37:37 +0800 Subject: [PATCH 34/37] address comments --- .../dmcluster/dm_cluster_controller.go | 2 + pkg/dmapi/master_control.go | 3 + pkg/manager/member/dm_master_scaler.go | 36 +---- .../member/dm_worker_member_manager.go | 14 +- pkg/manager/member/dm_worker_scaler.go | 131 ++++++++++++++++++ 5 files changed, 152 insertions(+), 34 deletions(-) create mode 100644 pkg/manager/member/dm_worker_scaler.go diff --git a/pkg/controller/dmcluster/dm_cluster_controller.go b/pkg/controller/dmcluster/dm_cluster_controller.go index 03e0af70b4..0ae4780907 100644 --- a/pkg/controller/dmcluster/dm_cluster_controller.go +++ b/pkg/controller/dmcluster/dm_cluster_controller.go @@ -102,6 +102,7 @@ func NewController( typedControl := controller.NewTypedControl(controller.NewRealGenericControl(genericCli, recorder)) masterScaler := mm.NewMasterScaler(masterControl, pvcInformer.Lister(), pvcControl) masterUpgrader := mm.NewMasterUpgrader(masterControl, podInformer.Lister()) + workerScaler := mm.NewWorkerScaler(pvcInformer.Lister(), pvcControl) podRestarter := mm.NewPodRestarter(kubeCli, podInformer.Lister()) dcc := &Controller{ @@ -130,6 +131,7 @@ func NewController( setInformer.Lister(), svcInformer.Lister(), podInformer.Lister(), + workerScaler, ), meta.NewReclaimPolicyDMManager( pvcInformer.Lister(), diff --git a/pkg/dmapi/master_control.go b/pkg/dmapi/master_control.go index a31fb1a5d0..a3b8ebb6b8 100644 --- a/pkg/dmapi/master_control.go +++ b/pkg/dmapi/master_control.go @@ -93,14 +93,17 @@ func (mc *defaultMasterControl) GetMasterPeerClient(namespace string, dcName str return NewMasterClient(MasterPeerClientURL(namespace, dcName, podName, scheme), DefaultTimeout, tlsConfig, true) } +// masterClientKey returns the master client key func masterClientKey(scheme, namespace, clusterName string) string { return fmt.Sprintf("%s.%s.%s", scheme, clusterName, namespace) } +// MasterClientURL builds the url of master client func MasterClientURL(namespace, clusterName, scheme string) string { return fmt.Sprintf("%s://%s-dm-master.%s:8261", scheme, clusterName, namespace) } +// MasterClientURL builds the url of master peer client. It's used to evict leader because dm can't forward evict leader command now func MasterPeerClientURL(namespace, clusterName, podName, scheme string) string { return fmt.Sprintf("%s://%s.%s-dm-master-peer.%s:8261", scheme, podName, clusterName, namespace) } diff --git a/pkg/manager/member/dm_master_scaler.go b/pkg/manager/member/dm_master_scaler.go index a8bbd2cafa..a371c88088 100644 --- a/pkg/manager/member/dm_master_scaler.go +++ b/pkg/manager/member/dm_master_scaler.go @@ -17,16 +17,13 @@ import ( "fmt" "time" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/pingcap/tidb-operator/pkg/label" - - "github.com/pingcap/advanced-statefulset/client/apis/apps/v1/helper" - "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/controller" "github.com/pingcap/tidb-operator/pkg/dmapi" + "github.com/pingcap/tidb-operator/pkg/label" + apps "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" ) @@ -80,25 +77,6 @@ func (msd *masterScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, return fmt.Errorf("DMCluster: %s/%s's dm-master status sync failed, can't scale out now", ns, dcName) } - if len(dc.Status.Master.FailureMembers) != 0 { - setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) - return nil - } - - healthCount := 0 - totalCount := *oldSet.Spec.Replicas - podOrdinals := helper.GetPodOrdinals(*oldSet.Spec.Replicas, oldSet).List() - for _, i := range podOrdinals { - podName := ordinalPodName(v1alpha1.DMMasterMemberType, dcName, i) - if member, ok := dc.Status.Master.Members[podName]; ok && member.Health { - healthCount++ - } - } - if healthCount < int(totalCount) { - return fmt.Errorf("DMCluster: %s/%s's dm-master %d/%d is ready, can't scale out now", - ns, dcName, healthCount, totalCount) - } - setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) return nil } @@ -124,10 +102,10 @@ func (msd *masterScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, n klog.Infof("scaling in dm-master statefulset %s/%s, ordinal: %d (replicas: %d, delete slots: %v)", oldSet.Namespace, oldSet.Name, ordinal, replicas, deleteSlots.List()) - if controller.PodWebhookEnabled { - setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) - return nil - } + //if controller.PodWebhookEnabled { + // setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + // return nil + //} // If the dm-master pod was dm-master leader during scale-in, we would evict dm-master leader first // If the dm-master statefulSet would be scale-in to zero and the dm-master-0 was going to be deleted, diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index bb834a9a05..89650aac29 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -53,6 +53,7 @@ type workerMemberManager struct { setLister v1.StatefulSetLister svcLister corelisters.ServiceLister podLister corelisters.PodLister + workerScaler Scaler } // NewWorkerMemberManager returns a *ticdcMemberManager @@ -63,7 +64,8 @@ func NewWorkerMemberManager(masterControl dmapi.MasterControlInterface, typedControl controller.TypedControlInterface, setLister v1.StatefulSetLister, svcLister corelisters.ServiceLister, - podLister corelisters.PodLister) manager.DMManager { + podLister corelisters.PodLister, + workerScaler Scaler) manager.DMManager { return &workerMemberManager{ masterControl, setControl, @@ -73,6 +75,7 @@ func NewWorkerMemberManager(masterControl dmapi.MasterControlInterface, setLister, svcLister, podLister, + workerScaler, } } @@ -211,6 +214,10 @@ func (wmm *workerMemberManager) syncWorkerStatefulSetForDMCluster(dc *v1alpha1.D return nil } + if err := wmm.workerScaler.Scale(dc, oldSts, newSts); err != nil { + return err + } + return updateStatefulSet(wmm.setControl, dc, newSts, oldSts) } @@ -489,10 +496,7 @@ func getNewWorkerSetForDMCluster(dc *v1alpha1.DMCluster, cm *corev1.ConfigMap) ( ServiceName: controller.DMWorkerPeerMemberName(dcName), PodManagementPolicy: apps.ParallelPodManagement, UpdateStrategy: apps.StatefulSetUpdateStrategy{ - Type: apps.RollingUpdateStatefulSetStrategyType, - RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{ - Partition: pointer.Int32Ptr(dc.WorkerStsDesiredReplicas()), - }}, + Type: apps.RollingUpdateStatefulSetStrategyType}, }, } diff --git a/pkg/manager/member/dm_worker_scaler.go b/pkg/manager/member/dm_worker_scaler.go new file mode 100644 index 0000000000..af2043dde6 --- /dev/null +++ b/pkg/manager/member/dm_worker_scaler.go @@ -0,0 +1,131 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package member + +import ( + "fmt" + "time" + + "github.com/pingcap/tidb-operator/pkg/label" + + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + apps "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/klog" +) + +type workerScaler struct { + generalScaler +} + +// NewWorkerScaler returns a DMScaler +func NewWorkerScaler(pvcLister corelisters.PersistentVolumeClaimLister, + pvcControl controller.PVCControlInterface) Scaler { + return &workerScaler{ + generalScaler: generalScaler{ + pvcLister: pvcLister, + pvcControl: pvcControl, + }, + } +} + +func (wsd *workerScaler) Scale(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + scaling, _, _, _ := scaleOne(oldSet, newSet) + if scaling > 0 { + return wsd.ScaleOut(meta, oldSet, newSet) + } else if scaling < 0 { + return wsd.ScaleIn(meta, oldSet, newSet) + } + return wsd.SyncAutoScalerAnn(meta, oldSet) +} + +func (wsd *workerScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + dc, ok := meta.(*v1alpha1.DMCluster) + if !ok { + return nil + } + + _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) + resetReplicas(newSet, oldSet) + ns := dc.GetNamespace() + dcName := dc.GetName() + + klog.Infof("scaling out dm-worker statefulset %s/%s, ordinal: %d (replicas: %d, delete slots: %v)", oldSet.Namespace, oldSet.Name, ordinal, replicas, deleteSlots.List()) + _, err := wsd.deleteDeferDeletingPVC(dc, oldSet.GetName(), v1alpha1.DMWorkerMemberType, ordinal) + if err != nil { + return err + } + + if !dc.Status.Worker.Synced { + return fmt.Errorf("DMCluster: %s/%s's dm-worker status sync failed, can't scale out now", ns, dcName) + } + + setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + return nil +} + +// We need remove member from cluster before reducing statefulset replicas +// only remove one member at a time when scale down +func (wsd *workerScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { + dc, ok := meta.(*v1alpha1.DMCluster) + if !ok { + return nil + } + ns := dc.GetNamespace() + dcName := dc.GetName() + _, ordinal, replicas, deleteSlots := scaleOne(oldSet, newSet) + resetReplicas(newSet, oldSet) + setName := oldSet.GetName() + + if !dc.Status.Worker.Synced { + return fmt.Errorf("DMCluster: %s/%s's dm-worker status sync failed, can't scale in now", ns, dcName) + } + + klog.Infof("scaling in dm-worker statefulset %s/%s, ordinal: %d (replicas: %d, delete slots: %v)", oldSet.Namespace, oldSet.Name, ordinal, replicas, deleteSlots.List()) + + //if controller.PodWebhookEnabled { + // setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + // return nil + //} + + pvcName := ordinalPVCName(v1alpha1.DMWorkerMemberType, setName, ordinal) + pvc, err := wsd.pvcLister.PersistentVolumeClaims(ns).Get(pvcName) + if err != nil { + return fmt.Errorf("dm-worker.ScaleIn: failed to get pvc %s for cluster %s/%s, error: %s", pvcName, ns, dcName, err) + } + + if pvc.Annotations == nil { + pvc.Annotations = map[string]string{} + } + now := time.Now().Format(time.RFC3339) + pvc.Annotations[label.AnnPVCDeferDeleting] = now + + _, err = wsd.pvcControl.UpdatePVC(dc, pvc) + if err != nil { + klog.Errorf("dm-worker scale in: failed to set pvc %s/%s annotation: %s to %s", + ns, pvcName, label.AnnPVCDeferDeleting, now) + return err + } + klog.Infof("dm-worker scale in: set pvc %s/%s annotation: %s to %s", + ns, pvcName, label.AnnPVCDeferDeleting, now) + + setReplicasAndDeleteSlots(newSet, replicas, deleteSlots) + return nil +} + +func (wsd *workerScaler) SyncAutoScalerAnn(meta metav1.Object, oldSet *apps.StatefulSet) error { + return nil +} From 4b2deec920043e4986eb597ede021602f5c51cba Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 2 Sep 2020 14:44:02 +0800 Subject: [PATCH 35/37] address comment --- pkg/manager/member/dm_worker_scaler.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/manager/member/dm_worker_scaler.go b/pkg/manager/member/dm_worker_scaler.go index af2043dde6..3fa3dda3c2 100644 --- a/pkg/manager/member/dm_worker_scaler.go +++ b/pkg/manager/member/dm_worker_scaler.go @@ -77,7 +77,10 @@ func (wsd *workerScaler) ScaleOut(meta metav1.Object, oldSet *apps.StatefulSet, return nil } -// We need remove member from cluster before reducing statefulset replicas +// Different from dm-master, we need remove member from cluster **after** reducing statefulset replicas +// Now it will be removed in syncing worker status. For dm-worker we can't remove its register info from dm-master +// when it's still alive. So we delete it later after its keepalive lease is outdated or revoked. +// We can defer deleting dm-worker register info because dm-master will patch replication task through keepalive info. // only remove one member at a time when scale down func (wsd *workerScaler) ScaleIn(meta metav1.Object, oldSet *apps.StatefulSet, newSet *apps.StatefulSet) error { dc, ok := meta.(*v1alpha1.DMCluster) From 979fd98649ef4d2624655542f5b4f53790346712 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 2 Sep 2020 14:58:15 +0800 Subject: [PATCH 36/37] address comment --- pkg/apis/pingcap/v1alpha1/dmcluster.go | 43 +++++++++++++++++++ .../member/dm_worker_member_manager.go | 15 +++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/pkg/apis/pingcap/v1alpha1/dmcluster.go b/pkg/apis/pingcap/v1alpha1/dmcluster.go index 909379c11c..3ae9f58aa8 100644 --- a/pkg/apis/pingcap/v1alpha1/dmcluster.go +++ b/pkg/apis/pingcap/v1alpha1/dmcluster.go @@ -14,8 +14,13 @@ package v1alpha1 import ( + "encoding/json" "fmt" "strings" + + "github.com/pingcap/advanced-statefulset/client/apis/apps/v1/helper" + "github.com/pingcap/tidb-operator/pkg/label" + "k8s.io/apimachinery/pkg/util/sets" ) func (dc *DMCluster) Scheme() string { @@ -92,6 +97,17 @@ func (dc *DMCluster) WorkerStsDesiredReplicas() int32 { return dc.Spec.Worker.Replicas } +func (dc *DMCluster) WorkerStsDesiredOrdinals(excludeFailover bool) sets.Int32 { + if dc.Spec.Worker == nil { + return sets.Int32{} + } + replicas := dc.Spec.Worker.Replicas + if !excludeFailover { + replicas = dc.WorkerStsDesiredReplicas() + } + return helper.GetPodOrdinalsFromReplicasAndDeleteSlots(replicas, dc.getDeleteSlots(label.DMWorkerLabelVal)) +} + func (dc *DMCluster) GetInstanceName() string { return dc.Name } @@ -138,6 +154,33 @@ func (dc *DMCluster) MasterScaling() bool { return dc.Status.Master.Phase == ScalePhase } +func (dc *DMCluster) getDeleteSlots(component string) (deleteSlots sets.Int32) { + deleteSlots = sets.NewInt32() + annotations := dc.GetAnnotations() + if annotations == nil { + return deleteSlots + } + var key string + if component == label.DMMasterLabelVal { + key = label.AnnDMMasterDeleteSlots + } else if component == label.DMWorkerLabelVal { + key = label.AnnDMWorkerDeleteSlots + } else { + return + } + value, ok := annotations[key] + if !ok { + return + } + var slice []int32 + err := json.Unmarshal([]byte(value), &slice) + if err != nil { + return + } + deleteSlots.Insert(slice...) + return +} + func (dc *DMCluster) MasterIsAvailable() bool { lowerLimit := dc.Spec.Master.Replicas/2 + 1 if int32(len(dc.Status.Master.Members)) < lowerLimit { diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index 89650aac29..944fbc2c90 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -269,10 +269,7 @@ func (wmm *workerMemberManager) syncDMClusterStatus(dc *v1alpha1.DMCluster, set // offline the workers that already been scaled-in if status.Stage == "offline" { - ordinal, err := util.GetOrdinalFromPodName(worker.Name) - if err != nil { - klog.Errorf("invalid worker name %s, can't offline this worker automatically, err: %s", worker.Name, err) - } else if ordinal >= dc.WorkerStsDesiredReplicas() { + if !isWorkerPodDesired(dc, name) { err := dmClient.DeleteWorker(name) if err != nil { klog.Errorf("fail to remove worker %s, err: %s", worker.Name, err) @@ -549,3 +546,13 @@ func getWorkerConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { } return cm, nil } + +func isWorkerPodDesired(dc *v1alpha1.DMCluster, podName string) bool { + ordinals := dc.WorkerStsDesiredOrdinals(true) + ordinal, err := util.GetOrdinalFromPodName(podName) + if err != nil { + klog.Errorf("unexpected pod name %q: %v", podName, err) + return false + } + return ordinals.Has(ordinal) +} From ead903fc8a9cc14b4d422b5d3641864ed8fcd319 Mon Sep 17 00:00:00 2001 From: Chunzhu Li Date: Wed, 2 Sep 2020 15:19:46 +0800 Subject: [PATCH 37/37] address comment --- pkg/manager/member/dm_worker_member_manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/manager/member/dm_worker_member_manager.go b/pkg/manager/member/dm_worker_member_manager.go index 944fbc2c90..61c09f8354 100644 --- a/pkg/manager/member/dm_worker_member_manager.go +++ b/pkg/manager/member/dm_worker_member_manager.go @@ -548,7 +548,7 @@ func getWorkerConfigMap(dc *v1alpha1.DMCluster) (*corev1.ConfigMap, error) { } func isWorkerPodDesired(dc *v1alpha1.DMCluster, podName string) bool { - ordinals := dc.WorkerStsDesiredOrdinals(true) + ordinals := dc.WorkerStsDesiredOrdinals(false) ordinal, err := util.GetOrdinalFromPodName(podName) if err != nil { klog.Errorf("unexpected pod name %q: %v", podName, err)