+
+spec
+
+
+TidbClusterSpec
+
+
+ |
+
+ Spec defines the behavior of a tidb cluster
+
+
+
+
+
+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
|
@@ -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
-
-
-
-
-Field |
-Description |
-
-
-
-
-
-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
-
-
-
-
-Field |
-Description |
-
-
-
-
-
-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)
-
-
-
-
-
-
-Field |
-Description |
-
-
-
-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
-
-
-
-
-
-Field |
-Description |
-
-
-
-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
-
-
- |
-
- |
+Field |
+Description |
+
+
-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
-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
+
+
+
+
+
+Field |
+Description |
+
+
+
-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)
+
+
+
+
+
+
+Field |
+Description |
+
+
+
-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
|
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
(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.
|
@@ -8147,7 +8147,7 @@ string
(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.
|
@@ -18574,7 +18574,7 @@ int64
(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
|
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
+
+(Members of ServiceSpec are embedded into this type.)
+
|
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
+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
|
@@ -4163,6 +4189,10 @@ string
|
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.
|
+
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)
|