From cecd6766ad63cf8757ab758ce1f0d019e0211015 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Sat, 4 Nov 2023 10:16:51 +0100 Subject: [PATCH 01/32] Implement queries_exec. --- chetan.yaml | 129 ++++++++++++ go.mod | 1 + go.sum | 2 + pkg/pxc/queries/queries_exec.go | 346 ++++++++++++++++++++++++++++++++ 4 files changed, 478 insertions(+) create mode 100644 chetan.yaml create mode 100644 pkg/pxc/queries/queries_exec.go diff --git a/chetan.yaml b/chetan.yaml new file mode 100644 index 0000000000..e99b8a367d --- /dev/null +++ b/chetan.yaml @@ -0,0 +1,129 @@ +apiVersion: pxc.percona.com/v1 +kind: PerconaXtraDBCluster +metadata: + name: cluster1 + finalizers: +# - delete-ssl +# - delete-proxysql-pvc +# - delete-pxc-pvc +# annotations: +# percona.com/issue-vault-token: "true" +spec: + allowUnsafeConfigurations: true + backup: + image: percona/percona-xtradb-cluster-operator:1.13.0-pxc8.0-backup-pxb8.0.32 + pitr: + enabled: false + resources: {} + storageName: "" + crVersion: 1.13.0 + haproxy: + affinity: + antiAffinityTopologyKey: none + configuration: | + timeout client 28800s + timeout connect 100500 + timeout server 28800s + enabled: true + image: percona/percona-xtradb-cluster-operator:1.13.0-haproxy + livenessProbes: {} + loadBalancerSourceRanges: + - 185.211.160.62/31 + - 35.158.96.9/31 + readinessProbes: {} + replicasServiceType: LoadBalancer + resources: + limits: + cpu: 600m + memory: 1G + serviceType: LoadBalancer + sidecarResources: {} + size: 1 + serviceAnnotations: + percona.com/inel: test + pmm: + enabled: false + image: percona/pmm-client:2 + resources: {} + serverHost: 3.73.128.178 + proxysql: + affinity: + antiAffinityTopologyKey: kubernetes.io/hostname + livenessProbes: {} + readinessProbes: {} + resources: {} + sidecarResources: {} + pxc: + affinity: + antiAffinityTopologyKey: kubernetes.io/hostname + configuration: |- + [mysqld] + binlog_cache_size = 131072 + binlog_expire_logs_seconds = 604800 + binlog_format = ROW + binlog_stmt_cache_size = 131072 + innodb_adaptive_hash_index = True + innodb_buffer_pool_chunk_size = 2097152 + innodb_buffer_pool_instances = 6 + innodb_buffer_pool_size = 11619903457 + innodb_ddl_threads = 2 + innodb_flush_log_at_trx_commit = 2 + innodb_flush_method = O_DIRECT + innodb_io_capacity_max = 1800 + innodb_log_file_size = 464124928 + innodb_log_files_in_group = 8 + innodb_monitor_enable = ALL + innodb_page_cleaners = 6 + innodb_parallel_read_threads = 3 + innodb_purge_threads = 4 + join_buffer_size = 524288 + max_connections = 502 + max_heap_table_size = 16777216 + read_rnd_buffer_size = 393216 + replica_compressed_protocol = 1 + replica_exec_mode = STRICT + replica_parallel_type = LOGICAL_CLOCK + replica_parallel_workers = 4 + replica_preserve_commit_order = ON + sort_buffer_size = 524288 + sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,TRADITIONAL,STRICT_ALL_TABLES' + sync_binlog = 1 + table_definition_cache = 4096 + table_open_cache = 4096 + table_open_cache_instances = 4 + tablespace_definition_cache = 512 + thread_cache_size = 18 + thread_pool_size = 6 + thread_stack = 1048576 + tmp_table_size = 16777216 + wsrep-provider-options = evs.join_retrans_period=PT4S;evs.suspect_timeout=PT54S;gmcast.peer_timeout=PT13S;evs.send_window=921;evs.user_send_window=921;pc.announce_timeout=PT54S;gcache.recover=yes;evs.delayed_keep_period=PT554S;evs.inactive_check_period=PT4S;evs.inactive_timeout=PT108S;evs.stats_report_period=PT1M;gcs.fc_limit=115;gmcast.time_wait=PT16S;pc.linger=PT54S;pc.recovery=true;evs.delay_margin=PT27S;evs.max_install_timeouts=4;gcache.size=4269949337;gcs.max_packet_size=117964; + wsrep_slave_threads = 1 + wsrep_sync_wait = 3 + wsrep_trx_fragment_size = 1048576 + wsrep_trx_fragment_unit = bytes + pxc_strict_mode=PERMISSIVE + secure_file_priv ='' + expose: {} + image: percona/percona-xtradb-cluster:8.0.32-24.2 + livenessProbes: {} + podDisruptionBudget: + maxUnavailable: 1 + readinessProbes: {} + resources: + limits: + cpu: "4" + memory: 16G + serviceType: ClusterIP + sidecarResources: {} + size: 3 + volumeSpec: + persistentVolumeClaim: + resources: + requests: + storage: 100G + storageClassName: io1-csi + secretsName: everest-secrets-steve-test1 + updateStrategy: SmartUpdate + upgradeOptions: + apply: never + schedule: 0 4 * * * diff --git a/go.mod b/go.mod index da3dc6456a..f1bf7ed5f8 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/go-openapi/swag v0.22.4 github.com/go-openapi/validate v0.22.1 github.com/go-sql-driver/mysql v1.7.1 + github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/google/go-cmp v0.5.9 github.com/hashicorp/go-version v1.6.0 github.com/minio/minio-go/v7 v7.0.59 diff --git a/go.sum b/go.sum index 34f2438aaf..dc61d0be85 100644 --- a/go.sum +++ b/go.sum @@ -123,6 +123,8 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d h1:KbPOUXFUDJxwZ04vbmDOc3yuruGvVO+LOa7cVER3yWw= +github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go new file mode 100644 index 0000000000..c1e0dfa082 --- /dev/null +++ b/pkg/pxc/queries/queries_exec.go @@ -0,0 +1,346 @@ +package queries + +import ( + "bytes" + "context" + "database/sql" + "encoding/csv" + "fmt" + "regexp" + "strings" + + "github.com/pkg/errors" + + "github.com/gocarina/gocsv" + corev1 "k8s.io/api/core/v1" + + "github.com/percona/percona-xtradb-cluster-operator/clientcmd" +) + +var sensitiveRegexp = regexp.MustCompile(":.*@") + +type DatabaseExec struct { + client clientcmd.Client + pod *corev1.Pod + user string + pass string + host string +} + +func NewExec(pod *corev1.Pod, cliCmd clientcmd.Client, user, pass, host string) *DatabaseExec { + return &DatabaseExec{client: cliCmd, pod: pod, user: user, pass: pass, host: host} +} + +func (d *DatabaseExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} + + err := d.client.Exec(d.pod, "mysql", cmd, nil, stdout, stderr, false) + if err != nil { + sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") + serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") + return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) + } + + if strings.Contains(stderr.String(), "ERROR") { + return fmt.Errorf("sql error: %s", stderr) + } + + return nil +} + +func (d *DatabaseExec) query(ctx context.Context, query string, out interface{}) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, query, &outb, &errb) + if err != nil { + return err + } + + if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { + return sql.ErrNoRows + } + + csv := csv.NewReader(bytes.NewReader(outb.Bytes())) + csv.Comma = '\t' + + if err = gocsv.UnmarshalCSV(csv, out); err != nil { + return err + } + + return nil +} + +func (p *DatabaseExec) CurrentReplicationChannelsExec(ctx context.Context) ([]string, error) { + rows := []*struct { + name string `csv:"name"` + }{} + + q := `SELECT DISTINCT(Channel_name) as name from replication_asynchronous_connection_failover` + err := p.query(ctx, q, &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + return nil, errors.Wrap(err, "select current replication channels") + } + + result := make([]string, 0) + for _, row := range rows { + result = append(result, row.name) + } + return result, nil +} + +func (p *DatabaseExec) ChangeChannelPasswordExec(ctx context.Context, channel, password string) error { + var errb, outb bytes.Buffer + + q := fmt.Sprintf(`START TRANSACTION; + STOP REPLICA IO_THREAD FOR CHANNEL %s; + CHANGE REPLICATION SOURCE TO SOURCE_PASSWORD='%s' FOR CHANNEL %s; + START REPLICA IO_THREAD FOR CHANNEL %s; + COMMIT; + `, channel, password, channel, channel) + + err := p.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "change channel password") + } + + return nil +} + +// channel name moze biti: group_replication_applier ili SHOW REPLICA STATUS FOR CHANNEL group_replication_recovery +func (p *DatabaseExec) ReplicationStatusExec(channel string) (ReplicationStatus, error) { + panic("not implemented") +} + +func (p *DatabaseExec) StopAllReplicationExec(ctx context.Context) error { + var errb, outb bytes.Buffer + if err := p.exec(ctx, "STOP REPLICA", &outb, &errb); err != nil { + return errors.Wrap(err, "failed to stop replication") + } + return nil +} + +func (p *DatabaseExec) AddReplicationSourceExec(ctx context.Context, name, host string, port, weight int) error { + var errb, outb bytes.Buffer + q := fmt.Sprintf("SELECT asynchronous_connection_failover_add_source('%s', '%s', %d, null, %d)", name, host, port, weight) + err := p.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "add replication source") + } + return nil +} + +func (p *DatabaseExec) ReplicationChannelSourcesExec(ctx context.Context, channelName string) ([]ReplicationChannelSource, error) { + rows := []*struct { + host string `csv:"host"` + port int `csv:"port"` + wieght int `csv:"weight"` + }{} + + q := fmt.Sprintf("SELECT host, port, weight FROM replication_asynchronous_connection_failover WHERE Channel_name = '%s'", channelName) + err := p.query(ctx, q, &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, ErrNotFound + } + return nil, errors.Wrap(err, "get replication channels") + } + + result := make([]ReplicationChannelSource, 0) + for _, row := range rows { + result = append(result, ReplicationChannelSource{Host: row.host, Port: row.port, Weight: row.wieght}) + } + return result, nil +} + +func (p *DatabaseExec) StopReplicationExec(ctx context.Context, name string) error { + var errb, outb bytes.Buffer + err := p.exec(ctx, fmt.Sprintf("STOP REPLICA FOR CHANNEL '%s'", name), &outb, &errb) + return errors.Wrap(err, "stop replication for channel "+name) +} + +func (p *DatabaseExec) EnableReadonlyExec(ctx context.Context) error { + var errb, outb bytes.Buffer + err := p.exec(ctx, "SET GLOBAL READ_ONLY=1", &outb, &errb) + return errors.Wrap(err, "set global read_only param to 1") +} + +func (p *DatabaseExec) DisableReadonlyExec(ctx context.Context) error { + var errb, outb bytes.Buffer + err := p.exec(ctx, "SET GLOBAL READ_ONLY=0", &outb, &errb) + return errors.Wrap(err, "set global read_only param to 0") +} + +func (p *DatabaseExec) IsReadonlyExec(ctx context.Context) (bool, error) { + rows := []*struct { + ro int `csv:"ro"` + }{} + err := p.query(ctx, "select @@read_only as ro", &rows) + return rows[0].ro == 1, errors.Wrap(err, "select global read_only param") +} + +func (p *DatabaseExec) StartReplicationExec(ctx context.Context, replicaPass string, config ReplicationConfig) error { + var ca string + var ssl int + if config.SSL { + ssl = 1 + ca = config.CA + } + + var sslVerify int + if !config.SSLSkipVerify { + sslVerify = 1 + } + + q := fmt.Sprintf(` + CHANGE REPLICATION SOURCE TO + SOURCE_USER='replication', + SOURCE_PASSWORD='%s', + SOURCE_HOST='%s', + SOURCE_PORT=%d, + SOURCE_CONNECTION_AUTO_FAILOVER=1, + SOURCE_AUTO_POSITION=1, + SOURCE_RETRY_COUNT=%d, + SOURCE_CONNECT_RETRY=%d, + SOURCE_SSL=%d, + SOURCE_SSL_CA='%s', + SOURCE_SSL_VERIFY_SERVER_CERT=%d + FOR CHANNEL '%s' + `, replicaPass, config.Source.Host, config.Source.Port, config.SourceRetryCount, config.SourceConnectRetry, ssl, ca, sslVerify, config.Source.Name) + + var errb, outb bytes.Buffer + err := p.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrapf(err, "change source for channel %s", config.Source.Name) + } + + outb.Reset() + errb.Reset() + err = p.exec(ctx, fmt.Sprintf(`START REPLICA FOR CHANNEL '%s'`, config.Source.Name), &outb, &errb) + return errors.Wrapf(err, "start replica for source %s", config.Source.Name) + +} + +func (p *DatabaseExec) DeleteReplicationSourceExec(ctx context.Context, name, host string, port int) error { + var errb, outb bytes.Buffer + q := fmt.Sprintf("SELECT asynchronous_connection_failover_delete_source('%s', '%s', %d, null)", name, host, port) + err := p.exec(ctx, q, &outb, &errb) + return errors.Wrap(err, "delete replication source "+name) +} + +func (p *DatabaseExec) ProxySQLInstanceStatusExec(ctx context.Context, host string) ([]string, error) { + + rows := []*struct { + status string `csv:"status"` + }{} + + q := fmt.Sprintf("SELECT status FROM proxysql_servers WHERE hostname LIKE '%s%%'", host) + + err := p.query(ctx, q, &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, ErrNotFound + } + return nil, err + } + + statuses := []string{} + for _, row := range rows { + statuses = append(statuses, row.status) + } + + return statuses, nil +} + +func (p *DatabaseExec) PresentInHostgroupsExec(ctx context.Context, host string) (bool, error) { + hostgroups := []string{WriterHostgroup, ReaderHostgroup} + + rows := []*struct { + count int `csv:"count"` + }{} + + q := fmt.Sprintf(` + SELECT COUNT(*) FROM mysql_servers + INNER JOIN mysql_galera_hostgroups ON hostgroup_id IN (%s) + WHERE hostname LIKE '%s' GROUP BY hostname`, strings.Join(hostgroups, ","), host+"%") + + err := p.query(ctx, q, &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return false, ErrNotFound + } + return false, err + } + if rows[0].count != len(hostgroups) { + return false, nil + } + return true, nil +} + +func (p *DatabaseExec) PrimaryHostExec(ctx context.Context) (string, error) { + rows := []*struct { + hostname string `csv:"host"` + }{} + + q := fmt.Sprintf("SELECT hostname FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) + + err := p.query(ctx, q, &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return "", ErrNotFound + } + return "", err + } + + return rows[0].hostname, nil +} + +func (p *DatabaseExec) HostnameExec(ctx context.Context) (string, error) { + rows := []*struct { + hostname string `csv:"hostname"` + }{} + + err := p.query(ctx, "SELECT @@hostname hostname", &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return "", ErrNotFound + } + return "", err + } + + return rows[0].hostname, nil +} + +func (p *DatabaseExec) WsrepLocalStateCommentExec(ctx context.Context) (string, error) { + rows := []*struct { + variable_name string `csv:"Variable_name"` + value string `csv:"Value"` + }{} + + err := p.query(ctx, "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'", &rows) + if err != nil { + if err == sql.ErrNoRows { + return "", fmt.Errorf("variable was not found") + } + return "", err + } + + return rows[0].value, nil +} + +func (p *DatabaseExec) VersionExecExec(ctx context.Context) (string, error) { + rows := []*struct { + version string `csv:"version"` + }{} + + err := p.query(ctx, "select @@VERSION;", &rows) + if err != nil { + if err == sql.ErrNoRows { + return "", fmt.Errorf("variable was not found") + } + return "", err + } + + return rows[0].version, nil +} From 3752d485bcc5dbb1d20a65b6af7b49e02671d880 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 7 Nov 2023 10:30:06 +0100 Subject: [PATCH 02/32] Add OPERATOR_IMAGE env var. --- cmd/manager/main.go | 15 ++++++++------- deploy/cr.yaml | 4 ++-- pkg/k8s/utils.go | 10 +++++++++- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 45b8524c38..0e63f6d826 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -84,13 +84,14 @@ func main() { } options := ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "08db1feb.percona.com", - Namespace: namespace, + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "08db1feb.percona.com", + LeaderElectionNamespace: operatorNamespace, + Namespace: namespace, } // Add support for MultiNamespace set in WATCH_NAMESPACE diff --git a/deploy/cr.yaml b/deploy/cr.yaml index b4e75b0b4b..87812aeeee 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -20,8 +20,8 @@ spec: # sslSecretName: cluster1-ssl # sslInternalSecretName: cluster1-ssl-internal # logCollectorSecretName: cluster1-log-collector-secrets -# initContainer: -# image: perconalab/percona-xtradb-cluster-operator:main + initContainer: + image: perconalab/percona-xtradb-cluster-operator:main # resources: # requests: # memory: 100M diff --git a/pkg/k8s/utils.go b/pkg/k8s/utils.go index a6555135ba..e3393e985a 100644 --- a/pkg/k8s/utils.go +++ b/pkg/k8s/utils.go @@ -6,7 +6,10 @@ import ( "strings" ) -const WatchNamespaceEnvVar = "WATCH_NAMESPACE" +const ( + WatchNamespaceEnvVar = "WATCH_NAMESPACE" + OperatorNamespaceEnbVar = "OPERATOR_NAMESPACE" +) // GetWatchNamespace returns the namespace the operator should be watching for changes func GetWatchNamespace() (string, error) { @@ -19,6 +22,11 @@ func GetWatchNamespace() (string, error) { // GetOperatorNamespace returns the namespace of the operator pod func GetOperatorNamespace() (string, error) { + ns, found := os.LookupEnv(OperatorNamespaceEnbVar) + if found { + return ns, nil + } + nsBytes, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") if err != nil { return "", err From 2d4e4545cc64b278b500d5d1452f06ef7ea56722 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 8 Nov 2023 10:20:27 +0100 Subject: [PATCH 03/32] Fix controller-runtime issues. --- cmd/manager/main.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 50b466d597..43116746d0 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -20,12 +20,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/webhook" _ "github.com/Percona-Lab/percona-version-service/api" "github.com/percona/percona-xtradb-cluster-operator/pkg/apis" "github.com/percona/percona-xtradb-cluster-operator/pkg/controller" "github.com/percona/percona-xtradb-cluster-operator/pkg/k8s" - "github.com/percona/percona-xtradb-cluster-operator/pkg/webhook" + hook "github.com/percona/percona-xtradb-cluster-operator/pkg/webhook" "github.com/percona/percona-xtradb-cluster-operator/version" ) @@ -83,22 +84,29 @@ func main() { os.Exit(1) } - options := ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, + Scheme: scheme, + WebhookServer: webhook.NewServer(webhook.Options{ + Port: 9443, + }), + // MetricsBindAddress: metricsAddr, + // Port: 9443, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "08db1feb.percona.com", LeaderElectionNamespace: operatorNamespace, - Namespace: namespace, + // Namespace: namespace, } // Add support for MultiNamespace set in WATCH_NAMESPACE if len(namespace) > 0 { - options.Namespace = "" - options.NewCache = cache.MultiNamespacedCacheBuilder(append(strings.Split(namespace, ","), operatorNamespace)) + // options.Namespace = "" + // options.NewCache = cache.MultiNamespacedCacheBuilder(append(strings.Split(namespace, ","), operatorNamespace)) + namespaces := make(map[string]cache.Config) + for _, ns := range append(strings.Split(namespace, ","), operatorNamespace) { + namespaces[ns] = cache.Config{} + } + options.Cache.DefaultNamespaces = namespaces } // Get a config to talk to the apiserver @@ -140,7 +148,7 @@ func main() { os.Exit(1) } - err = webhook.SetupWebhook(mgr) + err = hook.SetupWebhook(mgr) if err != nil { setupLog.Error(err, "set up validation webhook") os.Exit(1) From 3f914734aa0a8fde95cccefd86906e76fb30c76a Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 8 Nov 2023 15:55:24 +0100 Subject: [PATCH 04/32] Use queries.DatabaseExec --- pkg/controller/pxc/replication.go | 122 ++++++++------- pkg/controller/pxc/secrets.go | 16 ++ pkg/controller/pxc/upgrade.go | 236 +++++++++++++++++++----------- pkg/controller/pxc/version.go | 29 ++-- pkg/pxc/queries/queries.go | 2 +- pkg/pxc/queries/queries_exec.go | 8 +- 6 files changed, 264 insertions(+), 149 deletions(-) diff --git a/pkg/controller/pxc/replication.go b/pkg/controller/pxc/replication.go index f9dbc6c5a8..421e5eb205 100644 --- a/pkg/controller/pxc/replication.go +++ b/pkg/controller/pxc/replication.go @@ -3,7 +3,6 @@ package pxc import ( "context" "fmt" - "strings" "github.com/go-logr/logr" "github.com/hashicorp/go-version" @@ -131,34 +130,43 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context } } - primary, err := r.getPrimaryPod(cr) - if err != nil { - return errors.Wrap(err, "get primary pxc pod") - } + // primary, err := r.getPrimaryPod(cr) + // if err != nil { + // return errors.Wrap(err, "get primary pxc pod") + // } - var primaryPod *corev1.Pod - for _, pod := range podList { - if pod.Status.PodIP == primary || pod.Name == primary || strings.HasPrefix(primary, fmt.Sprintf("%s.%s.%s", pod.Name, sfs.StatefulSet().Name, cr.Namespace)) { - primaryPod = &pod - break - } - } + // var primaryPod *corev1.Pod + // for _, pod := range podList { + // if pod.Status.PodIP == primary || pod.Name == primary || strings.HasPrefix(primary, fmt.Sprintf("%s.%s.%s", pod.Name, sfs.StatefulSet().Name, cr.Namespace)) { + // primaryPod = &pod + // break + // } + // } - if primaryPod == nil { - log.Info("Unable to find primary pod for replication. No pod with name or ip like this", "primary name", primary) - return nil + // if primaryPod == nil { + // log.Info("Unable to find primary pod for replication. No pod with name or ip like this", "primary name", primary) + // return nil + // } + + primaryPod, err := r.getPrimaryPodExec(ctx, cr) + if err != nil { + return errors.Wrap(err, "get primary pxc pod") } - port := int32(33062) + // port := int32(33062) - primaryDB, err := queries.New(r.client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, primaryPod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // primaryDB, err := queries.New(r.client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, primaryPod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // return errors.Wrapf(err, "failed to connect to pod %s", primaryPod.Name) + // } + // defer primaryDB.Close() + pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { - return errors.Wrapf(err, "failed to connect to pod %s", primaryPod.Name) + return errors.Wrap(err, "failed to get operator password") } + primaryDB := queries.NewExec(&primaryPod, r.clientcmd, users.Operator, pass, primaryPod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - defer primaryDB.Close() - - dbVer, err := primaryDB.Version() + dbVer, err := primaryDB.VersionExec(ctx) if err != nil { return errors.Wrap(err, "failed to get current db version") } @@ -172,7 +180,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context return errors.Wrap(err, "remove outdated replication channels") } - err = checkReadonlyStatus(cr.Spec.PXC.ReplicationChannels, podList, cr, r.client) + err = r.checkReadonlyStatus(cr.Spec.PXC.ReplicationChannels, podList, cr, r.client) if err != nil { return errors.Wrap(err, "failed to ensure cluster readonly status") } @@ -191,12 +199,19 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context continue } if _, ok := pod.Labels[replicationPodLabel]; ok { - db, err := queries.New(r.client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // db, err := queries.New(r.client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // return errors.Wrapf(err, "failed to connect to pod %s", pod.Name) + // } + // db.Close() + + pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { - return errors.Wrapf(err, "failed to connect to pod %s", pod.Name) + return errors.Wrap(err, "failed to get operator password") } - err = db.StopAllReplication() - db.Close() + db := queries.NewExec(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + + err = db.StopAllReplicationExec(ctx) if err != nil { return errors.Wrapf(err, "stop replication on pod %s", pod.Name) } @@ -210,7 +225,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context if _, ok := primaryPod.Labels[replicationPodLabel]; !ok { primaryPod.Labels[replicationPodLabel] = "true" - err = r.client.Update(context.TODO(), primaryPod) + err = r.client.Update(context.TODO(), &primaryPod) if err != nil { return errors.Wrap(err, "add label to main replica pod") } @@ -253,14 +268,14 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context return r.updateStatus(cr, false, nil) } -func handleReplicaPasswordChange(db queries.Database, newPass string) error { - channels, err := db.CurrentReplicationChannels() +func handleReplicaPasswordChange(db *queries.DatabaseExec, newPass string) error { + channels, err := db.CurrentReplicationChannelsExec(context.TODO()) if err != nil { return errors.Wrap(err, "get current replication channels") } for _, channel := range channels { - err := db.ChangeChannelPassword(channel, newPass) + err := db.ChangeChannelPasswordExec(context.TODO(), channel, newPass) if err != nil { return errors.Wrapf(err, "change password for channel %s", channel) } @@ -268,19 +283,28 @@ func handleReplicaPasswordChange(db queries.Database, newPass string) error { return nil } -func checkReadonlyStatus(channels []api.ReplicationChannel, pods []corev1.Pod, cr *api.PerconaXtraDBCluster, client client.Client) error { +func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(channels []api.ReplicationChannel, pods []corev1.Pod, cr *api.PerconaXtraDBCluster, client client.Client) error { isReplica := false if len(channels) > 0 { isReplica = !channels[0].IsSource } for _, pod := range pods { - db, err := queries.New(client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, 33062, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // db, err := queries.New(client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, 33062, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // return errors.Wrapf(err, "connect to pod %s", pod.Name) + // } + // defer db.Close() + + ctx := context.TODO() + + pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { - return errors.Wrapf(err, "connect to pod %s", pod.Name) + return errors.Wrap(err, "failed to get operator password") } - defer db.Close() - readonly, err := db.IsReadonly() + db := queries.NewExec(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + + readonly, err := db.IsReadonlyExec(ctx) if err != nil { return errors.Wrap(err, "check readonly status") } @@ -290,11 +314,11 @@ func checkReadonlyStatus(channels []api.ReplicationChannel, pods []corev1.Pod, c } if isReplica && !readonly { - err = db.EnableReadonly() + err = db.EnableReadonlyExec(ctx) } if !isReplica && readonly { - err = db.DisableReadonly() + err = db.DisableReadonlyExec(ctx) } if err != nil { return errors.Wrap(err, "enable or disable readonly mode") @@ -304,8 +328,8 @@ func checkReadonlyStatus(channels []api.ReplicationChannel, pods []corev1.Pod, c return nil } -func removeOutdatedChannels(db queries.Database, currentChannels []api.ReplicationChannel) error { - dbChannels, err := db.CurrentReplicationChannels() +func removeOutdatedChannels(db *queries.DatabaseExec, currentChannels []api.ReplicationChannel) error { + dbChannels, err := db.CurrentReplicationChannelsExec(context.TODO()) if err != nil { return errors.Wrap(err, "get current replication channels") } @@ -330,17 +354,17 @@ func removeOutdatedChannels(db queries.Database, currentChannels []api.Replicati } for channelToRemove := range toRemove { - err = db.StopReplication(channelToRemove) + err = db.StopReplicationExec(context.TODO(), channelToRemove) if err != nil { return errors.Wrapf(err, "stop replication for channel %s", channelToRemove) } - srcList, err := db.ReplicationChannelSources(channelToRemove) + srcList, err := db.ReplicationChannelSourcesExec(context.TODO(), channelToRemove) if err != nil && err != queries.ErrNotFound { return errors.Wrapf(err, "get src list for outdated channel %s", channelToRemove) } for _, v := range srcList { - err = db.DeleteReplicationSource(channelToRemove, v.Host, v.Port) + err = db.DeleteReplicationSourceExec(context.TODO(), channelToRemove, v.Host, v.Port) if err != nil { return errors.Wrapf(err, "delete replication source for outdated channel %s", channelToRemove) } @@ -349,13 +373,13 @@ func removeOutdatedChannels(db queries.Database, currentChannels []api.Replicati return nil } -func manageReplicationChannel(log logr.Logger, primaryDB queries.Database, channel api.ReplicationChannel, currConf api.ReplicationChannelConfig, replicaPW string) error { - currentSources, err := primaryDB.ReplicationChannelSources(channel.Name) +func manageReplicationChannel(log logr.Logger, primaryDB *queries.DatabaseExec, channel api.ReplicationChannel, currConf api.ReplicationChannelConfig, replicaPW string) error { + currentSources, err := primaryDB.ReplicationChannelSourcesExec(context.TODO(), channel.Name) if err != nil && err != queries.ErrNotFound { return errors.Wrapf(err, "get current replication sources for channel %s", channel.Name) } - replicationStatus, err := primaryDB.ReplicationStatus(channel.Name) + replicationStatus, err := primaryDB.ReplicationStatusExec(context.TODO(), channel.Name) if err != nil { return errors.Wrap(err, "failed to check replication status") } @@ -373,14 +397,14 @@ func manageReplicationChannel(log logr.Logger, primaryDB queries.Database, chann } if replicationStatus == queries.ReplicationStatusActive { - err = primaryDB.StopReplication(channel.Name) + err = primaryDB.StopReplicationExec(context.TODO(), channel.Name) if err != nil { return errors.Wrapf(err, "stop replication for channel %s", channel.Name) } } for _, src := range currentSources { - err = primaryDB.DeleteReplicationSource(channel.Name, src.Host, src.Port) + err = primaryDB.DeleteReplicationSourceExec(context.TODO(), channel.Name, src.Host, src.Port) if err != nil { return errors.Wrapf(err, "delete replication source for channel %s", channel.Name) } @@ -393,13 +417,13 @@ func manageReplicationChannel(log logr.Logger, primaryDB queries.Database, chann if src.Weight > maxWeight { maxWeightSrc = src } - err := primaryDB.AddReplicationSource(channel.Name, src.Host, src.Port, src.Weight) + err := primaryDB.AddReplicationSourceExec(context.TODO(), channel.Name, src.Host, src.Port, src.Weight) if err != nil { return errors.Wrapf(err, "add replication source for channel %s", channel.Name) } } - return primaryDB.StartReplication(replicaPW, queries.ReplicationConfig{ + return primaryDB.StartReplicationExec(context.TODO(), replicaPW, queries.ReplicationConfig{ Source: queries.ReplicationChannelSource{ Name: channel.Name, Host: maxWeightSrc.Host, diff --git a/pkg/controller/pxc/secrets.go b/pkg/controller/pxc/secrets.go index 33b592ec85..6ce1bcd01b 100644 --- a/pkg/controller/pxc/secrets.go +++ b/pkg/controller/pxc/secrets.go @@ -132,3 +132,19 @@ func validatePasswords(secret *corev1.Secret) error { return nil } + +func (r *ReconcilePerconaXtraDBCluster) getUserPass(ctx context.Context, cr *api.PerconaXtraDBCluster, user string) (string, error) { + secretObj := corev1.Secret{} + err := r.client.Get(ctx, + types.NamespacedName{ + Namespace: cr.Namespace, + Name: internalSecretsPrefix + cr.Name, + }, + &secretObj, + ) + if err != nil { + return "", err + } + + return string(secretObj.Data[user]), nil +} diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index fed8e7ddc6..9d4045c580 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" + "github.com/percona/percona-xtradb-cluster-operator/pkg/pxc/app/statefulset" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -293,16 +294,22 @@ func (r *ReconcilePerconaXtraDBCluster) smartUpdate(ctx context.Context, sfs api return nil } - primary, err := r.getPrimaryPod(cr) + primPod, err := r.getPrimaryPodExec(ctx, cr) if err != nil { - return errors.Wrap(err, "get primary pod") - } - for _, pod := range list.Items { - if pod.Status.PodIP == primary || pod.Name == primary { - primary = fmt.Sprintf("%s.%s.%s", pod.Name, currentSet.Name, currentSet.Namespace) - break - } + return errors.Wrap(err, "get primary pxc pod") } + primary := fmt.Sprintf("%s.%s.%s", primPod.Name, currentSet.Name, currentSet.Namespace) + + // primary, err := r.getPrimaryPod(cr) + // if err != nil { + // return errors.Wrap(err, "get primary pod") + // } + // for _, pod := range list.Items { + // if pod.Status.PodIP == primary || pod.Name == primary { + // primary = fmt.Sprintf("%s.%s.%s", pod.Name, currentSet.Name, currentSet.Namespace) + // break + // } + // } log.Info("primary pod", "pod name", primary) @@ -362,7 +369,10 @@ func (r *ReconcilePerconaXtraDBCluster) applyNWait(ctx context.Context, cr *api. return errors.Wrap(err, "failed to wait pod") } - if err := r.waitPXCSynced(cr, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, waitLimit); err != nil { + // if err := r.waitPXCSynced(cr, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, waitLimit); err != nil { + // return errors.Wrap(err, "failed to wait pxc sync") + // } + if err := r.waitPXCSynced(cr, pod, waitLimit); err != nil { return errors.Wrap(err, "failed to wait pxc sync") } @@ -386,18 +396,23 @@ func (r *ReconcilePerconaXtraDBCluster) waitHostgroups(ctx context.Context, cr * return nil } - database, err := r.connectProxy(cr) + // database, err := r.connectProxy(cr) + // if err != nil { + // return errors.Wrap(err, "failed to get proxySQL db") + // } + // defer database.Close() + + pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { - return errors.Wrap(err, "failed to get proxySQL db") + return errors.Wrap(err, "failed to get operator password") } - - defer database.Close() + database := queries.NewExec(pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) podNamePrefix := fmt.Sprintf("%s.%s.%s", pod.Name, sfsName, cr.Namespace) return retry(time.Second*10, time.Duration(waitLimit)*time.Second, func() (bool, error) { - present, err := database.PresentInHostgroups(podNamePrefix) + present, err := database.PresentInHostgroupsExec(ctx, podNamePrefix) if err != nil && err != queries.ErrNotFound { return false, errors.Wrap(err, "failed to get hostgroup status") } @@ -415,18 +430,23 @@ func (r *ReconcilePerconaXtraDBCluster) waitUntilOnline(ctx context.Context, cr return nil } - database, err := r.connectProxy(cr) + // database, err := r.connectProxy(cr) + // if err != nil { + // return errors.Wrap(err, "failed to get proxySQL db") + // } + // defer database.Close() + + pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { - return errors.Wrap(err, "failed to get proxySQL db") + return errors.Wrap(err, "failed to get operator password") } - - defer database.Close() + database := queries.NewExec(pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) podNamePrefix := fmt.Sprintf("%s.%s.%s", pod.Name, sfsName, cr.Namespace) return retry(time.Second*10, time.Duration(waitLimit)*time.Second, func() (bool, error) { - statuses, err := database.ProxySQLInstanceStatus(podNamePrefix) + statuses, err := database.ProxySQLInstanceStatusExec(ctx, podNamePrefix) if err != nil && err != queries.ErrNotFound { return false, errors.Wrap(err, "failed to get status") } @@ -476,91 +496,141 @@ func retry(in, limit time.Duration, f func() (bool, error)) error { } // connectProxy returns a new connection through the proxy (ProxySQL or HAProxy) -func (r *ReconcilePerconaXtraDBCluster) connectProxy(cr *api.PerconaXtraDBCluster) (queries.Database, error) { - var database queries.Database - var user, host string - var port, proxySize int32 - - if cr.ProxySQLEnabled() { - user = users.ProxyAdmin - host = fmt.Sprintf("%s-proxysql-unready.%s", cr.ObjectMeta.Name, cr.Namespace) - proxySize = cr.Spec.ProxySQL.Size - port = 6032 - } else if cr.HAProxyEnabled() { - user = users.Monitor - host = fmt.Sprintf("%s-haproxy.%s", cr.Name, cr.Namespace) - proxySize = cr.Spec.HAProxy.Size - - hasKey, err := cr.ConfigHasKey("mysqld", "proxy_protocol_networks") - if err != nil { - return database, errors.Wrap(err, "check if config has proxy_protocol_networks key") - } - - port = 3306 - if hasKey && cr.CompareVersionWith("1.6.0") >= 0 { - port = 33062 - } - } else { - return database, errors.New("can't detect enabled proxy, please enable HAProxy or ProxySQL") - } - - secrets := cr.Spec.SecretsName - if cr.CompareVersionWith("1.6.0") >= 0 { - secrets = "internal-" + cr.Name +// func (r *ReconcilePerconaXtraDBCluster) connectProxy(cr *api.PerconaXtraDBCluster) (queries.Database, error) { +// var database queries.Database +// var user, host string +// var port, proxySize int32 + +// if cr.ProxySQLEnabled() { +// user = users.ProxyAdmin +// host = fmt.Sprintf("%s-proxysql-unready.%s", cr.ObjectMeta.Name, cr.Namespace) +// proxySize = cr.Spec.ProxySQL.Size +// port = 6032 +// } else if cr.HAProxyEnabled() { +// user = users.Monitor +// host = fmt.Sprintf("%s-haproxy.%s", cr.Name, cr.Namespace) +// proxySize = cr.Spec.HAProxy.Size + +// hasKey, err := cr.ConfigHasKey("mysqld", "proxy_protocol_networks") +// if err != nil { +// return database, errors.Wrap(err, "check if config has proxy_protocol_networks key") +// } + +// port = 3306 +// if hasKey && cr.CompareVersionWith("1.6.0") >= 0 { +// port = 33062 +// } +// } else { +// return database, errors.New("can't detect enabled proxy, please enable HAProxy or ProxySQL") +// } + +// secrets := cr.Spec.SecretsName +// if cr.CompareVersionWith("1.6.0") >= 0 { +// secrets = "internal-" + cr.Name +// } + +// for i := 0; ; i++ { +// db, err := queries.New(r.client, cr.Namespace, secrets, user, host, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) +// if err != nil && i < int(proxySize) { +// time.Sleep(time.Second) +// } else if err != nil && i == int(proxySize) { +// return database, err +// } else { +// database = db +// break +// } +// } + +// return database, nil +// } + +// func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(cr *api.PerconaXtraDBCluster) (string, error) { +// conn, err := r.connectProxy(cr) +// if err != nil { +// return "", errors.Wrap(err, "failed to get proxy connection") +// } +// defer conn.Close() + +// if cr.HAProxyEnabled() { +// host, err := conn.Hostname() +// if err != nil { +// return "", err +// } + +// return host, nil +// } + +// return conn.PrimaryHost() +// } + +func (r *ReconcilePerconaXtraDBCluster) getPrimaryPodExec(ctx context.Context, cr *api.PerconaXtraDBCluster) (corev1.Pod, error) { + sfs := statefulset.NewNode(cr) + + pods := corev1.PodList{} + err := r.client.List(ctx, + &pods, + &client.ListOptions{ + Namespace: cr.Namespace, + LabelSelector: labels.SelectorFromSet(sfs.Labels()), + }, + ) + if err != nil { + return corev1.Pod{}, errors.Wrap(err, "failed to get pod list") } - for i := 0; ; i++ { - db, err := queries.New(r.client, cr.Namespace, secrets, user, host, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - if err != nil && i < int(proxySize) { - time.Sleep(time.Second) - } else if err != nil && i == int(proxySize) { - return database, err - } else { - database = db - break - } + pass, err := r.getUserPass(ctx, cr, users.Operator) + if err != nil { + return corev1.Pod{}, errors.Wrap(err, "failed to get operator password") } + db := queries.NewExec(&pods.Items[0], r.clientcmd, users.Operator, pass, pods.Items[0].Name+"."+cr.Name+"-pxc."+cr.Namespace) - return database, nil -} + db.HostnameExec(ctx) -func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(cr *api.PerconaXtraDBCluster) (string, error) { - conn, err := r.connectProxy(cr) + host, err := db.HostnameExec(ctx) if err != nil { - return "", errors.Wrap(err, "failed to get proxy connection") + return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") } - defer conn.Close() - if cr.HAProxyEnabled() { - host, err := conn.Hostname() + if cr.ProxySQLEnabled() { + host, err = db.PrimaryHostExec(ctx) if err != nil { - return "", err + return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") } + } - return host, nil + for _, p := range pods.Items { + if strings.Contains(p.Name, host) { + return p, nil + } } - return conn.PrimaryHost() + return corev1.Pod{}, errors.New("failed to get primary pod") } -func (r *ReconcilePerconaXtraDBCluster) waitPXCSynced(cr *api.PerconaXtraDBCluster, host string, waitLimit int) error { - secrets := cr.Spec.SecretsName - port := int32(3306) - if cr.CompareVersionWith("1.6.0") >= 0 { - secrets = "internal-" + cr.Name - port = int32(33062) - } - - database, err := queries.New(r.client, cr.Namespace, secrets, users.Root, host, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) +func (r *ReconcilePerconaXtraDBCluster) waitPXCSynced(cr *api.PerconaXtraDBCluster, pod *corev1.Pod, waitLimit int) error { + // secrets := cr.Spec.SecretsName + // port := int32(3306) + // if cr.CompareVersionWith("1.6.0") >= 0 { + // secrets = "internal-" + cr.Name + // port = int32(33062) + // } + + // database, err := queries.New(r.client, cr.Namespace, secrets, users.Root, host, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // return errors.Wrap(err, "failed to access PXC database") + // } + // defer database.Close() + + pass, err := r.getUserPass(context.TODO(), cr, users.Root) if err != nil { - return errors.Wrap(err, "failed to access PXC database") + return errors.Wrap(err, "failed to get root password") } - defer database.Close() + database := queries.NewExec(pod, r.clientcmd, users.Root, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) return retry(time.Second*10, time.Duration(waitLimit)*time.Second, func() (bool, error) { - state, err := database.WsrepLocalStateComment() + state, err := database.WsrepLocalStateCommentExec(context.TODO()) if err != nil { return false, errors.Wrap(err, "failed to get wsrep local state") } diff --git a/pkg/controller/pxc/version.go b/pkg/controller/pxc/version.go index 434c67274c..22cb817533 100644 --- a/pkg/controller/pxc/version.go +++ b/pkg/controller/pxc/version.go @@ -291,27 +291,32 @@ func (r *ReconcilePerconaXtraDBCluster) mysqlVersion(ctx context.Context, cr *ap return "", errors.Wrap(err, "get pod list") } - port := int32(3306) - secrets := cr.Spec.SecretsName - if cr.CompareVersionWith("1.6.0") >= 0 { - port = int32(33062) - secrets = "internal-" + cr.Name - } + // port := int32(3306) + // secrets := cr.Spec.SecretsName + // if cr.CompareVersionWith("1.6.0") >= 0 { + // port = int32(33062) + // secrets = "internal-" + cr.Name + // } for _, pod := range list.Items { if !isPodReady(pod) { continue } - database, err := queries.New(r.client, cr.Namespace, secrets, users.Root, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // database, err := queries.New(r.client, cr.Namespace, secrets, users.Root, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // log.Error(err, "failed to create db instance") + // continue + // } + // defer database.Close() + + pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { - log.Error(err, "failed to create db instance") - continue + return "", errors.Wrap(err, "failed to get operator password") } + database := queries.NewExec(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - defer database.Close() - - version, err := database.Version() + version, err := database.VersionExec(ctx) if err != nil { log.Error(err, "failed to get pxc version") continue diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index 59c5aaa817..081f0025bf 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -53,7 +53,7 @@ type ReplicationChannelSource struct { var ErrNotFound = errors.New("not found") -func New(client client.Client, namespace, secretName, user, host string, port int32, timeout int32) (Database, error) { +func NewOld(client client.Client, namespace, secretName, user, host string, port int32, timeout int32) (Database, error) { secretObj := corev1.Secret{} err := client.Get(context.TODO(), types.NamespacedName{ diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go index c1e0dfa082..0af3d9c0dc 100644 --- a/pkg/pxc/queries/queries_exec.go +++ b/pkg/pxc/queries/queries_exec.go @@ -20,14 +20,14 @@ import ( var sensitiveRegexp = regexp.MustCompile(":.*@") type DatabaseExec struct { - client clientcmd.Client + client *clientcmd.Client pod *corev1.Pod user string pass string host string } -func NewExec(pod *corev1.Pod, cliCmd clientcmd.Client, user, pass, host string) *DatabaseExec { +func NewExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *DatabaseExec { return &DatabaseExec{client: cliCmd, pod: pod, user: user, pass: pass, host: host} } @@ -109,7 +109,7 @@ func (p *DatabaseExec) ChangeChannelPasswordExec(ctx context.Context, channel, p } // channel name moze biti: group_replication_applier ili SHOW REPLICA STATUS FOR CHANNEL group_replication_recovery -func (p *DatabaseExec) ReplicationStatusExec(channel string) (ReplicationStatus, error) { +func (p *DatabaseExec) ReplicationStatusExec(ctx context.Context, channel string) (ReplicationStatus, error) { panic("not implemented") } @@ -329,7 +329,7 @@ func (p *DatabaseExec) WsrepLocalStateCommentExec(ctx context.Context) (string, return rows[0].value, nil } -func (p *DatabaseExec) VersionExecExec(ctx context.Context) (string, error) { +func (p *DatabaseExec) VersionExec(ctx context.Context) (string, error) { rows := []*struct { version string `csv:"version"` }{} From d31e269e328c9de2c5bcc66faa8d9f81a7c95055 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 9 Nov 2023 19:13:15 +0100 Subject: [PATCH 05/32] Implement user exec manger. --- pkg/controller/pxc/upgrade.go | 2 - pkg/controller/pxc/users.go | 121 ++++++----- pkg/controller/pxc/users_without_dp.go | 11 +- pkg/pxc/users/users_exec.go | 280 +++++++++++++++++++++++++ 4 files changed, 353 insertions(+), 61 deletions(-) create mode 100644 pkg/pxc/users/users_exec.go diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index 9d4045c580..d638c8e94f 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -584,8 +584,6 @@ func (r *ReconcilePerconaXtraDBCluster) getPrimaryPodExec(ctx context.Context, c } db := queries.NewExec(&pods.Items[0], r.clientcmd, users.Operator, pass, pods.Items[0].Name+"."+cr.Name+"-pxc."+cr.Namespace) - db.HostnameExec(ctx) - host, err := db.HostnameExec(ctx) if err != nil { return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index f3df49dc03..e26139377a 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -14,6 +14,7 @@ import ( corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -349,17 +350,26 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont if err != nil { return errors.Wrap(err, "generate password") } - addr := cr.Name + "-pxc." + cr.Namespace - if cr.CompareVersionWith("1.6.0") >= 0 { - addr = cr.Name + "-pxc-unready." + cr.Namespace + ":33062" - } - um, err := users.NewManager(addr, users.Root, string(secrets.Data[users.Root]), cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + + primary, err := r.getPrimaryPodExec(ctx, cr) if err != nil { - return errors.Wrap(err, "new users manager") + return errors.Wrap(err, "get primary pod") } - defer um.Close() - err = um.CreateOperatorUser(string(pass)) + host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace + um := users.NewManagerExec(&primary, r.clientcmd, users.Root, string(secrets.Data[users.Root]), host) + + // addr := cr.Name + "-pxc." + cr.Namespace + // if cr.CompareVersionWith("1.6.0") >= 0 { + // addr = cr.Name + "-pxc-unready." + cr.Namespace + ":33062" + // } + // um, err := users.NewManagerOld(addr, users.Root, string(secrets.Data[users.Root]), cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // return errors.Wrap(err, "new users manager") + // } + // defer um.Close() + + err = um.CreateOperatorUser(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create operator user") } @@ -394,11 +404,10 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c return err } - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - defer um.Close() if cr.CompareVersionWith("1.6.0") >= 0 { err := r.updateMonitorUserGrant(ctx, cr, internalSecrets, um) @@ -519,7 +528,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c return nil } -func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, um *users.Manager) error { +func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, um *users.ManagerExec) error { log := logf.FromContext(ctx) annotationName := "grant-for-1.6.0-monitor-user" @@ -527,7 +536,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Conte return nil } - err := um.Update160MonitorUserGrant(string(internalSysSecretObj.Data[users.Monitor])) + err := um.Update160MonitorUserGrant(ctx, string(internalSysSecretObj.Data[users.Monitor])) if err != nil { return errors.Wrap(err, "update monitor grant") } @@ -580,11 +589,10 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUser(ctx context.Conte } if !ver.LessThan(privSystemUserAddedIn) { - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - defer um.Close() if err := r.grantSystemUserPrivilege(ctx, cr, internalSecrets, user, um); err != nil { return errors.Wrap(err, "clustercheck user grant system privilege") @@ -726,13 +734,12 @@ func (r *ReconcilePerconaXtraDBCluster) updateXtrabackupUserGrant(ctx context.Co return nil } - um, err := getUserManager(cr, secrets) + um, err := r.getUserManager(ctx, cr, secrets) if err != nil { return err } - defer um.Close() - err = um.Update170XtrabackupUser(string(secrets.Data[users.Xtrabackup])) + err = um.Update170XtrabackupUser(ctx, string(secrets.Data[users.Xtrabackup])) if err != nil { return errors.Wrap(err, "update xtrabackup grant") } @@ -841,18 +848,17 @@ func (r *ReconcilePerconaXtraDBCluster) manageReplicationUser(ctx context.Contex return nil } - um, err := getUserManager(cr, secrets) + um, err := r.getUserManager(ctx, cr, secrets) if err != nil { return err } - defer um.Close() pass, err = generatePass() if err != nil { return errors.Wrap(err, "generate password") } - err = um.CreateReplicationUser(string(pass)) + err = um.CreateReplicationUser(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create replication user") } @@ -1007,13 +1013,12 @@ func (r *ReconcilePerconaXtraDBCluster) syncPXCUsersWithProxySQL(ctx context.Con } func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(context.TODO(), cr, internalSecrets) if err != nil { return err } - defer um.Close() - err = um.UpdateUserPass(user) + err = um.UpdateUserPass(context.TODO(), user) if err != nil { return errors.Wrap(err, "update user pass") } @@ -1022,13 +1027,12 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(cr *api.Perc } func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(context.TODO(), cr, internalSecrets) if err != nil { return err } - defer um.Close() - err = um.DiscardOldPassword(user) + err = um.DiscardOldPassword(context.TODO(), user) if err != nil { return errors.Wrap(err, fmt.Sprintf("discard old user %s pass", user.Name)) } @@ -1037,13 +1041,12 @@ func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(cr *api.PerconaXtraDB } func (r *ReconcilePerconaXtraDBCluster) isOldPasswordDiscarded(cr *api.PerconaXtraDBCluster, secrets *corev1.Secret, user *users.SysUser) (bool, error) { - um, err := getUserManager(cr, secrets) + um, err := r.getUserManager(context.TODO(), cr, secrets) if err != nil { return false, err } - defer um.Close() - discarded, err := um.IsOldPassDiscarded(user) + discarded, err := um.IsOldPassDiscarded(context.TODO(), user) if err != nil { return false, errors.Wrap(err, "is old password discarded") } @@ -1113,21 +1116,29 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(cr *api.PerconaXtraDBClu return nil } - for i := 0; i < int(cr.Spec.ProxySQL.Size); i++ { - um, err := users.NewManager(cr.Name+"-proxysql-"+strconv.Itoa(i)+"."+cr.Name+"-proxysql-unready."+cr.Namespace+":6032", users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - if err != nil { - return errors.Wrap(err, "new users manager") - } - defer um.Close() - err = um.UpdateProxyUser(user) + sfs := statefulset.NewNode(cr) + + pods := corev1.PodList{} + err := r.client.List(context.TODO(), &pods, &client.ListOptions{ + Namespace: cr.Namespace, + LabelSelector: labels.SelectorFromSet(sfs.Labels())}) + if err != nil { + return errors.Wrap(err, "failed to get pod list") + } + + for _, pod := range pods.Items { + um := users.NewManagerExec(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + + err = um.UpdateProxyUser(context.TODO(), user) if err != nil { return errors.Wrap(err, "update proxy users") } } + return nil } -func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, user *users.SysUser, um *users.Manager) error { +func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, user *users.SysUser, um *users.ManagerExec) error { log := logf.FromContext(ctx) annotationName := "grant-for-1.10.0-system-privilege" @@ -1135,7 +1146,7 @@ func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Con return nil } - if err := um.Update1100SystemUserPrivilege(user); err != nil { + if err := um.Update1100SystemUserPrivilege(ctx, user); err != nil { return errors.Wrap(err, "grant system user privilege") } @@ -1153,7 +1164,7 @@ func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Con return nil } -func getUserManager(cr *api.PerconaXtraDBCluster, secrets *corev1.Secret) (*users.Manager, error) { +func (r *ReconcilePerconaXtraDBCluster) getUserManager(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets *corev1.Secret) (*users.ManagerExec, error) { pxcUser := users.Root pxcPass := string(secrets.Data[users.Root]) if _, ok := secrets.Data[users.Operator]; ok { @@ -1161,21 +1172,27 @@ func getUserManager(cr *api.PerconaXtraDBCluster, secrets *corev1.Secret) (*user pxcPass = string(secrets.Data[users.Operator]) } - addr := cr.Name + "-pxc-unready." + cr.Namespace + ":3306" - hasKey, err := cr.ConfigHasKey("mysqld", "proxy_protocol_networks") - if err != nil { - return nil, errors.Wrap(err, "check if congfig has proxy_protocol_networks key") - } - if hasKey { - addr = cr.Name + "-pxc-unready." + cr.Namespace + ":33062" - } + // addr := cr.Name + "-pxc-unready." + cr.Namespace + ":3306" + // hasKey, err := cr.ConfigHasKey("mysqld", "proxy_protocol_networks") + // if err != nil { + // return nil, errors.Wrap(err, "check if congfig has proxy_protocol_networks key") + // } + // if hasKey { + // addr = cr.Name + "-pxc-unready." + cr.Namespace + ":33062" + // } + + // um, err := users.NewManager(addr, pxcUser, pxcPass, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + // if err != nil { + // return nil, errors.Wrap(err, "new users manager") + // } - um, err := users.NewManager(addr, pxcUser, pxcPass, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) + primary, err := r.getPrimaryPodExec(ctx, cr) if err != nil { - return nil, errors.Wrap(err, "new users manager") + return nil, errors.Wrap(err, "get primary pod") } + host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace - return &um, nil + return users.NewManagerExec(&primary, r.clientcmd, pxcUser, pxcPass, host), nil } func (r *ReconcilePerconaXtraDBCluster) updateUserPassExpirationPolicy(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSecrets *corev1.Secret, user *users.SysUser) error { @@ -1187,12 +1204,12 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassExpirationPolicy(ctx conte } if cr.CompareVersionWith("1.13.0") >= 0 { - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - if err := um.UpdatePassExpirationPolicy(user); err != nil { + if err := um.UpdatePassExpirationPolicy(ctx, user); err != nil { return errors.Wrapf(err, "update %s user password expiration policy", user.Name) } diff --git a/pkg/controller/pxc/users_without_dp.go b/pkg/controller/pxc/users_without_dp.go index a03a5dafd3..376c818481 100644 --- a/pkg/controller/pxc/users_without_dp.go +++ b/pkg/controller/pxc/users_without_dp.go @@ -168,11 +168,10 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUserWithoutDP(ctx context.C return err } - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - defer um.Close() if cr.CompareVersionWith("1.6.0") >= 0 { err := r.updateMonitorUserGrant(ctx, cr, internalSecrets, um) @@ -283,11 +282,10 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUserWithoutDP(ctx cont } if !ver.LessThan(privSystemUserAddedIn) { - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - defer um.Close() if err := r.grantSystemUserPrivilege(ctx, cr, internalSecrets, user, um); err != nil { return errors.Wrap(err, "clustercheck user grant system privilege") @@ -481,13 +479,12 @@ func (r *ReconcilePerconaXtraDBCluster) handleProxyadminUserWithoutDP(ctx contex } func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithoutDP(cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { - um, err := getUserManager(cr, internalSecrets) + um, err := r.getUserManager(context.TODO(), cr, internalSecrets) if err != nil { return err } - defer um.Close() - err = um.UpdateUserPassWithoutDP(user) + err = um.UpdateUserPassWithoutDP(context.TODO(), user) if err != nil { return errors.Wrap(err, "update user pass") } diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go new file mode 100644 index 0000000000..b898a7114a --- /dev/null +++ b/pkg/pxc/users/users_exec.go @@ -0,0 +1,280 @@ +package users + +import ( + "bytes" + "context" + "database/sql" + "encoding/csv" + "fmt" + "regexp" + "strings" + + "github.com/pkg/errors" + + "github.com/gocarina/gocsv" + corev1 "k8s.io/api/core/v1" + + "github.com/percona/percona-xtradb-cluster-operator/clientcmd" +) + +var sensitiveRegexp = regexp.MustCompile(":.*@") + +type ManagerExec struct { + client *clientcmd.Client + pod *corev1.Pod + user string + pass string + host string +} + +func NewManagerExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *ManagerExec { + return &ManagerExec{client: cliCmd, pod: pod, user: user, pass: pass, host: host} +} + +func (d *ManagerExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} + + err := d.client.Exec(d.pod, "mysql", cmd, nil, stdout, stderr, false) + if err != nil { + sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") + serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") + return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) + } + + if strings.Contains(stderr.String(), "ERROR") { + return fmt.Errorf("sql error: %s", stderr) + } + + return nil +} + +func (d *ManagerExec) query(ctx context.Context, query string, out interface{}) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, query, &outb, &errb) + if err != nil { + return err + } + + if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { + return sql.ErrNoRows + } + + csv := csv.NewReader(bytes.NewReader(outb.Bytes())) + csv.Comma = '\t' + + if err = gocsv.UnmarshalCSV(csv, out); err != nil { + return err + } + + return nil +} + +func (u *ManagerExec) CreateOperatorUser(ctx context.Context, pass string) error { + var errb, outb bytes.Buffer + + q := fmt.Sprintf("CREATE USER IF NOT EXISTS 'operator'@'%%' IDENTIFIED BY '%s'", pass) + err := u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "create operator user") + } + + outb.Reset() + errb.Reset() + err = u.exec(ctx, "GRANT ALL ON *.* TO 'operator'@'%' WITH GRANT OPTION", &outb, &errb) + if err != nil { + return errors.Wrap(err, "grant operator user") + } + + return nil +} + +// UpdateUserPassWithoutDP updates user pass without Dual Password +// feature introduced in MsSQL 8 +func (u *ManagerExec) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser) error { + if user == nil { + return nil + } + + var errb, outb bytes.Buffer + for _, host := range user.Hosts { + q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s", user.Name, host, user.Pass) + err := u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "update password") + } + } + + return nil +} + +// UpdateUserPass updates user passwords but retains the current password +// using Dual Password feature of MySQL 8. +func (m *ManagerExec) UpdateUserPass(ctx context.Context, user *SysUser) error { + if user == nil { + return nil + } + + for _, host := range user.Hosts { + var errb, outb bytes.Buffer + q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s' RETAIN CURRENT PASSWORD", user.Name, host, user.Pass) + err := m.exec(ctx, q, &outb, &errb) + if err != nil { + return err + } + } + + return nil +} + +// DiscardOldPassword discards old passwords of given users +func (m *ManagerExec) DiscardOldPassword(ctx context.Context, user *SysUser) error { + if user == nil { + return nil + } + + for _, host := range user.Hosts { + var errb, outb bytes.Buffer + q := fmt.Sprintf("ALTER USER '%s'@'%s' DISCARD OLD PASSWORD", user.Name, host) + err := m.exec(ctx, q, &outb, &errb) + if err != nil { + return err + } + } + + return nil +} + +// IsOldPassDiscarded checks if old password is discarded +func (m *ManagerExec) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bool, error) { + rows := []*struct { + attr string `csv:"attr"` + }{} + + err := m.query(ctx, fmt.Sprintf("SELECT User_attributes as attr FROM mysql.user WHERE user='%s'", user.Name), &rows) + if err != nil { + if err == sql.ErrNoRows { + return true, nil + } + return false, errors.Wrap(err, "select User_attributes field") + } + + if len(rows[0].attr) > 0 { + return false, nil + } + + return true, nil +} + +func (u *ManagerExec) UpdateProxyUser(ctx context.Context, user *SysUser) error { + switch user.Name { + case ProxyAdmin: + q := fmt.Sprintf(` + UPDATE global_variables SET variable_value='%s' WHERE variable_name='admin-admin_credentials'; + UPDATE global_variables SET variable_value='%s' WHERE variable_name='admin-cluster_password'; + LOAD ADMIN VARIABLES TO RUNTIME; + SAVE ADMIN VARIABLES TO DISK; + `, "proxyadmin:"+user.Pass, user.Pass) + + var errb, outb bytes.Buffer + err := u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "update proxy admin password") + } + case Monitor: + q := fmt.Sprintf(` + UPDATE global_variables SET variable_value='%s' WHERE variable_name='mysql-monitor_password'; + LOAD MYSQL VARIABLES TO RUNTIME; + SAVE MYSQL VARIABLES TO DISK; + `, user.Pass) + + var errb, outb bytes.Buffer + err := u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "update proxy monitor password") + } + } + + return nil +} + +// Update160MonitorUserGrant grants SERVICE_CONNECTION_ADMIN rights to the monitor user +// if pxc version is 8 or more and sets the MAX_USER_CONNECTIONS parameter to 100 (empirically determined) +func (u *ManagerExec) Update160MonitorUserGrant(ctx context.Context, pass string) (err error) { + q := fmt.Sprintf(` + CREATE USER IF NOT EXISTS 'monitor'@'%%' IDENTIFIED BY '%s'; + GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%'; + ALTER USER 'monitor'@'%%' WITH MAX_USER_CONNECTIONS 100; + `, pass) + + var errb, outb bytes.Buffer + err = u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "update monitor user grants") + } + + return nil +} + +// Update170XtrabackupUser grants all needed rights to the xtrabackup user +func (u *ManagerExec) Update170XtrabackupUser(ctx context.Context, pass string) (err error) { + q := fmt.Sprintf(` + CREATE USER IF NOT EXISTS 'xtrabackup'@'%%' IDENTIFIED BY '%s'; + GRANT ALL ON *.* TO 'xtrabackup'@'%%'; + `, pass) + var errb, outb bytes.Buffer + err = u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "update xtrabackup user grants") + } + + return nil +} + +// Update1100SystemUserPrivilege grants system_user privilege for monitor and clustercheck users +func (u *ManagerExec) Update1100SystemUserPrivilege(ctx context.Context, user *SysUser) (err error) { + switch user.Name { + case Monitor: + var errb, outb bytes.Buffer + if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'monitor'@'%'", &outb, &errb); err != nil { + return errors.Wrap(err, "monitor user") + } + case Clustercheck: + var errb, outb bytes.Buffer + if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'clustercheck'@'localhost'", &outb, &errb); err != nil { + return errors.Wrap(err, "clustercheck user") + } + } + + return nil +} + +func (u *ManagerExec) CreateReplicationUser(ctx context.Context, password string) error { + q := fmt.Sprintf(` + CREATE USER IF NOT EXISTS 'replication'@'%%' IDENTIFIED BY '%s'; + GRANT REPLICATION SLAVE ON *.* to 'replication'@'%%'; + `, password) + var errb, outb bytes.Buffer + err := u.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "create replication user") + } + + return nil +} + +// UpdatePassExpirationPolicy sets user password expiration policy to never +func (u *ManagerExec) UpdatePassExpirationPolicy(ctx context.Context, user *SysUser) error { + if user == nil { + return nil + } + + for _, host := range user.Hosts { + var errb, outb bytes.Buffer + q := fmt.Sprintf("ALTER USER '%s'@'%s' PASSWORD EXPIRE NEVER", user.Name, host) + err := u.exec(ctx, q, &outb, &errb) + if err != nil { + return err + } + } + return nil +} From 58f9af3e2e34fc69e99be4d4b2799317a0758836 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Sat, 11 Nov 2023 10:26:29 +0100 Subject: [PATCH 06/32] Fix sql result parsing and set proper container. --- cmd/manager/main.go | 12 ++++----- pkg/pxc/queries/queries_exec.go | 48 ++++++++++++++++----------------- pkg/pxc/users/users_exec.go | 6 ++--- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 43116746d0..84fadff665 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -100,8 +100,6 @@ func main() { // Add support for MultiNamespace set in WATCH_NAMESPACE if len(namespace) > 0 { - // options.Namespace = "" - // options.NewCache = cache.MultiNamespacedCacheBuilder(append(strings.Split(namespace, ","), operatorNamespace)) namespaces := make(map[string]cache.Config) for _, ns := range append(strings.Split(namespace, ","), operatorNamespace) { namespaces[ns] = cache.Config{} @@ -148,10 +146,12 @@ func main() { os.Exit(1) } - err = hook.SetupWebhook(mgr) - if err != nil { - setupLog.Error(err, "set up validation webhook") - os.Exit(1) + if _, found := os.LookupEnv("DISABLE_WEBHOOK"); !found { + err = hook.SetupWebhook(mgr) + if err != nil { + setupLog.Error(err, "set up validation webhook") + os.Exit(1) + } } if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go index 0af3d9c0dc..badec75f54 100644 --- a/pkg/pxc/queries/queries_exec.go +++ b/pkg/pxc/queries/queries_exec.go @@ -34,7 +34,7 @@ func NewExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) func (d *DatabaseExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} - err := d.client.Exec(d.pod, "mysql", cmd, nil, stdout, stderr, false) + err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) if err != nil { sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") @@ -71,7 +71,7 @@ func (d *DatabaseExec) query(ctx context.Context, query string, out interface{}) func (p *DatabaseExec) CurrentReplicationChannelsExec(ctx context.Context) ([]string, error) { rows := []*struct { - name string `csv:"name"` + Name string `csv:"name"` }{} q := `SELECT DISTINCT(Channel_name) as name from replication_asynchronous_connection_failover` @@ -85,7 +85,7 @@ func (p *DatabaseExec) CurrentReplicationChannelsExec(ctx context.Context) ([]st result := make([]string, 0) for _, row := range rows { - result = append(result, row.name) + result = append(result, row.Name) } return result, nil } @@ -133,9 +133,9 @@ func (p *DatabaseExec) AddReplicationSourceExec(ctx context.Context, name, host func (p *DatabaseExec) ReplicationChannelSourcesExec(ctx context.Context, channelName string) ([]ReplicationChannelSource, error) { rows := []*struct { - host string `csv:"host"` - port int `csv:"port"` - wieght int `csv:"weight"` + Host string `csv:"host"` + Port int `csv:"port"` + Wieght int `csv:"weight"` }{} q := fmt.Sprintf("SELECT host, port, weight FROM replication_asynchronous_connection_failover WHERE Channel_name = '%s'", channelName) @@ -149,7 +149,7 @@ func (p *DatabaseExec) ReplicationChannelSourcesExec(ctx context.Context, channe result := make([]ReplicationChannelSource, 0) for _, row := range rows { - result = append(result, ReplicationChannelSource{Host: row.host, Port: row.port, Weight: row.wieght}) + result = append(result, ReplicationChannelSource{Host: row.Host, Port: row.Port, Weight: row.Wieght}) } return result, nil } @@ -174,10 +174,10 @@ func (p *DatabaseExec) DisableReadonlyExec(ctx context.Context) error { func (p *DatabaseExec) IsReadonlyExec(ctx context.Context) (bool, error) { rows := []*struct { - ro int `csv:"ro"` + ReadOnly int `csv:"readOnly"` }{} - err := p.query(ctx, "select @@read_only as ro", &rows) - return rows[0].ro == 1, errors.Wrap(err, "select global read_only param") + err := p.query(ctx, "select @@read_only as readOnly", &rows) + return rows[0].ReadOnly == 1, errors.Wrap(err, "select global read_only param") } func (p *DatabaseExec) StartReplicationExec(ctx context.Context, replicaPass string, config ReplicationConfig) error { @@ -232,7 +232,7 @@ func (p *DatabaseExec) DeleteReplicationSourceExec(ctx context.Context, name, ho func (p *DatabaseExec) ProxySQLInstanceStatusExec(ctx context.Context, host string) ([]string, error) { rows := []*struct { - status string `csv:"status"` + Status string `csv:"status"` }{} q := fmt.Sprintf("SELECT status FROM proxysql_servers WHERE hostname LIKE '%s%%'", host) @@ -247,7 +247,7 @@ func (p *DatabaseExec) ProxySQLInstanceStatusExec(ctx context.Context, host stri statuses := []string{} for _, row := range rows { - statuses = append(statuses, row.status) + statuses = append(statuses, row.Status) } return statuses, nil @@ -257,7 +257,7 @@ func (p *DatabaseExec) PresentInHostgroupsExec(ctx context.Context, host string) hostgroups := []string{WriterHostgroup, ReaderHostgroup} rows := []*struct { - count int `csv:"count"` + Count int `csv:"count"` }{} q := fmt.Sprintf(` @@ -272,7 +272,7 @@ func (p *DatabaseExec) PresentInHostgroupsExec(ctx context.Context, host string) } return false, err } - if rows[0].count != len(hostgroups) { + if rows[0].Count != len(hostgroups) { return false, nil } return true, nil @@ -280,7 +280,7 @@ func (p *DatabaseExec) PresentInHostgroupsExec(ctx context.Context, host string) func (p *DatabaseExec) PrimaryHostExec(ctx context.Context) (string, error) { rows := []*struct { - hostname string `csv:"host"` + Hostname string `csv:"host"` }{} q := fmt.Sprintf("SELECT hostname FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) @@ -293,12 +293,12 @@ func (p *DatabaseExec) PrimaryHostExec(ctx context.Context) (string, error) { return "", err } - return rows[0].hostname, nil + return rows[0].Hostname, nil } func (p *DatabaseExec) HostnameExec(ctx context.Context) (string, error) { rows := []*struct { - hostname string `csv:"hostname"` + Hostname string `csv:"hostname"` }{} err := p.query(ctx, "SELECT @@hostname hostname", &rows) @@ -309,13 +309,13 @@ func (p *DatabaseExec) HostnameExec(ctx context.Context) (string, error) { return "", err } - return rows[0].hostname, nil + return rows[0].Hostname, nil } func (p *DatabaseExec) WsrepLocalStateCommentExec(ctx context.Context) (string, error) { rows := []*struct { - variable_name string `csv:"Variable_name"` - value string `csv:"Value"` + VariableName string `csv:"Variable_name"` + Value string `csv:"Value"` }{} err := p.query(ctx, "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'", &rows) @@ -326,15 +326,15 @@ func (p *DatabaseExec) WsrepLocalStateCommentExec(ctx context.Context) (string, return "", err } - return rows[0].value, nil + return rows[0].Value, nil } func (p *DatabaseExec) VersionExec(ctx context.Context) (string, error) { rows := []*struct { - version string `csv:"version"` + Version string `csv:"version"` }{} - err := p.query(ctx, "select @@VERSION;", &rows) + err := p.query(ctx, "select @@VERSION as version;", &rows) if err != nil { if err == sql.ErrNoRows { return "", fmt.Errorf("variable was not found") @@ -342,5 +342,5 @@ func (p *DatabaseExec) VersionExec(ctx context.Context) (string, error) { return "", err } - return rows[0].version, nil + return rows[0].Version, nil } diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index b898a7114a..8cd2cbde8d 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -34,7 +34,7 @@ func NewManagerExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host func (d *ManagerExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} - err := d.client.Exec(d.pod, "mysql", cmd, nil, stdout, stderr, false) + err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) if err != nil { sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") @@ -147,7 +147,7 @@ func (m *ManagerExec) DiscardOldPassword(ctx context.Context, user *SysUser) err // IsOldPassDiscarded checks if old password is discarded func (m *ManagerExec) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bool, error) { rows := []*struct { - attr string `csv:"attr"` + Attr string `csv:"attr"` }{} err := m.query(ctx, fmt.Sprintf("SELECT User_attributes as attr FROM mysql.user WHERE user='%s'", user.Name), &rows) @@ -158,7 +158,7 @@ func (m *ManagerExec) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bo return false, errors.Wrap(err, "select User_attributes field") } - if len(rows[0].attr) > 0 { + if len(rows[0].Attr) > 0 { return false, nil } From 33316f44ce846a1ab6e6964897f872b9258f1583 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 14 Nov 2023 08:29:56 +0100 Subject: [PATCH 07/32] Temp improve getting primary pod. --- pkg/controller/pxc/upgrade.go | 22 +++------------- pkg/controller/pxc/users.go | 20 +++++++------- pkg/controller/pxc/users_without_dp.go | 2 +- pkg/pxc/users/users_exec.go | 36 +++++++++++++------------- 4 files changed, 32 insertions(+), 48 deletions(-) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index d638c8e94f..596c8c0b73 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -578,26 +578,10 @@ func (r *ReconcilePerconaXtraDBCluster) getPrimaryPodExec(ctx context.Context, c return corev1.Pod{}, errors.Wrap(err, "failed to get pod list") } - pass, err := r.getUserPass(ctx, cr, users.Operator) - if err != nil { - return corev1.Pod{}, errors.Wrap(err, "failed to get operator password") - } - db := queries.NewExec(&pods.Items[0], r.clientcmd, users.Operator, pass, pods.Items[0].Name+"."+cr.Name+"-pxc."+cr.Namespace) - - host, err := db.HostnameExec(ctx) - if err != nil { - return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") - } - - if cr.ProxySQLEnabled() { - host, err = db.PrimaryHostExec(ctx) - if err != nil { - return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") - } - } - + // TODO: this logic is not complete, primary can be some other pod + // if the pod 0 is not ready for _, p := range pods.Items { - if strings.Contains(p.Name, host) { + if strings.Contains(p.Name, "pxc-0") || isPodReady(p) { return p, nil } } diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index e26139377a..0910113e71 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -369,7 +369,7 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont // } // defer um.Close() - err = um.CreateOperatorUser(ctx, string(pass)) + err = um.CreateOperatorUserExec(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create operator user") } @@ -536,7 +536,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Conte return nil } - err := um.Update160MonitorUserGrant(ctx, string(internalSysSecretObj.Data[users.Monitor])) + err := um.Update160MonitorUserGrantExec(ctx, string(internalSysSecretObj.Data[users.Monitor])) if err != nil { return errors.Wrap(err, "update monitor grant") } @@ -739,7 +739,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateXtrabackupUserGrant(ctx context.Co return err } - err = um.Update170XtrabackupUser(ctx, string(secrets.Data[users.Xtrabackup])) + err = um.Update170XtrabackupUserExec(ctx, string(secrets.Data[users.Xtrabackup])) if err != nil { return errors.Wrap(err, "update xtrabackup grant") } @@ -858,7 +858,7 @@ func (r *ReconcilePerconaXtraDBCluster) manageReplicationUser(ctx context.Contex return errors.Wrap(err, "generate password") } - err = um.CreateReplicationUser(ctx, string(pass)) + err = um.CreateReplicationUserExec(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create replication user") } @@ -1018,7 +1018,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(cr *api.Perc return err } - err = um.UpdateUserPass(context.TODO(), user) + err = um.UpdateUserPassExec(context.TODO(), user) if err != nil { return errors.Wrap(err, "update user pass") } @@ -1032,7 +1032,7 @@ func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(cr *api.PerconaXtraDB return err } - err = um.DiscardOldPassword(context.TODO(), user) + err = um.DiscardOldPasswordExec(context.TODO(), user) if err != nil { return errors.Wrap(err, fmt.Sprintf("discard old user %s pass", user.Name)) } @@ -1046,7 +1046,7 @@ func (r *ReconcilePerconaXtraDBCluster) isOldPasswordDiscarded(cr *api.PerconaXt return false, err } - discarded, err := um.IsOldPassDiscarded(context.TODO(), user) + discarded, err := um.IsOldPassDiscardedExec(context.TODO(), user) if err != nil { return false, errors.Wrap(err, "is old password discarded") } @@ -1129,7 +1129,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(cr *api.PerconaXtraDBClu for _, pod := range pods.Items { um := users.NewManagerExec(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - err = um.UpdateProxyUser(context.TODO(), user) + err = um.UpdateProxyUserExec(context.TODO(), user) if err != nil { return errors.Wrap(err, "update proxy users") } @@ -1146,7 +1146,7 @@ func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Con return nil } - if err := um.Update1100SystemUserPrivilege(ctx, user); err != nil { + if err := um.Update1100SystemUserPrivilegeExec(ctx, user); err != nil { return errors.Wrap(err, "grant system user privilege") } @@ -1209,7 +1209,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassExpirationPolicy(ctx conte return err } - if err := um.UpdatePassExpirationPolicy(ctx, user); err != nil { + if err := um.UpdatePassExpirationPolicyExec(ctx, user); err != nil { return errors.Wrapf(err, "update %s user password expiration policy", user.Name) } diff --git a/pkg/controller/pxc/users_without_dp.go b/pkg/controller/pxc/users_without_dp.go index 376c818481..c7725d3af0 100644 --- a/pkg/controller/pxc/users_without_dp.go +++ b/pkg/controller/pxc/users_without_dp.go @@ -484,7 +484,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithoutDP(cr *api.PerconaX return err } - err = um.UpdateUserPassWithoutDP(context.TODO(), user) + err = um.UpdateUserPassWithoutDPExec(context.TODO(), user) if err != nil { return errors.Wrap(err, "update user pass") } diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index 8cd2cbde8d..c53a7aca4a 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -69,7 +69,7 @@ func (d *ManagerExec) query(ctx context.Context, query string, out interface{}) return nil } -func (u *ManagerExec) CreateOperatorUser(ctx context.Context, pass string) error { +func (u *ManagerExec) CreateOperatorUserExec(ctx context.Context, pass string) error { var errb, outb bytes.Buffer q := fmt.Sprintf("CREATE USER IF NOT EXISTS 'operator'@'%%' IDENTIFIED BY '%s'", pass) @@ -88,9 +88,9 @@ func (u *ManagerExec) CreateOperatorUser(ctx context.Context, pass string) error return nil } -// UpdateUserPassWithoutDP updates user pass without Dual Password +// UpdateUserPassWithoutDPExec updates user pass without Dual Password // feature introduced in MsSQL 8 -func (u *ManagerExec) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser) error { +func (u *ManagerExec) UpdateUserPassWithoutDPExec(ctx context.Context, user *SysUser) error { if user == nil { return nil } @@ -107,9 +107,9 @@ func (u *ManagerExec) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser return nil } -// UpdateUserPass updates user passwords but retains the current password +// UpdateUserPassExec updates user passwords but retains the current password // using Dual Password feature of MySQL 8. -func (m *ManagerExec) UpdateUserPass(ctx context.Context, user *SysUser) error { +func (m *ManagerExec) UpdateUserPassExec(ctx context.Context, user *SysUser) error { if user == nil { return nil } @@ -126,8 +126,8 @@ func (m *ManagerExec) UpdateUserPass(ctx context.Context, user *SysUser) error { return nil } -// DiscardOldPassword discards old passwords of given users -func (m *ManagerExec) DiscardOldPassword(ctx context.Context, user *SysUser) error { +// DiscardOldPasswordExec discards old passwords of given users +func (m *ManagerExec) DiscardOldPasswordExec(ctx context.Context, user *SysUser) error { if user == nil { return nil } @@ -145,7 +145,7 @@ func (m *ManagerExec) DiscardOldPassword(ctx context.Context, user *SysUser) err } // IsOldPassDiscarded checks if old password is discarded -func (m *ManagerExec) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bool, error) { +func (m *ManagerExec) IsOldPassDiscardedExec(ctx context.Context, user *SysUser) (bool, error) { rows := []*struct { Attr string `csv:"attr"` }{} @@ -165,7 +165,7 @@ func (m *ManagerExec) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bo return true, nil } -func (u *ManagerExec) UpdateProxyUser(ctx context.Context, user *SysUser) error { +func (u *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) error { switch user.Name { case ProxyAdmin: q := fmt.Sprintf(` @@ -197,9 +197,9 @@ func (u *ManagerExec) UpdateProxyUser(ctx context.Context, user *SysUser) error return nil } -// Update160MonitorUserGrant grants SERVICE_CONNECTION_ADMIN rights to the monitor user +// Update160MonitorUserGrantExec grants SERVICE_CONNECTION_ADMIN rights to the monitor user // if pxc version is 8 or more and sets the MAX_USER_CONNECTIONS parameter to 100 (empirically determined) -func (u *ManagerExec) Update160MonitorUserGrant(ctx context.Context, pass string) (err error) { +func (u *ManagerExec) Update160MonitorUserGrantExec(ctx context.Context, pass string) (err error) { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'monitor'@'%%' IDENTIFIED BY '%s'; GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%'; @@ -215,8 +215,8 @@ func (u *ManagerExec) Update160MonitorUserGrant(ctx context.Context, pass string return nil } -// Update170XtrabackupUser grants all needed rights to the xtrabackup user -func (u *ManagerExec) Update170XtrabackupUser(ctx context.Context, pass string) (err error) { +// Update170XtrabackupUserExec grants all needed rights to the xtrabackup user +func (u *ManagerExec) Update170XtrabackupUserExec(ctx context.Context, pass string) (err error) { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'xtrabackup'@'%%' IDENTIFIED BY '%s'; GRANT ALL ON *.* TO 'xtrabackup'@'%%'; @@ -230,8 +230,8 @@ func (u *ManagerExec) Update170XtrabackupUser(ctx context.Context, pass string) return nil } -// Update1100SystemUserPrivilege grants system_user privilege for monitor and clustercheck users -func (u *ManagerExec) Update1100SystemUserPrivilege(ctx context.Context, user *SysUser) (err error) { +// Update1100SystemUserPrivilegeExec grants system_user privilege for monitor and clustercheck users +func (u *ManagerExec) Update1100SystemUserPrivilegeExec(ctx context.Context, user *SysUser) (err error) { switch user.Name { case Monitor: var errb, outb bytes.Buffer @@ -248,7 +248,7 @@ func (u *ManagerExec) Update1100SystemUserPrivilege(ctx context.Context, user *S return nil } -func (u *ManagerExec) CreateReplicationUser(ctx context.Context, password string) error { +func (u *ManagerExec) CreateReplicationUserExec(ctx context.Context, password string) error { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'replication'@'%%' IDENTIFIED BY '%s'; GRANT REPLICATION SLAVE ON *.* to 'replication'@'%%'; @@ -262,8 +262,8 @@ func (u *ManagerExec) CreateReplicationUser(ctx context.Context, password string return nil } -// UpdatePassExpirationPolicy sets user password expiration policy to never -func (u *ManagerExec) UpdatePassExpirationPolicy(ctx context.Context, user *SysUser) error { +// UpdatePassExpirationPolicyExec sets user password expiration policy to never +func (u *ManagerExec) UpdatePassExpirationPolicyExec(ctx context.Context, user *SysUser) error { if user == nil { return nil } From 3985c0162a9edc1c982d3452cf695a43b04a6f8a Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 14 Nov 2023 11:00:25 +0100 Subject: [PATCH 08/32] Implement ReplicationStatusExec. --- pkg/pxc/queries/queries_exec.go | 30 ++++++++++++++++++++++++++++-- pkg/pxc/users/users_exec.go | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go index badec75f54..0899eb1c61 100644 --- a/pkg/pxc/queries/queries_exec.go +++ b/pkg/pxc/queries/queries_exec.go @@ -108,9 +108,35 @@ func (p *DatabaseExec) ChangeChannelPasswordExec(ctx context.Context, channel, p return nil } -// channel name moze biti: group_replication_applier ili SHOW REPLICA STATUS FOR CHANNEL group_replication_recovery func (p *DatabaseExec) ReplicationStatusExec(ctx context.Context, channel string) (ReplicationStatus, error) { - panic("not implemented") + rows := []*struct { + IORunning string `csv:"Replica_IO_Running"` + SQLRunning string `csv:"Replica_SQL_Running"` + LastErrNo int `csv:"Last_Errno"` + }{} + + q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL %s", channel) + err := p.query(ctx, q, &rows) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return ReplicationStatusNotInitiated, nil + } + return ReplicationStatusError, errors.Wrap(err, "select replication status") + } + + ioRunning := rows[0].IORunning == "Yes" + sqlRunning := rows[0].SQLRunning == "Yes" + lastErrNo := rows[0].LastErrNo + + if ioRunning && sqlRunning { + return ReplicationStatusActive, nil + } + + if !ioRunning && !sqlRunning && lastErrNo == 0 { + return ReplicationStatusNotInitiated, nil + } + + return ReplicationStatusError, nil } func (p *DatabaseExec) StopAllReplicationExec(ctx context.Context) error { diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index c53a7aca4a..401ae80e7e 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -158,7 +158,7 @@ func (m *ManagerExec) IsOldPassDiscardedExec(ctx context.Context, user *SysUser) return false, errors.Wrap(err, "select User_attributes field") } - if len(rows[0].Attr) > 0 { + if len(rows[0].Attr) > 0 && rows[0].Attr != "NULL" { return false, nil } From 0aae3e3ea06843df10bec13ccec187c8c5c25279 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 14 Nov 2023 11:13:21 +0100 Subject: [PATCH 09/32] Comments cleanup --- cmd/manager/main.go | 3 - deploy/cr.yaml | 4 +- pkg/controller/pxc/replication.go | 39 +---------- pkg/controller/pxc/upgrade.go | 112 +----------------------------- pkg/controller/pxc/users.go | 28 +------- pkg/controller/pxc/version.go | 14 ---- pkg/pxc/queries/queries.go | 2 +- 7 files changed, 8 insertions(+), 194 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 84fadff665..6855a3fb24 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -89,13 +89,10 @@ func main() { WebhookServer: webhook.NewServer(webhook.Options{ Port: 9443, }), - // MetricsBindAddress: metricsAddr, - // Port: 9443, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "08db1feb.percona.com", LeaderElectionNamespace: operatorNamespace, - // Namespace: namespace, } // Add support for MultiNamespace set in WATCH_NAMESPACE diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 87812aeeee..b4e75b0b4b 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -20,8 +20,8 @@ spec: # sslSecretName: cluster1-ssl # sslInternalSecretName: cluster1-ssl-internal # logCollectorSecretName: cluster1-log-collector-secrets - initContainer: - image: perconalab/percona-xtradb-cluster-operator:main +# initContainer: +# image: perconalab/percona-xtradb-cluster-operator:main # resources: # requests: # memory: 100M diff --git a/pkg/controller/pxc/replication.go b/pkg/controller/pxc/replication.go index 421e5eb205..9098f65d3e 100644 --- a/pkg/controller/pxc/replication.go +++ b/pkg/controller/pxc/replication.go @@ -130,36 +130,11 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context } } - // primary, err := r.getPrimaryPod(cr) - // if err != nil { - // return errors.Wrap(err, "get primary pxc pod") - // } - - // var primaryPod *corev1.Pod - // for _, pod := range podList { - // if pod.Status.PodIP == primary || pod.Name == primary || strings.HasPrefix(primary, fmt.Sprintf("%s.%s.%s", pod.Name, sfs.StatefulSet().Name, cr.Namespace)) { - // primaryPod = &pod - // break - // } - // } - - // if primaryPod == nil { - // log.Info("Unable to find primary pod for replication. No pod with name or ip like this", "primary name", primary) - // return nil - // } - - primaryPod, err := r.getPrimaryPodExec(ctx, cr) + primaryPod, err := r.getPrimaryPod(ctx, cr) if err != nil { return errors.Wrap(err, "get primary pxc pod") } - // port := int32(33062) - - // primaryDB, err := queries.New(r.client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, primaryPod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // return errors.Wrapf(err, "failed to connect to pod %s", primaryPod.Name) - // } - // defer primaryDB.Close() pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { return errors.Wrap(err, "failed to get operator password") @@ -199,12 +174,6 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context continue } if _, ok := pod.Labels[replicationPodLabel]; ok { - // db, err := queries.New(r.client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // return errors.Wrapf(err, "failed to connect to pod %s", pod.Name) - // } - // db.Close() - pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { return errors.Wrap(err, "failed to get operator password") @@ -290,12 +259,6 @@ func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(channels []api.Repli } for _, pod := range pods { - // db, err := queries.New(client, cr.Namespace, internalSecretsPrefix+cr.Name, users.Operator, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, 33062, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // return errors.Wrapf(err, "connect to pod %s", pod.Name) - // } - // defer db.Close() - ctx := context.TODO() pass, err := r.getUserPass(ctx, cr, users.Operator) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index 596c8c0b73..9a7883807a 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -294,23 +294,11 @@ func (r *ReconcilePerconaXtraDBCluster) smartUpdate(ctx context.Context, sfs api return nil } - primPod, err := r.getPrimaryPodExec(ctx, cr) + primPod, err := r.getPrimaryPod(ctx, cr) if err != nil { return errors.Wrap(err, "get primary pxc pod") } primary := fmt.Sprintf("%s.%s.%s", primPod.Name, currentSet.Name, currentSet.Namespace) - - // primary, err := r.getPrimaryPod(cr) - // if err != nil { - // return errors.Wrap(err, "get primary pod") - // } - // for _, pod := range list.Items { - // if pod.Status.PodIP == primary || pod.Name == primary { - // primary = fmt.Sprintf("%s.%s.%s", pod.Name, currentSet.Name, currentSet.Namespace) - // break - // } - // } - log.Info("primary pod", "pod name", primary) waitLimit := 2 * 60 * 60 // 2 hours @@ -369,9 +357,6 @@ func (r *ReconcilePerconaXtraDBCluster) applyNWait(ctx context.Context, cr *api. return errors.Wrap(err, "failed to wait pod") } - // if err := r.waitPXCSynced(cr, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, waitLimit); err != nil { - // return errors.Wrap(err, "failed to wait pxc sync") - // } if err := r.waitPXCSynced(cr, pod, waitLimit); err != nil { return errors.Wrap(err, "failed to wait pxc sync") } @@ -396,12 +381,6 @@ func (r *ReconcilePerconaXtraDBCluster) waitHostgroups(ctx context.Context, cr * return nil } - // database, err := r.connectProxy(cr) - // if err != nil { - // return errors.Wrap(err, "failed to get proxySQL db") - // } - // defer database.Close() - pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { return errors.Wrap(err, "failed to get operator password") @@ -430,12 +409,6 @@ func (r *ReconcilePerconaXtraDBCluster) waitUntilOnline(ctx context.Context, cr return nil } - // database, err := r.connectProxy(cr) - // if err != nil { - // return errors.Wrap(err, "failed to get proxySQL db") - // } - // defer database.Close() - pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { return errors.Wrap(err, "failed to get operator password") @@ -495,75 +468,7 @@ func retry(in, limit time.Duration, f func() (bool, error)) error { } } -// connectProxy returns a new connection through the proxy (ProxySQL or HAProxy) -// func (r *ReconcilePerconaXtraDBCluster) connectProxy(cr *api.PerconaXtraDBCluster) (queries.Database, error) { -// var database queries.Database -// var user, host string -// var port, proxySize int32 - -// if cr.ProxySQLEnabled() { -// user = users.ProxyAdmin -// host = fmt.Sprintf("%s-proxysql-unready.%s", cr.ObjectMeta.Name, cr.Namespace) -// proxySize = cr.Spec.ProxySQL.Size -// port = 6032 -// } else if cr.HAProxyEnabled() { -// user = users.Monitor -// host = fmt.Sprintf("%s-haproxy.%s", cr.Name, cr.Namespace) -// proxySize = cr.Spec.HAProxy.Size - -// hasKey, err := cr.ConfigHasKey("mysqld", "proxy_protocol_networks") -// if err != nil { -// return database, errors.Wrap(err, "check if config has proxy_protocol_networks key") -// } - -// port = 3306 -// if hasKey && cr.CompareVersionWith("1.6.0") >= 0 { -// port = 33062 -// } -// } else { -// return database, errors.New("can't detect enabled proxy, please enable HAProxy or ProxySQL") -// } - -// secrets := cr.Spec.SecretsName -// if cr.CompareVersionWith("1.6.0") >= 0 { -// secrets = "internal-" + cr.Name -// } - -// for i := 0; ; i++ { -// db, err := queries.New(r.client, cr.Namespace, secrets, user, host, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) -// if err != nil && i < int(proxySize) { -// time.Sleep(time.Second) -// } else if err != nil && i == int(proxySize) { -// return database, err -// } else { -// database = db -// break -// } -// } - -// return database, nil -// } - -// func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(cr *api.PerconaXtraDBCluster) (string, error) { -// conn, err := r.connectProxy(cr) -// if err != nil { -// return "", errors.Wrap(err, "failed to get proxy connection") -// } -// defer conn.Close() - -// if cr.HAProxyEnabled() { -// host, err := conn.Hostname() -// if err != nil { -// return "", err -// } - -// return host, nil -// } - -// return conn.PrimaryHost() -// } - -func (r *ReconcilePerconaXtraDBCluster) getPrimaryPodExec(ctx context.Context, cr *api.PerconaXtraDBCluster) (corev1.Pod, error) { +func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(ctx context.Context, cr *api.PerconaXtraDBCluster) (corev1.Pod, error) { sfs := statefulset.NewNode(cr) pods := corev1.PodList{} @@ -590,19 +495,6 @@ func (r *ReconcilePerconaXtraDBCluster) getPrimaryPodExec(ctx context.Context, c } func (r *ReconcilePerconaXtraDBCluster) waitPXCSynced(cr *api.PerconaXtraDBCluster, pod *corev1.Pod, waitLimit int) error { - // secrets := cr.Spec.SecretsName - // port := int32(3306) - // if cr.CompareVersionWith("1.6.0") >= 0 { - // secrets = "internal-" + cr.Name - // port = int32(33062) - // } - - // database, err := queries.New(r.client, cr.Namespace, secrets, users.Root, host, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // return errors.Wrap(err, "failed to access PXC database") - // } - // defer database.Close() - pass, err := r.getUserPass(context.TODO(), cr, users.Root) if err != nil { return errors.Wrap(err, "failed to get root password") diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index 0910113e71..04cd683a06 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -351,7 +351,7 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont return errors.Wrap(err, "generate password") } - primary, err := r.getPrimaryPodExec(ctx, cr) + primary, err := r.getPrimaryPod(ctx, cr) if err != nil { return errors.Wrap(err, "get primary pod") } @@ -359,16 +359,6 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace um := users.NewManagerExec(&primary, r.clientcmd, users.Root, string(secrets.Data[users.Root]), host) - // addr := cr.Name + "-pxc." + cr.Namespace - // if cr.CompareVersionWith("1.6.0") >= 0 { - // addr = cr.Name + "-pxc-unready." + cr.Namespace + ":33062" - // } - // um, err := users.NewManagerOld(addr, users.Root, string(secrets.Data[users.Root]), cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // return errors.Wrap(err, "new users manager") - // } - // defer um.Close() - err = um.CreateOperatorUserExec(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create operator user") @@ -1172,21 +1162,7 @@ func (r *ReconcilePerconaXtraDBCluster) getUserManager(ctx context.Context, cr * pxcPass = string(secrets.Data[users.Operator]) } - // addr := cr.Name + "-pxc-unready." + cr.Namespace + ":3306" - // hasKey, err := cr.ConfigHasKey("mysqld", "proxy_protocol_networks") - // if err != nil { - // return nil, errors.Wrap(err, "check if congfig has proxy_protocol_networks key") - // } - // if hasKey { - // addr = cr.Name + "-pxc-unready." + cr.Namespace + ":33062" - // } - - // um, err := users.NewManager(addr, pxcUser, pxcPass, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // return nil, errors.Wrap(err, "new users manager") - // } - - primary, err := r.getPrimaryPodExec(ctx, cr) + primary, err := r.getPrimaryPod(ctx, cr) if err != nil { return nil, errors.Wrap(err, "get primary pod") } diff --git a/pkg/controller/pxc/version.go b/pkg/controller/pxc/version.go index 22cb817533..b1f48d4cf4 100644 --- a/pkg/controller/pxc/version.go +++ b/pkg/controller/pxc/version.go @@ -291,25 +291,11 @@ func (r *ReconcilePerconaXtraDBCluster) mysqlVersion(ctx context.Context, cr *ap return "", errors.Wrap(err, "get pod list") } - // port := int32(3306) - // secrets := cr.Spec.SecretsName - // if cr.CompareVersionWith("1.6.0") >= 0 { - // port = int32(33062) - // secrets = "internal-" + cr.Name - // } - for _, pod := range list.Items { if !isPodReady(pod) { continue } - // database, err := queries.New(r.client, cr.Namespace, secrets, users.Root, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace, port, cr.Spec.PXC.ReadinessProbes.TimeoutSeconds) - // if err != nil { - // log.Error(err, "failed to create db instance") - // continue - // } - // defer database.Close() - pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { return "", errors.Wrap(err, "failed to get operator password") diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index 081f0025bf..59c5aaa817 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -53,7 +53,7 @@ type ReplicationChannelSource struct { var ErrNotFound = errors.New("not found") -func NewOld(client client.Client, namespace, secretName, user, host string, port int32, timeout int32) (Database, error) { +func New(client client.Client, namespace, secretName, user, host string, port int32, timeout int32) (Database, error) { secretObj := corev1.Secret{} err := client.Get(context.TODO(), types.NamespacedName{ From fb40c518797ef294872b6acb45fc88c36772766a Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 14 Nov 2023 11:36:01 +0100 Subject: [PATCH 10/32] Cleanup contexts. --- pkg/controller/pxc/controller.go | 4 +- pkg/controller/pxc/replication.go | 74 +++++++-------- pkg/controller/pxc/users.go | 124 ++++++++++++------------- pkg/controller/pxc/users_without_dp.go | 36 +++---- 4 files changed, 118 insertions(+), 120 deletions(-) diff --git a/pkg/controller/pxc/controller.go b/pkg/controller/pxc/controller.go index f9362bd5ad..2f0f0fa5d3 100644 --- a/pkg/controller/pxc/controller.go +++ b/pkg/controller/pxc/controller.go @@ -342,12 +342,12 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(ctx context.Context, request r } if o.Spec.PXC.Expose.Enabled { - err = r.ensurePxcPodServices(o) + err = r.ensurePxcPodServices(ctx, o) if err != nil { return rr, errors.Wrap(err, "create replication services") } } else { - err = r.removePxcPodServices(o) + err = r.removePxcPodServices(ctx, o) if err != nil { return rr, errors.Wrap(err, "remove pxc pod services") } diff --git a/pkg/controller/pxc/replication.go b/pkg/controller/pxc/replication.go index 9098f65d3e..6a964bc6f7 100644 --- a/pkg/controller/pxc/replication.go +++ b/pkg/controller/pxc/replication.go @@ -25,7 +25,7 @@ const replicationPodLabel = "percona.com/replicationPod" var minReplicationVersion = version.Must(version.NewVersion("8.0.23-14.1")) -func (r *ReconcilePerconaXtraDBCluster) ensurePxcPodServices(cr *api.PerconaXtraDBCluster) error { +func (r *ReconcilePerconaXtraDBCluster) ensurePxcPodServices(ctx context.Context, cr *api.PerconaXtraDBCluster) error { if cr.Spec.Pause { return nil } @@ -62,10 +62,10 @@ func (r *ReconcilePerconaXtraDBCluster) ensurePxcPodServices(cr *api.PerconaXtra return errors.Wrap(err, "failed to ensure pxc service") } } - return r.removeOutdatedServices(cr) + return r.removeOutdatedServices(ctx, cr) } -func (r *ReconcilePerconaXtraDBCluster) removeOutdatedServices(cr *api.PerconaXtraDBCluster) error { +func (r *ReconcilePerconaXtraDBCluster) removeOutdatedServices(ctx context.Context, cr *api.PerconaXtraDBCluster) error { //needed for labels svc := NewExposedPXCService("", cr) @@ -75,7 +75,7 @@ func (r *ReconcilePerconaXtraDBCluster) removeOutdatedServices(cr *api.PerconaXt } svcList := &corev1.ServiceList{} - err := r.client.List(context.TODO(), + err := r.client.List(ctx, svcList, &client.ListOptions{ Namespace: cr.Namespace, @@ -89,7 +89,7 @@ func (r *ReconcilePerconaXtraDBCluster) removeOutdatedServices(cr *api.PerconaXt for _, service := range svcList.Items { if _, ok := svcNames[service.Name]; !ok { - err = r.client.Delete(context.TODO(), &service) + err = r.client.Delete(ctx, &service) if err != nil { return errors.Wrapf(err, "failed to delete service %s", service.Name) } @@ -108,7 +108,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context sfs := statefulset.NewNode(cr) listRaw := corev1.PodList{} - err := r.client.List(context.TODO(), + err := r.client.List(ctx, &listRaw, &client.ListOptions{ Namespace: cr.Namespace, @@ -150,22 +150,22 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context return nil } - err = removeOutdatedChannels(primaryDB, cr.Spec.PXC.ReplicationChannels) + err = removeOutdatedChannels(ctx, primaryDB, cr.Spec.PXC.ReplicationChannels) if err != nil { return errors.Wrap(err, "remove outdated replication channels") } - err = r.checkReadonlyStatus(cr.Spec.PXC.ReplicationChannels, podList, cr, r.client) + err = r.checkReadonlyStatus(ctx, cr.Spec.PXC.ReplicationChannels, podList, cr, r.client) if err != nil { return errors.Wrap(err, "failed to ensure cluster readonly status") } if len(cr.Spec.PXC.ReplicationChannels) == 0 { - return deleteReplicaLabels(r.client, podList) + return deleteReplicaLabels(ctx, r.client, podList) } if cr.Spec.PXC.ReplicationChannels[0].IsSource { - return deleteReplicaLabels(r.client, podList) + return deleteReplicaLabels(ctx, r.client, podList) } // if primary pod is not a replica, we need to make it as replica, and stop replication on other pods @@ -185,7 +185,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context return errors.Wrapf(err, "stop replication on pod %s", pod.Name) } delete(pod.Labels, replicationPodLabel) - err = r.client.Update(context.TODO(), &pod) + err = r.client.Update(ctx, &pod) if err != nil { return errors.Wrap(err, "failed to remove primary label from secondary pod") } @@ -194,7 +194,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context if _, ok := primaryPod.Labels[replicationPodLabel]; !ok { primaryPod.Labels[replicationPodLabel] = "true" - err = r.client.Update(context.TODO(), &primaryPod) + err = r.client.Update(ctx, &primaryPod) if err != nil { return errors.Wrap(err, "add label to main replica pod") } @@ -202,7 +202,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context } sysUsersSecretObj := corev1.Secret{} - err = r.client.Get(context.TODO(), + err = r.client.Get(ctx, types.NamespacedName{ Namespace: cr.Namespace, Name: internalSecretsPrefix + cr.Name, @@ -214,7 +214,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context } if replicaPassUpdated { - err = handleReplicaPasswordChange(primaryDB, string(sysUsersSecretObj.Data[users.Replication])) + err = handleReplicaPasswordChange(ctx, primaryDB, string(sysUsersSecretObj.Data[users.Replication])) if err != nil { return errors.Wrap(err, "failed to change replication password") } @@ -227,7 +227,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context currConf := currentReplicaConfig(channel.Name, cr.Status.PXCReplication) - err = manageReplicationChannel(log, primaryDB, channel, currConf, string(sysUsersSecretObj.Data[users.Replication])) + err = manageReplicationChannel(ctx, log, primaryDB, channel, currConf, string(sysUsersSecretObj.Data[users.Replication])) if err != nil { return errors.Wrapf(err, "manage replication channel %s", channel.Name) } @@ -237,14 +237,14 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context return r.updateStatus(cr, false, nil) } -func handleReplicaPasswordChange(db *queries.DatabaseExec, newPass string) error { - channels, err := db.CurrentReplicationChannelsExec(context.TODO()) +func handleReplicaPasswordChange(ctx context.Context, db *queries.DatabaseExec, newPass string) error { + channels, err := db.CurrentReplicationChannelsExec(ctx) if err != nil { return errors.Wrap(err, "get current replication channels") } for _, channel := range channels { - err := db.ChangeChannelPasswordExec(context.TODO(), channel, newPass) + err := db.ChangeChannelPasswordExec(ctx, channel, newPass) if err != nil { return errors.Wrapf(err, "change password for channel %s", channel) } @@ -252,15 +252,13 @@ func handleReplicaPasswordChange(db *queries.DatabaseExec, newPass string) error return nil } -func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(channels []api.ReplicationChannel, pods []corev1.Pod, cr *api.PerconaXtraDBCluster, client client.Client) error { +func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(ctx context.Context, channels []api.ReplicationChannel, pods []corev1.Pod, cr *api.PerconaXtraDBCluster, client client.Client) error { isReplica := false if len(channels) > 0 { isReplica = !channels[0].IsSource } for _, pod := range pods { - ctx := context.TODO() - pass, err := r.getUserPass(ctx, cr, users.Operator) if err != nil { return errors.Wrap(err, "failed to get operator password") @@ -291,8 +289,8 @@ func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(channels []api.Repli return nil } -func removeOutdatedChannels(db *queries.DatabaseExec, currentChannels []api.ReplicationChannel) error { - dbChannels, err := db.CurrentReplicationChannelsExec(context.TODO()) +func removeOutdatedChannels(ctx context.Context, db *queries.DatabaseExec, currentChannels []api.ReplicationChannel) error { + dbChannels, err := db.CurrentReplicationChannelsExec(ctx) if err != nil { return errors.Wrap(err, "get current replication channels") } @@ -317,17 +315,17 @@ func removeOutdatedChannels(db *queries.DatabaseExec, currentChannels []api.Repl } for channelToRemove := range toRemove { - err = db.StopReplicationExec(context.TODO(), channelToRemove) + err = db.StopReplicationExec(ctx, channelToRemove) if err != nil { return errors.Wrapf(err, "stop replication for channel %s", channelToRemove) } - srcList, err := db.ReplicationChannelSourcesExec(context.TODO(), channelToRemove) + srcList, err := db.ReplicationChannelSourcesExec(ctx, channelToRemove) if err != nil && err != queries.ErrNotFound { return errors.Wrapf(err, "get src list for outdated channel %s", channelToRemove) } for _, v := range srcList { - err = db.DeleteReplicationSourceExec(context.TODO(), channelToRemove, v.Host, v.Port) + err = db.DeleteReplicationSourceExec(ctx, channelToRemove, v.Host, v.Port) if err != nil { return errors.Wrapf(err, "delete replication source for outdated channel %s", channelToRemove) } @@ -336,13 +334,13 @@ func removeOutdatedChannels(db *queries.DatabaseExec, currentChannels []api.Repl return nil } -func manageReplicationChannel(log logr.Logger, primaryDB *queries.DatabaseExec, channel api.ReplicationChannel, currConf api.ReplicationChannelConfig, replicaPW string) error { - currentSources, err := primaryDB.ReplicationChannelSourcesExec(context.TODO(), channel.Name) +func manageReplicationChannel(ctx context.Context, log logr.Logger, primaryDB *queries.DatabaseExec, channel api.ReplicationChannel, currConf api.ReplicationChannelConfig, replicaPW string) error { + currentSources, err := primaryDB.ReplicationChannelSourcesExec(ctx, channel.Name) if err != nil && err != queries.ErrNotFound { return errors.Wrapf(err, "get current replication sources for channel %s", channel.Name) } - replicationStatus, err := primaryDB.ReplicationStatusExec(context.TODO(), channel.Name) + replicationStatus, err := primaryDB.ReplicationStatusExec(ctx, channel.Name) if err != nil { return errors.Wrap(err, "failed to check replication status") } @@ -360,14 +358,14 @@ func manageReplicationChannel(log logr.Logger, primaryDB *queries.DatabaseExec, } if replicationStatus == queries.ReplicationStatusActive { - err = primaryDB.StopReplicationExec(context.TODO(), channel.Name) + err = primaryDB.StopReplicationExec(ctx, channel.Name) if err != nil { return errors.Wrapf(err, "stop replication for channel %s", channel.Name) } } for _, src := range currentSources { - err = primaryDB.DeleteReplicationSourceExec(context.TODO(), channel.Name, src.Host, src.Port) + err = primaryDB.DeleteReplicationSourceExec(ctx, channel.Name, src.Host, src.Port) if err != nil { return errors.Wrapf(err, "delete replication source for channel %s", channel.Name) } @@ -380,13 +378,13 @@ func manageReplicationChannel(log logr.Logger, primaryDB *queries.DatabaseExec, if src.Weight > maxWeight { maxWeightSrc = src } - err := primaryDB.AddReplicationSourceExec(context.TODO(), channel.Name, src.Host, src.Port, src.Weight) + err := primaryDB.AddReplicationSourceExec(ctx, channel.Name, src.Host, src.Port, src.Weight) if err != nil { return errors.Wrapf(err, "add replication source for channel %s", channel.Name) } } - return primaryDB.StartReplicationExec(context.TODO(), replicaPW, queries.ReplicationConfig{ + return primaryDB.StartReplicationExec(ctx, replicaPW, queries.ReplicationConfig{ Source: queries.ReplicationChannelSource{ Name: channel.Name, Host: maxWeightSrc.Host, @@ -424,11 +422,11 @@ func isSourcesChanged(new []api.ReplicationSource, old []queries.ReplicationChan return len(oldSrc) != 0 } -func deleteReplicaLabels(client client.Client, pods []corev1.Pod) error { +func deleteReplicaLabels(ctx context.Context, client client.Client, pods []corev1.Pod) error { for _, pod := range pods { if _, ok := pod.Labels[replicationPodLabel]; ok { delete(pod.Labels, replicationPodLabel) - err := client.Update(context.TODO(), &pod) + err := client.Update(ctx, &pod) if err != nil { return errors.Wrap(err, "failed to remove replication label from pod") } @@ -437,7 +435,7 @@ func deleteReplicaLabels(client client.Client, pods []corev1.Pod) error { return nil } -func (r *ReconcilePerconaXtraDBCluster) removePxcPodServices(cr *api.PerconaXtraDBCluster) error { +func (r *ReconcilePerconaXtraDBCluster) removePxcPodServices(ctx context.Context, cr *api.PerconaXtraDBCluster) error { if cr.Spec.Pause { return nil } @@ -446,7 +444,7 @@ func (r *ReconcilePerconaXtraDBCluster) removePxcPodServices(cr *api.PerconaXtra svc := NewExposedPXCService("", cr) svcList := &corev1.ServiceList{} - err := r.client.List(context.TODO(), + err := r.client.List(ctx, svcList, &client.ListOptions{ Namespace: cr.Namespace, @@ -462,7 +460,7 @@ func (r *ReconcilePerconaXtraDBCluster) removePxcPodServices(cr *api.PerconaXtra } for _, service := range svcList.Items { - err = r.client.Delete(context.TODO(), &service) + err = r.client.Delete(ctx, &service) if err != nil { return errors.Wrap(err, "failed to delete external service") } diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index 04cd683a06..1d5950da37 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -47,7 +47,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileUsers(ctx context.Context, cr * log := logf.FromContext(ctx) secrets := corev1.Secret{} - err := r.client.Get(context.TODO(), + err := r.client.Get(ctx, types.NamespacedName{ Namespace: cr.Namespace, Name: cr.Spec.SecretsName, @@ -63,7 +63,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileUsers(ctx context.Context, cr * internalSecretName := internalSecretsPrefix + cr.Name internalSecrets := corev1.Secret{} - err = r.client.Get(context.TODO(), + err = r.client.Get(ctx, types.NamespacedName{ Namespace: cr.Namespace, Name: internalSecretName, @@ -80,7 +80,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileUsers(ctx context.Context, cr * Name: internalSecretName, Namespace: cr.Namespace, } - err = r.client.Create(context.TODO(), is) + err = r.client.Create(ctx, is) if err != nil { return nil, errors.Wrap(err, "create internal sys users secret") } @@ -210,7 +210,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleRootUser(ctx context.Context, cr * return err } - passDiscarded, err := r.isOldPasswordDiscarded(cr, internalSecrets, user) + passDiscarded, err := r.isOldPasswordDiscarded(ctx, cr, internalSecrets, user) if err != nil { return err } @@ -220,7 +220,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleRootUser(ctx context.Context, cr * } if bytes.Equal(secrets.Data[user.Name], internalSecrets.Data[user.Name]) && !passDiscarded { - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old pass") } @@ -231,7 +231,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleRootUser(ctx context.Context, cr * log.Info("Password changed, updating user", "user", user.Name) - err = r.updateUserPassWithRetention(cr, secrets, internalSecrets, user) + err = r.updateUserPassWithRetention(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update root users pass") } @@ -244,13 +244,13 @@ func (r *ReconcilePerconaXtraDBCluster) handleRootUser(ctx context.Context, cr * orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal secrets root user password") } log.Info("Internal secrets updated", "user", user.Name) - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old password") } @@ -283,7 +283,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUser(ctx context.Context, return nil } - passDiscarded, err := r.isOldPasswordDiscarded(cr, internalSecrets, user) + passDiscarded, err := r.isOldPasswordDiscarded(ctx, cr, internalSecrets, user) if err != nil { return err } @@ -293,7 +293,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUser(ctx context.Context, } if bytes.Equal(secrets.Data[user.Name], internalSecrets.Data[user.Name]) && !passDiscarded { - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old pass") } @@ -304,7 +304,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUser(ctx context.Context, log.Info("Password changed, updating user", "user", user.Name) - err = r.updateUserPassWithRetention(cr, secrets, internalSecrets, user) + err = r.updateUserPassWithRetention(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update operator users pass") } @@ -312,7 +312,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUser(ctx context.Context, orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets operator user password") } @@ -320,7 +320,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUser(ctx context.Context, actions.restartProxy = true - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard operator old password") } @@ -367,11 +367,11 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont secrets.Data[users.Operator] = pass internalSecrets.Data[users.Operator] = pass - err = r.client.Update(context.TODO(), secrets) + err = r.client.Update(ctx, secrets) if err != nil { return errors.Wrap(err, "update sys users secret") } - err = r.client.Update(context.TODO(), internalSecrets) + err = r.client.Update(ctx, internalSecrets) if err != nil { return errors.Wrap(err, "update internal users secret") } @@ -438,7 +438,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c return nil } - passDiscarded, err := r.isOldPasswordDiscarded(cr, internalSecrets, user) + passDiscarded, err := r.isOldPasswordDiscarded(ctx, cr, internalSecrets, user) if err != nil { return err } @@ -450,7 +450,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c if bytes.Equal(secrets.Data[user.Name], internalSecrets.Data[user.Name]) && !passDiscarded { log.Info("Password updated but old one not discarded", "user", user.Name) - passPropagated, err := r.isPassPropagated(cr, user) + passPropagated, err := r.isPassPropagated(ctx, cr, user) if err != nil { return errors.Wrap(err, "is password propagated") } @@ -463,7 +463,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c actions.restartPXC = true } - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old pass") } @@ -474,14 +474,14 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c log.Info("Password changed, updating user", "user", user.Name) - err = r.updateUserPassWithRetention(cr, secrets, internalSecrets, user) + err = r.updateUserPassWithRetention(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update monitor users pass") } log.Info("Password updated", "user", user.Name) if cr.Spec.ProxySQLEnabled() { - err := r.updateProxyUser(cr, internalSecrets, user) + err := r.updateProxyUser(ctx, cr, internalSecrets, user) if err != nil { return errors.Wrap(err, "update monitor users pass") } @@ -495,13 +495,13 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets monitor user password") } log.Info("Internal secrets updated", "user", user.Name) - passPropagated, err := r.isPassPropagated(cr, user) + passPropagated, err := r.isPassPropagated(ctx, cr, user) if err != nil { return errors.Wrap(err, "is password propagated") } @@ -509,7 +509,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c return PassNotPropagatedError } - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard monitor old password") } @@ -536,7 +536,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Conte } internalSysSecretObj.Annotations[annotationName] = "done" - err = r.client.Update(context.TODO(), internalSysSecretObj) + err = r.client.Update(ctx, internalSysSecretObj) if err != nil { return errors.Wrap(err, "update internal sys users secret annotation") } @@ -596,7 +596,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUser(ctx context.Conte return nil } - passDiscarded, err := r.isOldPasswordDiscarded(cr, internalSecrets, user) + passDiscarded, err := r.isOldPasswordDiscarded(ctx, cr, internalSecrets, user) if err != nil { return err } @@ -606,7 +606,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUser(ctx context.Conte } if bytes.Equal(secrets.Data[user.Name], internalSecrets.Data[user.Name]) && !passDiscarded { - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old pass") } @@ -617,7 +617,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUser(ctx context.Conte log.Info("Password changed, updating user", "user", user.Name) - err = r.updateUserPassWithRetention(cr, secrets, internalSecrets, user) + err = r.updateUserPassWithRetention(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update clustercheck users pass") } @@ -625,13 +625,13 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUser(ctx context.Conte orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets clustercheck user password") } log.Info("Internal secrets updated", "user", user.Name) - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard clustercheck old pass") } @@ -671,7 +671,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleXtrabackupUser(ctx context.Context return nil } - passDiscarded, err := r.isOldPasswordDiscarded(cr, internalSecrets, user) + passDiscarded, err := r.isOldPasswordDiscarded(ctx, cr, internalSecrets, user) if err != nil { return err } @@ -681,7 +681,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleXtrabackupUser(ctx context.Context } if bytes.Equal(secrets.Data[user.Name], internalSecrets.Data[user.Name]) && !passDiscarded { - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old pass") } @@ -692,7 +692,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleXtrabackupUser(ctx context.Context log.Info("Password changed, updating user", "user", user.Name) - err = r.updateUserPassWithRetention(cr, secrets, internalSecrets, user) + err = r.updateUserPassWithRetention(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update xtrabackup users pass") } @@ -700,13 +700,13 @@ func (r *ReconcilePerconaXtraDBCluster) handleXtrabackupUser(ctx context.Context orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets xtrabackup user password") } log.Info("Internal secrets updated", "user", user.Name) - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard xtrabackup old pass") } @@ -739,7 +739,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateXtrabackupUserGrant(ctx context.Co } secrets.Annotations[annotationName] = "done" - err = r.client.Update(context.TODO(), secrets) + err = r.client.Update(ctx, secrets) if err != nil { return errors.Wrap(err, "update internal sys users secret annotation") } @@ -776,7 +776,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleReplicationUser(ctx context.Contex return nil } - passDiscarded, err := r.isOldPasswordDiscarded(cr, internalSecrets, user) + passDiscarded, err := r.isOldPasswordDiscarded(ctx, cr, internalSecrets, user) if err != nil { return err } @@ -786,7 +786,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleReplicationUser(ctx context.Contex } if bytes.Equal(secrets.Data[user.Name], internalSecrets.Data[user.Name]) && !passDiscarded { - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard old pass") } @@ -797,7 +797,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleReplicationUser(ctx context.Contex log.Info("Password changed, updating user", "user", user.Name) - err = r.updateUserPassWithRetention(cr, secrets, internalSecrets, user) + err = r.updateUserPassWithRetention(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update replication users pass") } @@ -805,13 +805,13 @@ func (r *ReconcilePerconaXtraDBCluster) handleReplicationUser(ctx context.Contex orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets replication user password") } log.Info("Internal secrets updated", "user", user.Name) - err = r.discardOldPassword(cr, secrets, internalSecrets, user) + err = r.discardOldPassword(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "discard replicaiton old pass") } @@ -856,11 +856,11 @@ func (r *ReconcilePerconaXtraDBCluster) manageReplicationUser(ctx context.Contex sysUsersSecretObj.Data[users.Replication] = pass secrets.Data[users.Replication] = pass - err = r.client.Update(context.TODO(), sysUsersSecretObj) + err = r.client.Update(ctx, sysUsersSecretObj) if err != nil { return errors.Wrap(err, "update sys users secret") } - err = r.client.Update(context.TODO(), secrets) + err = r.client.Update(ctx, secrets) if err != nil { return errors.Wrap(err, "update internal users secret") } @@ -895,7 +895,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleProxyadminUser(ctx context.Context log.Info("Password changed, updating user", "user", user.Name) - err := r.updateProxyUser(cr, internalSecrets, user) + err := r.updateProxyUser(ctx, cr, internalSecrets, user) if err != nil { return errors.Wrap(err, "update Proxy users") } @@ -903,7 +903,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleProxyadminUser(ctx context.Context orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets proxyadmin user password") } @@ -925,7 +925,7 @@ func (r *ReconcilePerconaXtraDBCluster) handlePMMUser(ctx context.Context, cr *a if _, ok := internalSecrets.Data[users.PMMServerKey]; !ok { internalSecrets.Data[users.PMMServerKey] = key - err := r.client.Update(context.TODO(), internalSecrets) + err := r.client.Update(ctx, internalSecrets) if err != nil { return errors.Wrap(err, "update internal users secrets pmm user password") } @@ -952,7 +952,7 @@ func (r *ReconcilePerconaXtraDBCluster) handlePMMUser(ctx context.Context, cr *a orig := internalSecrets.DeepCopy() internalSecrets.Data[name] = secrets.Data[name] - err := r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err := r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets pmm user password") } @@ -976,7 +976,7 @@ func (r *ReconcilePerconaXtraDBCluster) syncPXCUsersWithProxySQL(ctx context.Con for i := 0; i < int(cr.Spec.ProxySQL.Size); i++ { pod := corev1.Pod{} - err := r.client.Get(context.TODO(), + err := r.client.Get(ctx, types.NamespacedName{ Namespace: cr.Namespace, Name: cr.Name + "-proxysql-" + strconv.Itoa(i), @@ -1002,13 +1002,13 @@ func (r *ReconcilePerconaXtraDBCluster) syncPXCUsersWithProxySQL(ctx context.Con return nil } -func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { - um, err := r.getUserManager(context.TODO(), cr, internalSecrets) +func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - err = um.UpdateUserPassExec(context.TODO(), user) + err = um.UpdateUserPassExec(ctx, user) if err != nil { return errors.Wrap(err, "update user pass") } @@ -1016,13 +1016,13 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(cr *api.Perc return nil } -func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { - um, err := r.getUserManager(context.TODO(), cr, internalSecrets) +func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - err = um.DiscardOldPasswordExec(context.TODO(), user) + err = um.DiscardOldPasswordExec(ctx, user) if err != nil { return errors.Wrap(err, fmt.Sprintf("discard old user %s pass", user.Name)) } @@ -1030,13 +1030,13 @@ func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(cr *api.PerconaXtraDB return nil } -func (r *ReconcilePerconaXtraDBCluster) isOldPasswordDiscarded(cr *api.PerconaXtraDBCluster, secrets *corev1.Secret, user *users.SysUser) (bool, error) { - um, err := r.getUserManager(context.TODO(), cr, secrets) +func (r *ReconcilePerconaXtraDBCluster) isOldPasswordDiscarded(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets *corev1.Secret, user *users.SysUser) (bool, error) { + um, err := r.getUserManager(ctx, cr, secrets) if err != nil { return false, err } - discarded, err := um.IsOldPassDiscardedExec(context.TODO(), user) + discarded, err := um.IsOldPassDiscardedExec(ctx, user) if err != nil { return false, errors.Wrap(err, "is old password discarded") } @@ -1044,7 +1044,7 @@ func (r *ReconcilePerconaXtraDBCluster) isOldPasswordDiscarded(cr *api.PerconaXt return discarded, nil } -func (r *ReconcilePerconaXtraDBCluster) isPassPropagated(cr *api.PerconaXtraDBCluster, user *users.SysUser) (bool, error) { +func (r *ReconcilePerconaXtraDBCluster) isPassPropagated(ctx context.Context, cr *api.PerconaXtraDBCluster, user *users.SysUser) (bool, error) { components := map[string]int32{ "pxc": cr.Spec.PXC.Size, } @@ -1061,7 +1061,7 @@ func (r *ReconcilePerconaXtraDBCluster) isPassPropagated(cr *api.PerconaXtraDBCl eg.Go(func() error { for i := 0; int32(i) < compCount; i++ { pod := corev1.Pod{} - err := r.client.Get(context.TODO(), + err := r.client.Get(ctx, types.NamespacedName{ Namespace: cr.Namespace, Name: fmt.Sprintf("%s-%s-%d", cr.Name, comp, i), @@ -1101,7 +1101,7 @@ func (r *ReconcilePerconaXtraDBCluster) isPassPropagated(cr *api.PerconaXtraDBCl return true, nil } -func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(cr *api.PerconaXtraDBCluster, internalSecrets *corev1.Secret, user *users.SysUser) error { +func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSecrets *corev1.Secret, user *users.SysUser) error { if user == nil { return nil } @@ -1109,7 +1109,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(cr *api.PerconaXtraDBClu sfs := statefulset.NewNode(cr) pods := corev1.PodList{} - err := r.client.List(context.TODO(), &pods, &client.ListOptions{ + err := r.client.List(ctx, &pods, &client.ListOptions{ Namespace: cr.Namespace, LabelSelector: labels.SelectorFromSet(sfs.Labels())}) if err != nil { @@ -1119,7 +1119,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(cr *api.PerconaXtraDBClu for _, pod := range pods.Items { um := users.NewManagerExec(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - err = um.UpdateProxyUserExec(context.TODO(), user) + err = um.UpdateProxyUserExec(ctx, user) if err != nil { return errors.Wrap(err, "update proxy users") } @@ -1145,7 +1145,7 @@ func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Con } internalSysSecretObj.Annotations[annotationName] = "done" - err := r.client.Update(context.TODO(), internalSysSecretObj) + err := r.client.Update(ctx, internalSysSecretObj) if err != nil { return errors.Wrap(err, "update internal sys users secret annotation") } diff --git a/pkg/controller/pxc/users_without_dp.go b/pkg/controller/pxc/users_without_dp.go index c7725d3af0..b00c2e49e2 100644 --- a/pkg/controller/pxc/users_without_dp.go +++ b/pkg/controller/pxc/users_without_dp.go @@ -84,7 +84,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleRootUserWithoutDP(ctx context.Cont log.Info("Password changed, updating user", "user", user.Name) - err := r.updateUserPassWithoutDP(cr, secrets, internalSecrets, user) + err := r.updateUserPassWithoutDP(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update root users pass") } @@ -97,7 +97,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleRootUserWithoutDP(ctx context.Cont orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal secrets root user password") } @@ -136,7 +136,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUserWithoutDP(ctx context. log.Info("Password changed, updating user", "user", user.Name) - err := r.updateUserPassWithoutDP(cr, secrets, internalSecrets, user) + err := r.updateUserPassWithoutDP(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update operator users pass") } @@ -144,7 +144,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleOperatorUserWithoutDP(ctx context. orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets operator user password") } @@ -218,14 +218,14 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUserWithoutDP(ctx context.C log.Info("Password changed, updating user", "user", user.Name) - err := r.updateUserPassWithoutDP(cr, secrets, internalSecrets, user) + err := r.updateUserPassWithoutDP(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update monitor users pass") } log.Info("User password updated", "user", user.Name) if cr.Spec.ProxySQLEnabled() { - err := r.updateProxyUser(cr, internalSecrets, user) + err := r.updateProxyUser(ctx, cr, internalSecrets, user) if err != nil { return errors.Wrap(err, "update monitor users pass") } @@ -239,7 +239,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUserWithoutDP(ctx context.C orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets monitor user password") } @@ -305,7 +305,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUserWithoutDP(ctx cont log.Info("Password changed, updating user", "user", user.Name) - err := r.updateUserPassWithoutDP(cr, secrets, internalSecrets, user) + err := r.updateUserPassWithoutDP(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update clustercheck users pass") } @@ -313,7 +313,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleClustercheckUserWithoutDP(ctx cont orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets clustercheck user password") } @@ -359,7 +359,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleXtrabackupUserWithoutDP(ctx contex log.Info("Password changed, updating user", "user", user.Name) - err := r.updateUserPassWithoutDP(cr, secrets, internalSecrets, user) + err := r.updateUserPassWithoutDP(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update xtrabackup users pass") } @@ -367,7 +367,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleXtrabackupUserWithoutDP(ctx contex orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets xtrabackup user password") } @@ -415,7 +415,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleReplicationUserWithoutDP(ctx conte log.Info("Password changed, updating user", "user", user.Name) - err := r.updateUserPassWithoutDP(cr, secrets, internalSecrets, user) + err := r.updateUserPassWithoutDP(ctx, cr, secrets, internalSecrets, user) if err != nil { return errors.Wrap(err, "update replication users pass") } @@ -423,7 +423,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleReplicationUserWithoutDP(ctx conte orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets replication user password") } @@ -459,7 +459,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleProxyadminUserWithoutDP(ctx contex log.Info("Password changed, updating user", "user", user.Name) - err := r.updateProxyUser(cr, internalSecrets, user) + err := r.updateProxyUser(ctx, cr, internalSecrets, user) if err != nil { return errors.Wrap(err, "update Proxy users") } @@ -467,7 +467,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleProxyadminUserWithoutDP(ctx contex orig := internalSecrets.DeepCopy() internalSecrets.Data[user.Name] = secrets.Data[user.Name] - err = r.client.Patch(context.TODO(), internalSecrets, client.MergeFrom(orig)) + err = r.client.Patch(ctx, internalSecrets, client.MergeFrom(orig)) if err != nil { return errors.Wrap(err, "update internal users secrets proxyadmin user password") } @@ -478,13 +478,13 @@ func (r *ReconcilePerconaXtraDBCluster) handleProxyadminUserWithoutDP(ctx contex return nil } -func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithoutDP(cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { - um, err := r.getUserManager(context.TODO(), cr, internalSecrets) +func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithoutDP(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets, internalSecrets *corev1.Secret, user *users.SysUser) error { + um, err := r.getUserManager(ctx, cr, internalSecrets) if err != nil { return err } - err = um.UpdateUserPassWithoutDPExec(context.TODO(), user) + err = um.UpdateUserPassWithoutDPExec(ctx, user) if err != nil { return errors.Wrap(err, "update user pass") } From e227a375ca7be21860b6b622cb5763caabc5c1b4 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 14 Nov 2023 11:37:26 +0100 Subject: [PATCH 11/32] Remove file. --- chetan.yaml | 129 ---------------------------------------------------- 1 file changed, 129 deletions(-) delete mode 100644 chetan.yaml diff --git a/chetan.yaml b/chetan.yaml deleted file mode 100644 index e99b8a367d..0000000000 --- a/chetan.yaml +++ /dev/null @@ -1,129 +0,0 @@ -apiVersion: pxc.percona.com/v1 -kind: PerconaXtraDBCluster -metadata: - name: cluster1 - finalizers: -# - delete-ssl -# - delete-proxysql-pvc -# - delete-pxc-pvc -# annotations: -# percona.com/issue-vault-token: "true" -spec: - allowUnsafeConfigurations: true - backup: - image: percona/percona-xtradb-cluster-operator:1.13.0-pxc8.0-backup-pxb8.0.32 - pitr: - enabled: false - resources: {} - storageName: "" - crVersion: 1.13.0 - haproxy: - affinity: - antiAffinityTopologyKey: none - configuration: | - timeout client 28800s - timeout connect 100500 - timeout server 28800s - enabled: true - image: percona/percona-xtradb-cluster-operator:1.13.0-haproxy - livenessProbes: {} - loadBalancerSourceRanges: - - 185.211.160.62/31 - - 35.158.96.9/31 - readinessProbes: {} - replicasServiceType: LoadBalancer - resources: - limits: - cpu: 600m - memory: 1G - serviceType: LoadBalancer - sidecarResources: {} - size: 1 - serviceAnnotations: - percona.com/inel: test - pmm: - enabled: false - image: percona/pmm-client:2 - resources: {} - serverHost: 3.73.128.178 - proxysql: - affinity: - antiAffinityTopologyKey: kubernetes.io/hostname - livenessProbes: {} - readinessProbes: {} - resources: {} - sidecarResources: {} - pxc: - affinity: - antiAffinityTopologyKey: kubernetes.io/hostname - configuration: |- - [mysqld] - binlog_cache_size = 131072 - binlog_expire_logs_seconds = 604800 - binlog_format = ROW - binlog_stmt_cache_size = 131072 - innodb_adaptive_hash_index = True - innodb_buffer_pool_chunk_size = 2097152 - innodb_buffer_pool_instances = 6 - innodb_buffer_pool_size = 11619903457 - innodb_ddl_threads = 2 - innodb_flush_log_at_trx_commit = 2 - innodb_flush_method = O_DIRECT - innodb_io_capacity_max = 1800 - innodb_log_file_size = 464124928 - innodb_log_files_in_group = 8 - innodb_monitor_enable = ALL - innodb_page_cleaners = 6 - innodb_parallel_read_threads = 3 - innodb_purge_threads = 4 - join_buffer_size = 524288 - max_connections = 502 - max_heap_table_size = 16777216 - read_rnd_buffer_size = 393216 - replica_compressed_protocol = 1 - replica_exec_mode = STRICT - replica_parallel_type = LOGICAL_CLOCK - replica_parallel_workers = 4 - replica_preserve_commit_order = ON - sort_buffer_size = 524288 - sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,TRADITIONAL,STRICT_ALL_TABLES' - sync_binlog = 1 - table_definition_cache = 4096 - table_open_cache = 4096 - table_open_cache_instances = 4 - tablespace_definition_cache = 512 - thread_cache_size = 18 - thread_pool_size = 6 - thread_stack = 1048576 - tmp_table_size = 16777216 - wsrep-provider-options = evs.join_retrans_period=PT4S;evs.suspect_timeout=PT54S;gmcast.peer_timeout=PT13S;evs.send_window=921;evs.user_send_window=921;pc.announce_timeout=PT54S;gcache.recover=yes;evs.delayed_keep_period=PT554S;evs.inactive_check_period=PT4S;evs.inactive_timeout=PT108S;evs.stats_report_period=PT1M;gcs.fc_limit=115;gmcast.time_wait=PT16S;pc.linger=PT54S;pc.recovery=true;evs.delay_margin=PT27S;evs.max_install_timeouts=4;gcache.size=4269949337;gcs.max_packet_size=117964; - wsrep_slave_threads = 1 - wsrep_sync_wait = 3 - wsrep_trx_fragment_size = 1048576 - wsrep_trx_fragment_unit = bytes - pxc_strict_mode=PERMISSIVE - secure_file_priv ='' - expose: {} - image: percona/percona-xtradb-cluster:8.0.32-24.2 - livenessProbes: {} - podDisruptionBudget: - maxUnavailable: 1 - readinessProbes: {} - resources: - limits: - cpu: "4" - memory: 16G - serviceType: ClusterIP - sidecarResources: {} - size: 3 - volumeSpec: - persistentVolumeClaim: - resources: - requests: - storage: 100G - storageClassName: io1-csi - secretsName: everest-secrets-steve-test1 - updateStrategy: SmartUpdate - upgradeOptions: - apply: never - schedule: 0 4 * * * From 2c591901ad5cd07df4a186a98898bcfde7ac3bca Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 16 Nov 2023 16:14:23 +0100 Subject: [PATCH 12/32] Bump go version to 1.21. --- go.mod | 6 +++--- go.sum | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6dbfa4e2da..e1101054cf 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/percona/percona-xtradb-cluster-operator -go 1.18 +go 1.21 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 @@ -136,10 +136,10 @@ exclude ( go.mongodb.org/mongo-driver v1.3.5 go.mongodb.org/mongo-driver v1.3.6 go.mongodb.org/mongo-driver v1.3.7 - go.mongodb.org/mongo-driver v1.4.0 go.mongodb.org/mongo-driver v1.4.0-beta1 go.mongodb.org/mongo-driver v1.4.0-beta2 go.mongodb.org/mongo-driver v1.4.0-rc0 + go.mongodb.org/mongo-driver v1.4.0 go.mongodb.org/mongo-driver v1.4.1 go.mongodb.org/mongo-driver v1.4.2 go.mongodb.org/mongo-driver v1.4.3 @@ -147,6 +147,6 @@ exclude ( go.mongodb.org/mongo-driver v1.4.5 go.mongodb.org/mongo-driver v1.4.6 go.mongodb.org/mongo-driver v1.4.7 - go.mongodb.org/mongo-driver v1.5.0 go.mongodb.org/mongo-driver v1.5.0-beta1 + go.mongodb.org/mongo-driver v1.5.0 ) diff --git a/go.sum b/go.sum index 1b3bd2c192..786eb0bedb 100644 --- a/go.sum +++ b/go.sum @@ -2,18 +2,22 @@ github.com/Azure/azure-sdk-for-go v67.3.0+incompatible h1:QEvenaO+Y9ShPeCWsSAtol github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Percona-Lab/percona-version-service/api v0.0.0-20201216104127-a39f2dded3cc h1:Teed8lKNzSXdHZCd8HhOJVNptRyShOdsul5w6656IVE= github.com/Percona-Lab/percona-version-service/api v0.0.0-20201216104127-a39f2dded3cc/go.mod h1:QDbZ+DHh0CkTHN6LRkMQd1pEl3b30EaNZ9FA97Mb3TA= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= @@ -34,6 +38,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= @@ -128,6 +133,7 @@ github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d/go.mod h1:5YoVOkjYA github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -178,11 +184,13 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -223,6 +231,7 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -243,6 +252,7 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -266,6 +276,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -285,11 +296,13 @@ go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5queth go.opentelemetry.io/otel v1.15.0 h1:NIl24d4eiLJPM0vKn4HjLYM+UZf6gSfi9Z+NmCxkWbk= go.opentelemetry.io/otel v1.15.0/go.mod h1:qfwLEbWhLPk5gyWrne4XnF0lC8wtywbuJbgfAE3zbek= go.opentelemetry.io/otel/sdk v1.15.0 h1:jZTCkRRd08nxD6w7rIaZeDNGZGGQstH3SfLQ3ZsKICk= +go.opentelemetry.io/otel/sdk v1.15.0/go.mod h1:XDEMrYWzJ4YlC17i6Luih2lwDw2j6G0PkUfr1ZqE+rQ= go.opentelemetry.io/otel/trace v1.15.0 h1:5Fwje4O2ooOxkfyqI/kJwxWotggDLix4BSAvpE1wlpo= go.opentelemetry.io/otel/trace v1.15.0/go.mod h1:CUsmE2Ht1CRkvE8OsMESvraoZrrcgD1J2W8GV1ev0Y4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -312,6 +325,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= From b4a671eacdf32d4e853881f9c9c4a00b3e3f283a Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 16 Nov 2023 16:29:48 +0100 Subject: [PATCH 13/32] Set go version to 1.20. --- go.mod | 6 +++--- go.sum | 14 -------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index e1101054cf..30fbe4fd44 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/percona/percona-xtradb-cluster-operator -go 1.21 +go 1.20 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 @@ -136,10 +136,10 @@ exclude ( go.mongodb.org/mongo-driver v1.3.5 go.mongodb.org/mongo-driver v1.3.6 go.mongodb.org/mongo-driver v1.3.7 + go.mongodb.org/mongo-driver v1.4.0 go.mongodb.org/mongo-driver v1.4.0-beta1 go.mongodb.org/mongo-driver v1.4.0-beta2 go.mongodb.org/mongo-driver v1.4.0-rc0 - go.mongodb.org/mongo-driver v1.4.0 go.mongodb.org/mongo-driver v1.4.1 go.mongodb.org/mongo-driver v1.4.2 go.mongodb.org/mongo-driver v1.4.3 @@ -147,6 +147,6 @@ exclude ( go.mongodb.org/mongo-driver v1.4.5 go.mongodb.org/mongo-driver v1.4.6 go.mongodb.org/mongo-driver v1.4.7 - go.mongodb.org/mongo-driver v1.5.0-beta1 go.mongodb.org/mongo-driver v1.5.0 + go.mongodb.org/mongo-driver v1.5.0-beta1 ) diff --git a/go.sum b/go.sum index 786eb0bedb..1b3bd2c192 100644 --- a/go.sum +++ b/go.sum @@ -2,22 +2,18 @@ github.com/Azure/azure-sdk-for-go v67.3.0+incompatible h1:QEvenaO+Y9ShPeCWsSAtol github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Percona-Lab/percona-version-service/api v0.0.0-20201216104127-a39f2dded3cc h1:Teed8lKNzSXdHZCd8HhOJVNptRyShOdsul5w6656IVE= github.com/Percona-Lab/percona-version-service/api v0.0.0-20201216104127-a39f2dded3cc/go.mod h1:QDbZ+DHh0CkTHN6LRkMQd1pEl3b30EaNZ9FA97Mb3TA= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= @@ -38,7 +34,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= @@ -133,7 +128,6 @@ github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d/go.mod h1:5YoVOkjYA github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -184,13 +178,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -231,7 +223,6 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -252,7 +243,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -276,7 +266,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -296,13 +285,11 @@ go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5queth go.opentelemetry.io/otel v1.15.0 h1:NIl24d4eiLJPM0vKn4HjLYM+UZf6gSfi9Z+NmCxkWbk= go.opentelemetry.io/otel v1.15.0/go.mod h1:qfwLEbWhLPk5gyWrne4XnF0lC8wtywbuJbgfAE3zbek= go.opentelemetry.io/otel/sdk v1.15.0 h1:jZTCkRRd08nxD6w7rIaZeDNGZGGQstH3SfLQ3ZsKICk= -go.opentelemetry.io/otel/sdk v1.15.0/go.mod h1:XDEMrYWzJ4YlC17i6Luih2lwDw2j6G0PkUfr1ZqE+rQ= go.opentelemetry.io/otel/trace v1.15.0 h1:5Fwje4O2ooOxkfyqI/kJwxWotggDLix4BSAvpE1wlpo= go.opentelemetry.io/otel/trace v1.15.0/go.mod h1:CUsmE2Ht1CRkvE8OsMESvraoZrrcgD1J2W8GV1ev0Y4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -325,7 +312,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= From 3732a1d6af517748d4791b84854abc943ce9ddb5 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 16 Nov 2023 16:43:01 +0100 Subject: [PATCH 14/32] Updte controller-runtime. --- go.mod | 66 ++++++++++++------------ go.sum | 156 ++++++++++++++++++++++++++++++--------------------------- 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/go.mod b/go.mod index 30fbe4fd44..bac3175305 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/cert-manager/cert-manager v1.12.1 github.com/flosch/pongo2/v6 v6.0.0 github.com/go-ini/ini v1.67.0 - github.com/go-logr/logr v1.2.4 + github.com/go-logr/logr v1.3.0 github.com/go-logr/zapr v1.2.4 github.com/go-openapi/errors v0.20.4 github.com/go-openapi/runtime v0.26.0 @@ -26,11 +26,11 @@ require ( github.com/pkg/errors v0.9.1 github.com/robfig/cron/v3 v3.0.1 go.uber.org/zap v1.26.0 - golang.org/x/sync v0.3.0 - k8s.io/api v0.28.3 - k8s.io/apimachinery v0.28.3 - k8s.io/client-go v0.28.3 - k8s.io/klog/v2 v2.100.1 + golang.org/x/sync v0.5.0 + k8s.io/api v0.28.4 + k8s.io/apimachinery v0.28.4 + k8s.io/client-go v0.28.4 + k8s.io/klog/v2 v2.110.1 sigs.k8s.io/controller-runtime v0.16.3 ) @@ -44,11 +44,11 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/loads v0.21.2 // indirect github.com/go-openapi/spec v0.20.8 // indirect @@ -59,14 +59,14 @@ require ( github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.7 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -76,10 +76,10 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rs/xid v1.5.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -87,30 +87,30 @@ require ( go.opentelemetry.io/otel v1.15.0 // indirect go.opentelemetry.io/otel/trace v1.15.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/oauth2 v0.14.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.4.0 // indirect + golang.org/x/tools v0.15.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.28.3 // indirect - k8s.io/component-base v0.28.3 // indirect - k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect - k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect + k8s.io/apiextensions-apiserver v0.28.4 // indirect + k8s.io/component-base v0.28.4 // indirect + k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/gateway-api v0.7.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible // Required by OLM diff --git a/go.sum b/go.sum index 1b3bd2c192..4f9b9bb8ab 100644 --- a/go.sum +++ b/go.sum @@ -40,18 +40,18 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU= github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= @@ -66,8 +66,9 @@ github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWL github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -130,9 +131,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -140,6 +140,7 @@ github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvR github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -148,16 +149,15 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -190,8 +190,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ= @@ -229,14 +229,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -265,7 +265,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -277,6 +277,7 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7Jul github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= @@ -302,38 +303,41 @@ golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -349,24 +353,26 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= +golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -377,20 +383,21 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -403,7 +410,6 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -412,29 +418,29 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= -k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= -k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= -k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= -k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= -k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= -k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= -k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= -k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= -k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= -k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= -k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= -k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= +k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU= +k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= +k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= +k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= +k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo= +k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e h1:snPmy96t93RredGRjKfMFt+gvxuVAncqSAyBveJtr4Q= +k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= sigs.k8s.io/gateway-api v0.7.0 h1:/mG8yyJNBifqvuVLW5gwlI4CQs0NR/5q4BKUlf1bVdY= sigs.k8s.io/gateway-api v0.7.0/go.mod h1:Xv0+ZMxX0lu1nSSDIIPEfbVztgNZ+3cfiYrJsa2Ooso= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From fedfe55263f23ceac7757144d6b202a772bf1ef4 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 16 Nov 2023 16:49:18 +0100 Subject: [PATCH 15/32] Set controller-runtime to v0.16.2. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bac3175305..74c5c71edd 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( k8s.io/apimachinery v0.28.4 k8s.io/client-go v0.28.4 k8s.io/klog/v2 v2.110.1 - sigs.k8s.io/controller-runtime v0.16.3 + sigs.k8s.io/controller-runtime v0.16.2 ) require ( diff --git a/go.sum b/go.sum index 4f9b9bb8ab..f205246b69 100644 --- a/go.sum +++ b/go.sum @@ -434,8 +434,8 @@ k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e h1:snPmy96t93RredGRjKfMFt k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= -sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/gateway-api v0.7.0 h1:/mG8yyJNBifqvuVLW5gwlI4CQs0NR/5q4BKUlf1bVdY= sigs.k8s.io/gateway-api v0.7.0/go.mod h1:Xv0+ZMxX0lu1nSSDIIPEfbVztgNZ+3cfiYrJsa2Ooso= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= From 6d1abf36be090839e87577da0e35ba0edd4ed2df Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Mon, 20 Nov 2023 17:18:45 +0100 Subject: [PATCH 16/32] Fix checking if old password is discarded. --- pkg/pxc/queries/queries_exec.go | 5 ++++- pkg/pxc/users/users_exec.go | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go index 0899eb1c61..45c5c2a7b5 100644 --- a/pkg/pxc/queries/queries_exec.go +++ b/pkg/pxc/queries/queries_exec.go @@ -203,7 +203,10 @@ func (p *DatabaseExec) IsReadonlyExec(ctx context.Context) (bool, error) { ReadOnly int `csv:"readOnly"` }{} err := p.query(ctx, "select @@read_only as readOnly", &rows) - return rows[0].ReadOnly == 1, errors.Wrap(err, "select global read_only param") + if err != nil { + return false, errors.Wrap(err, "select global read_only param") + } + return rows[0].ReadOnly == 1, nil } func (p *DatabaseExec) StartReplicationExec(ctx context.Context, replicaPass string, config ReplicationConfig) error { diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index 401ae80e7e..728c263094 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -147,10 +147,10 @@ func (m *ManagerExec) DiscardOldPasswordExec(ctx context.Context, user *SysUser) // IsOldPassDiscarded checks if old password is discarded func (m *ManagerExec) IsOldPassDiscardedExec(ctx context.Context, user *SysUser) (bool, error) { rows := []*struct { - Attr string `csv:"attr"` + HasAttr int `csv:"has_attr"` }{} - err := m.query(ctx, fmt.Sprintf("SELECT User_attributes as attr FROM mysql.user WHERE user='%s'", user.Name), &rows) + err := m.query(ctx, fmt.Sprintf("SELECT IF(User_attributes IS NULL, TRUE, FALSE) AS has_attr FROM mysql.user WHERE user='%s'", user.Name), &rows) if err != nil { if err == sql.ErrNoRows { return true, nil @@ -158,7 +158,7 @@ func (m *ManagerExec) IsOldPassDiscardedExec(ctx context.Context, user *SysUser) return false, errors.Wrap(err, "select User_attributes field") } - if len(rows[0].Attr) > 0 && rows[0].Attr != "NULL" { + if rows[0].HasAttr == 0 { return false, nil } From f3485572d54d8f5d7e8c4cdf6cf581dcf03b7ee6 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Tue, 21 Nov 2023 10:44:02 +0100 Subject: [PATCH 17/32] Properly update monitor and proxyadmin user within ProxySQL. --- pkg/controller/pxc/users.go | 6 +++--- pkg/pxc/users/users_exec.go | 24 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index 1d5950da37..72bc3f1b0f 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -1106,18 +1106,18 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(ctx context.Context, cr return nil } - sfs := statefulset.NewNode(cr) + sts :=statefulset.NewProxy(cr) pods := corev1.PodList{} err := r.client.List(ctx, &pods, &client.ListOptions{ Namespace: cr.Namespace, - LabelSelector: labels.SelectorFromSet(sfs.Labels())}) + LabelSelector: labels.SelectorFromSet(sts.Labels())}) if err != nil { return errors.Wrap(err, "failed to get pod list") } for _, pod := range pods.Items { - um := users.NewManagerExec(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + um := users.NewManagerExec(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), "127.0.0.1") err = um.UpdateProxyUserExec(ctx, user) if err != nil { diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index 728c263094..0ef9efcc38 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -165,7 +165,25 @@ func (m *ManagerExec) IsOldPassDiscardedExec(ctx context.Context, user *SysUser) return true, nil } -func (u *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) error { +// UpdateProxyUserExec updates proxy admin and monitor user passwords within ProxySQL +func (e *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) error { + exec := func(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := []string{"mysql", fmt.Sprintf("-p%s", e.pass), "-u", string(e.user), "-h", e.host, "-P 6032", "-e", stm} + + err := e.client.Exec(e.pod, "proxysql", cmd, nil, stdout, stderr, false) + if err != nil { + sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") + serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") + return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) + } + + if strings.Contains(stderr.String(), "ERROR") { + return fmt.Errorf("sql error: %s", stderr) + } + + return nil + } + switch user.Name { case ProxyAdmin: q := fmt.Sprintf(` @@ -176,7 +194,7 @@ func (u *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) er `, "proxyadmin:"+user.Pass, user.Pass) var errb, outb bytes.Buffer - err := u.exec(ctx, q, &outb, &errb) + err := exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update proxy admin password") } @@ -188,7 +206,7 @@ func (u *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) er `, user.Pass) var errb, outb bytes.Buffer - err := u.exec(ctx, q, &outb, &errb) + err := exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update proxy monitor password") } From 30d7c205620b08352643bab89321074e3860a1ea Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 22 Nov 2023 08:46:40 +0100 Subject: [PATCH 18/32] Fix Update160MonitorUserGrantExec with correct SQL query. --- pkg/pxc/users/users_exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index 0ef9efcc38..30def97489 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -220,7 +220,7 @@ func (e *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) er func (u *ManagerExec) Update160MonitorUserGrantExec(ctx context.Context, pass string) (err error) { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'monitor'@'%%' IDENTIFIED BY '%s'; - GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%'; + /*!80015 GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%' */; ALTER USER 'monitor'@'%%' WITH MAX_USER_CONNECTIONS 100; `, pass) From 090b5bde3fe431308d6e6385bb9335a3a2e5ca89 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 22 Nov 2023 15:53:57 +0100 Subject: [PATCH 19/32] Fix syntax sql error. --- pkg/pxc/users/users_exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go index 30def97489..888b4f607c 100644 --- a/pkg/pxc/users/users_exec.go +++ b/pkg/pxc/users/users_exec.go @@ -97,7 +97,7 @@ func (u *ManagerExec) UpdateUserPassWithoutDPExec(ctx context.Context, user *Sys var errb, outb bytes.Buffer for _, host := range user.Hosts { - q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s", user.Name, host, user.Pass) + q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user.Name, host, user.Pass) err := u.exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update password") From 9273b2ae97b7deb741319375f44b41151ddec8c7 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 22 Nov 2023 17:42:52 +0100 Subject: [PATCH 20/32] Improve getting primary pod. --- pkg/controller/pxc/upgrade.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index 9a7883807a..a585ea6c1d 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -5,6 +5,7 @@ import ( "crypto/md5" "encoding/json" "fmt" + "log" "sort" "strconv" "strings" @@ -483,10 +484,24 @@ func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(ctx context.Context, cr *a return corev1.Pod{}, errors.Wrap(err, "failed to get pod list") } + log.Printf("AAAAAA before sort") + for _, pod := range pods.Items { + log.Printf("AAAAAA pod name is %s", pod.Name) + } + sort.Slice(pods.Items, func(i, j int) bool { + return pods.Items[i].Name < pods.Items[j].Name + }) + + log.Printf("AAAAAA after sort") + for _, pod := range pods.Items { + log.Printf("AAAAAA pod name is %s", pod.Name) + } + // TODO: this logic is not complete, primary can be some other pod // if the pod 0 is not ready for _, p := range pods.Items { - if strings.Contains(p.Name, "pxc-0") || isPodReady(p) { + if isPodReady(p) { + log.Printf("CCCC primary pod is %s", p.Name) return p, nil } } From 65e676cbf1923cb7d803bc877481c1e3903b87fb Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 23 Nov 2023 10:33:45 +0100 Subject: [PATCH 21/32] Cleanup --- pkg/controller/pxc/upgrade.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index a585ea6c1d..5959864cdb 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -484,24 +484,11 @@ func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(ctx context.Context, cr *a return corev1.Pod{}, errors.Wrap(err, "failed to get pod list") } - log.Printf("AAAAAA before sort") - for _, pod := range pods.Items { - log.Printf("AAAAAA pod name is %s", pod.Name) - } sort.Slice(pods.Items, func(i, j int) bool { return pods.Items[i].Name < pods.Items[j].Name }) - - log.Printf("AAAAAA after sort") - for _, pod := range pods.Items { - log.Printf("AAAAAA pod name is %s", pod.Name) - } - - // TODO: this logic is not complete, primary can be some other pod - // if the pod 0 is not ready for _, p := range pods.Items { if isPodReady(p) { - log.Printf("CCCC primary pod is %s", p.Name) return p, nil } } From df3dccb987624a4cc8d5734023c40a11cec29782 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Thu, 23 Nov 2023 10:38:42 +0100 Subject: [PATCH 22/32] Fix import. --- pkg/controller/pxc/upgrade.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index 5959864cdb..1c04f5170b 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -5,7 +5,6 @@ import ( "crypto/md5" "encoding/json" "fmt" - "log" "sort" "strconv" "strings" From eace940c78c90c300c9fbddecfefa150cd8c29e5 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 24 Nov 2023 10:03:39 +0100 Subject: [PATCH 23/32] Get Dabatabase connected through proxy. --- pkg/controller/pxc/upgrade.go | 100 +++++++++++++++++++++++++++----- pkg/pxc/queries/queries_exec.go | 32 ++++++---- 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index 1c04f5170b..a4544eb8c4 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -381,11 +381,10 @@ func (r *ReconcilePerconaXtraDBCluster) waitHostgroups(ctx context.Context, cr * return nil } - pass, err := r.getUserPass(ctx, cr, users.Operator) + database, err := r.connectProxy(ctx, cr) if err != nil { - return errors.Wrap(err, "failed to get operator password") + return errors.Wrap(err, "failed to connect to proxy") } - database := queries.NewExec(pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) podNamePrefix := fmt.Sprintf("%s.%s.%s", pod.Name, sfsName, cr.Namespace) @@ -409,11 +408,10 @@ func (r *ReconcilePerconaXtraDBCluster) waitUntilOnline(ctx context.Context, cr return nil } - pass, err := r.getUserPass(ctx, cr, users.Operator) + database, err := r.connectProxy(ctx, cr) if err != nil { - return errors.Wrap(err, "failed to get operator password") + return errors.Wrap(err, "failed to connect to proxy") } - database := queries.NewExec(pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) podNamePrefix := fmt.Sprintf("%s.%s.%s", pod.Name, sfsName, cr.Namespace) @@ -468,26 +466,100 @@ func retry(in, limit time.Duration, f func() (bool, error)) error { } } +// connectProxy gets queries.DatabaseExec connected to ProxySQL or HAProxy pod +func (r *ReconcilePerconaXtraDBCluster) connectProxy(ctx context.Context, cr *api.PerconaXtraDBCluster) (*queries.DatabaseExec, error) { + getPods := func(sfs api.StatefulApp) ([]corev1.Pod, error) { + pods := corev1.PodList{} + if err := r.client.List(ctx, + &pods, + &client.ListOptions{ + Namespace: cr.Namespace, + LabelSelector: labels.SelectorFromSet(sfs.Labels()), + }, + ); err != nil { + return nil, errors.Wrapf(err, "failed to get pods for statefulset %s", sfs.Name) + } + + return pods.Items, nil + } + + if cr.HAProxyEnabled() { + pass, err := r.getUserPass(ctx, cr, users.Monitor) + if err != nil { + return nil, errors.Wrap(err, "failed to get monitor password") + } + haproxyPods, err := getPods(statefulset.NewHAProxy(cr)) + if err != nil { + return nil, errors.Wrap(err, "failed to get pod list") + } + + for _, p := range haproxyPods { + // get internal secret + if isPodReady(p) { + db := queries.NewHAProxy(&p, r.clientcmd, users.Monitor, pass) + return db, nil + } + } + + } + + pass, err := r.getUserPass(ctx, cr, users.ProxyAdmin) + if err != nil { + return nil, errors.Wrap(err, "failed to get proxyadmin password") + } + proxysqlPods, err := getPods(statefulset.NewProxy(cr)) + if err != nil { + return nil, errors.Wrap(err, "failed to get pod list") + } + + for _, p := range proxysqlPods { + // get internal secret + if isPodReady(p) { + db := queries.NewProxySQL(&p, r.clientcmd, users.ProxyAdmin, pass) + return db, nil + } + } + + return nil, errors.New("failed connect to proxy") +} + func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(ctx context.Context, cr *api.PerconaXtraDBCluster) (corev1.Pod, error) { - sfs := statefulset.NewNode(cr) + db, err := r.connectProxy(ctx, cr) + if err != nil { + return corev1.Pod{}, errors.Wrap(err, "failed to connect to proxy") + } + + var primary string + if cr.HAProxyEnabled() { + h, err := db.HostnameExec(ctx) + if err != nil { + return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") + } + primary = h + } else { + h, err := db.PrimaryHostExec(ctx) + if err != nil { + return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") + } + primary = h + } + + sfs := statefulset.NewNode(cr) pods := corev1.PodList{} - err := r.client.List(ctx, + + if err := r.client.List(ctx, &pods, &client.ListOptions{ Namespace: cr.Namespace, LabelSelector: labels.SelectorFromSet(sfs.Labels()), }, - ) - if err != nil { + ); err != nil { return corev1.Pod{}, errors.Wrap(err, "failed to get pod list") } - sort.Slice(pods.Items, func(i, j int) bool { - return pods.Items[i].Name < pods.Items[j].Name - }) for _, p := range pods.Items { - if isPodReady(p) { + if strings.Contains(primary, p.Name) && isPodReady(p) { return p, nil } } diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go index 45c5c2a7b5..369126641e 100644 --- a/pkg/pxc/queries/queries_exec.go +++ b/pkg/pxc/queries/queries_exec.go @@ -20,21 +20,33 @@ import ( var sensitiveRegexp = regexp.MustCompile(":.*@") type DatabaseExec struct { - client *clientcmd.Client - pod *corev1.Pod - user string - pass string - host string + client *clientcmd.Client + pod *corev1.Pod + container string + cmd []string } +// NewExec creates a new DatabaseExec instance for a given PXC pod func NewExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *DatabaseExec { - return &DatabaseExec{client: cliCmd, pod: pod, user: user, pass: pass, host: host} + cmd := []string{"mysql", "--database", "mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", host, "-e"} + return &DatabaseExec{client: cliCmd, pod: pod, container: "pxc", cmd: cmd} } -func (d *DatabaseExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} +// NewProxySQL creates a new DatabaseExec instance for a given ProxySQL pod +func NewProxySQL(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *DatabaseExec { + cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-P", "6032", "-e"} + return &DatabaseExec{client: cliCmd, pod: pod, container: "proxysql", cmd: cmd} +} - err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) +// NewHAProxy creates a new DatabaseExec instance for a given HAProxy pod +func NewHAProxy(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *DatabaseExec { + cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-e"} + return &DatabaseExec{client: cliCmd, pod: pod, container: "haproxy", cmd: cmd} +} + +func (d *DatabaseExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := append(d.cmd, stm) + err := d.client.Exec(d.pod, d.container, cmd, nil, stdout, stderr, false) if err != nil { sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") @@ -312,7 +324,7 @@ func (p *DatabaseExec) PrimaryHostExec(ctx context.Context) (string, error) { Hostname string `csv:"host"` }{} - q := fmt.Sprintf("SELECT hostname FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) + q := fmt.Sprintf("SELECT hostname as host FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) err := p.query(ctx, q, &rows) if err != nil { From 1c2c1f53996e1992612400094df0fe0a99c6a5ae Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 24 Nov 2023 10:23:06 +0100 Subject: [PATCH 24/32] Refactor --- pkg/controller/pxc/replication.go | 44 +-- pkg/controller/pxc/upgrade.go | 14 +- pkg/controller/pxc/users.go | 34 +- pkg/controller/pxc/users_without_dp.go | 2 +- pkg/controller/pxc/version.go | 4 +- pkg/pxc/queries/queries.go | 410 +++++++++++++------------ pkg/pxc/queries/queries_exec.go | 387 ----------------------- pkg/pxc/users/users.go | 284 +++++++++-------- pkg/pxc/users/users_exec.go | 298 ------------------ 9 files changed, 418 insertions(+), 1059 deletions(-) delete mode 100644 pkg/pxc/queries/queries_exec.go delete mode 100644 pkg/pxc/users/users_exec.go diff --git a/pkg/controller/pxc/replication.go b/pkg/controller/pxc/replication.go index 6a964bc6f7..4964908cb9 100644 --- a/pkg/controller/pxc/replication.go +++ b/pkg/controller/pxc/replication.go @@ -139,9 +139,9 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context if err != nil { return errors.Wrap(err, "failed to get operator password") } - primaryDB := queries.NewExec(&primaryPod, r.clientcmd, users.Operator, pass, primaryPod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + primaryDB := queries.NewPXC(&primaryPod, r.clientcmd, users.Operator, pass, primaryPod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - dbVer, err := primaryDB.VersionExec(ctx) + dbVer, err := primaryDB.Version(ctx) if err != nil { return errors.Wrap(err, "failed to get current db version") } @@ -178,9 +178,9 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context if err != nil { return errors.Wrap(err, "failed to get operator password") } - db := queries.NewExec(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + db := queries.NewPXC(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - err = db.StopAllReplicationExec(ctx) + err = db.StopAllReplication(ctx) if err != nil { return errors.Wrapf(err, "stop replication on pod %s", pod.Name) } @@ -237,14 +237,14 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileReplication(ctx context.Context return r.updateStatus(cr, false, nil) } -func handleReplicaPasswordChange(ctx context.Context, db *queries.DatabaseExec, newPass string) error { - channels, err := db.CurrentReplicationChannelsExec(ctx) +func handleReplicaPasswordChange(ctx context.Context, db *queries.Database, newPass string) error { + channels, err := db.CurrentReplicationChannels(ctx) if err != nil { return errors.Wrap(err, "get current replication channels") } for _, channel := range channels { - err := db.ChangeChannelPasswordExec(ctx, channel, newPass) + err := db.ChangeChannelPassword(ctx, channel, newPass) if err != nil { return errors.Wrapf(err, "change password for channel %s", channel) } @@ -263,7 +263,7 @@ func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(ctx context.Context, if err != nil { return errors.Wrap(err, "failed to get operator password") } - db := queries.NewExec(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + db := queries.NewPXC(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) readonly, err := db.IsReadonlyExec(ctx) if err != nil { @@ -275,11 +275,11 @@ func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(ctx context.Context, } if isReplica && !readonly { - err = db.EnableReadonlyExec(ctx) + err = db.EnableReadonly(ctx) } if !isReplica && readonly { - err = db.DisableReadonlyExec(ctx) + err = db.DisableReadonly(ctx) } if err != nil { return errors.Wrap(err, "enable or disable readonly mode") @@ -289,8 +289,8 @@ func (r *ReconcilePerconaXtraDBCluster) checkReadonlyStatus(ctx context.Context, return nil } -func removeOutdatedChannels(ctx context.Context, db *queries.DatabaseExec, currentChannels []api.ReplicationChannel) error { - dbChannels, err := db.CurrentReplicationChannelsExec(ctx) +func removeOutdatedChannels(ctx context.Context, db *queries.Database, currentChannels []api.ReplicationChannel) error { + dbChannels, err := db.CurrentReplicationChannels(ctx) if err != nil { return errors.Wrap(err, "get current replication channels") } @@ -315,17 +315,17 @@ func removeOutdatedChannels(ctx context.Context, db *queries.DatabaseExec, curre } for channelToRemove := range toRemove { - err = db.StopReplicationExec(ctx, channelToRemove) + err = db.StopReplication(ctx, channelToRemove) if err != nil { return errors.Wrapf(err, "stop replication for channel %s", channelToRemove) } - srcList, err := db.ReplicationChannelSourcesExec(ctx, channelToRemove) + srcList, err := db.ReplicationChannelSources(ctx, channelToRemove) if err != nil && err != queries.ErrNotFound { return errors.Wrapf(err, "get src list for outdated channel %s", channelToRemove) } for _, v := range srcList { - err = db.DeleteReplicationSourceExec(ctx, channelToRemove, v.Host, v.Port) + err = db.DeleteReplicationSource(ctx, channelToRemove, v.Host, v.Port) if err != nil { return errors.Wrapf(err, "delete replication source for outdated channel %s", channelToRemove) } @@ -334,13 +334,13 @@ func removeOutdatedChannels(ctx context.Context, db *queries.DatabaseExec, curre return nil } -func manageReplicationChannel(ctx context.Context, log logr.Logger, primaryDB *queries.DatabaseExec, channel api.ReplicationChannel, currConf api.ReplicationChannelConfig, replicaPW string) error { - currentSources, err := primaryDB.ReplicationChannelSourcesExec(ctx, channel.Name) +func manageReplicationChannel(ctx context.Context, log logr.Logger, primaryDB *queries.Database, channel api.ReplicationChannel, currConf api.ReplicationChannelConfig, replicaPW string) error { + currentSources, err := primaryDB.ReplicationChannelSources(ctx, channel.Name) if err != nil && err != queries.ErrNotFound { return errors.Wrapf(err, "get current replication sources for channel %s", channel.Name) } - replicationStatus, err := primaryDB.ReplicationStatusExec(ctx, channel.Name) + replicationStatus, err := primaryDB.ReplicationStatus(ctx, channel.Name) if err != nil { return errors.Wrap(err, "failed to check replication status") } @@ -358,14 +358,14 @@ func manageReplicationChannel(ctx context.Context, log logr.Logger, primaryDB *q } if replicationStatus == queries.ReplicationStatusActive { - err = primaryDB.StopReplicationExec(ctx, channel.Name) + err = primaryDB.StopReplication(ctx, channel.Name) if err != nil { return errors.Wrapf(err, "stop replication for channel %s", channel.Name) } } for _, src := range currentSources { - err = primaryDB.DeleteReplicationSourceExec(ctx, channel.Name, src.Host, src.Port) + err = primaryDB.DeleteReplicationSource(ctx, channel.Name, src.Host, src.Port) if err != nil { return errors.Wrapf(err, "delete replication source for channel %s", channel.Name) } @@ -378,13 +378,13 @@ func manageReplicationChannel(ctx context.Context, log logr.Logger, primaryDB *q if src.Weight > maxWeight { maxWeightSrc = src } - err := primaryDB.AddReplicationSourceExec(ctx, channel.Name, src.Host, src.Port, src.Weight) + err := primaryDB.AddReplicationSource(ctx, channel.Name, src.Host, src.Port, src.Weight) if err != nil { return errors.Wrapf(err, "add replication source for channel %s", channel.Name) } } - return primaryDB.StartReplicationExec(ctx, replicaPW, queries.ReplicationConfig{ + return primaryDB.StartReplication(ctx, replicaPW, queries.ReplicationConfig{ Source: queries.ReplicationChannelSource{ Name: channel.Name, Host: maxWeightSrc.Host, diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index a4544eb8c4..48b999e6ae 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -390,7 +390,7 @@ func (r *ReconcilePerconaXtraDBCluster) waitHostgroups(ctx context.Context, cr * return retry(time.Second*10, time.Duration(waitLimit)*time.Second, func() (bool, error) { - present, err := database.PresentInHostgroupsExec(ctx, podNamePrefix) + present, err := database.PresentInHostgroups(ctx, podNamePrefix) if err != nil && err != queries.ErrNotFound { return false, errors.Wrap(err, "failed to get hostgroup status") } @@ -417,7 +417,7 @@ func (r *ReconcilePerconaXtraDBCluster) waitUntilOnline(ctx context.Context, cr return retry(time.Second*10, time.Duration(waitLimit)*time.Second, func() (bool, error) { - statuses, err := database.ProxySQLInstanceStatusExec(ctx, podNamePrefix) + statuses, err := database.ProxySQLInstanceStatus(ctx, podNamePrefix) if err != nil && err != queries.ErrNotFound { return false, errors.Wrap(err, "failed to get status") } @@ -467,7 +467,7 @@ func retry(in, limit time.Duration, f func() (bool, error)) error { } // connectProxy gets queries.DatabaseExec connected to ProxySQL or HAProxy pod -func (r *ReconcilePerconaXtraDBCluster) connectProxy(ctx context.Context, cr *api.PerconaXtraDBCluster) (*queries.DatabaseExec, error) { +func (r *ReconcilePerconaXtraDBCluster) connectProxy(ctx context.Context, cr *api.PerconaXtraDBCluster) (*queries.Database, error) { getPods := func(sfs api.StatefulApp) ([]corev1.Pod, error) { pods := corev1.PodList{} if err := r.client.List(ctx, @@ -532,13 +532,13 @@ func (r *ReconcilePerconaXtraDBCluster) getPrimaryPod(ctx context.Context, cr *a var primary string if cr.HAProxyEnabled() { - h, err := db.HostnameExec(ctx) + h, err := db.Hostname(ctx) if err != nil { return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") } primary = h } else { - h, err := db.PrimaryHostExec(ctx) + h, err := db.PrimaryHost(ctx) if err != nil { return corev1.Pod{}, errors.Wrap(err, "failed to get primary pod") } @@ -573,11 +573,11 @@ func (r *ReconcilePerconaXtraDBCluster) waitPXCSynced(cr *api.PerconaXtraDBClust return errors.Wrap(err, "failed to get root password") } - database := queries.NewExec(pod, r.clientcmd, users.Root, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + database := queries.NewPXC(pod, r.clientcmd, users.Root, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) return retry(time.Second*10, time.Duration(waitLimit)*time.Second, func() (bool, error) { - state, err := database.WsrepLocalStateCommentExec(context.TODO()) + state, err := database.WsrepLocalStateComment(context.TODO()) if err != nil { return false, errors.Wrap(err, "failed to get wsrep local state") } diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index 72bc3f1b0f..a93c4552cd 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -357,9 +357,9 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont } host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace - um := users.NewManagerExec(&primary, r.clientcmd, users.Root, string(secrets.Data[users.Root]), host) + um := users.NewManager(&primary, r.clientcmd, users.Root, string(secrets.Data[users.Root]), host) - err = um.CreateOperatorUserExec(ctx, string(pass)) + err = um.CreateOperatorUser(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create operator user") } @@ -518,7 +518,7 @@ func (r *ReconcilePerconaXtraDBCluster) handleMonitorUser(ctx context.Context, c return nil } -func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, um *users.ManagerExec) error { +func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, um *users.Manager) error { log := logf.FromContext(ctx) annotationName := "grant-for-1.6.0-monitor-user" @@ -526,7 +526,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateMonitorUserGrant(ctx context.Conte return nil } - err := um.Update160MonitorUserGrantExec(ctx, string(internalSysSecretObj.Data[users.Monitor])) + err := um.Update160MonitorUserGrant(ctx, string(internalSysSecretObj.Data[users.Monitor])) if err != nil { return errors.Wrap(err, "update monitor grant") } @@ -729,7 +729,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateXtrabackupUserGrant(ctx context.Co return err } - err = um.Update170XtrabackupUserExec(ctx, string(secrets.Data[users.Xtrabackup])) + err = um.Update170XtrabackupUser(ctx, string(secrets.Data[users.Xtrabackup])) if err != nil { return errors.Wrap(err, "update xtrabackup grant") } @@ -848,7 +848,7 @@ func (r *ReconcilePerconaXtraDBCluster) manageReplicationUser(ctx context.Contex return errors.Wrap(err, "generate password") } - err = um.CreateReplicationUserExec(ctx, string(pass)) + err = um.CreateReplicationUser(ctx, string(pass)) if err != nil { return errors.Wrap(err, "create replication user") } @@ -1008,7 +1008,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithRetention(ctx context. return err } - err = um.UpdateUserPassExec(ctx, user) + err = um.UpdateUserPass(ctx, user) if err != nil { return errors.Wrap(err, "update user pass") } @@ -1022,7 +1022,7 @@ func (r *ReconcilePerconaXtraDBCluster) discardOldPassword(ctx context.Context, return err } - err = um.DiscardOldPasswordExec(ctx, user) + err = um.DiscardOldPassword(ctx, user) if err != nil { return errors.Wrap(err, fmt.Sprintf("discard old user %s pass", user.Name)) } @@ -1036,7 +1036,7 @@ func (r *ReconcilePerconaXtraDBCluster) isOldPasswordDiscarded(ctx context.Conte return false, err } - discarded, err := um.IsOldPassDiscardedExec(ctx, user) + discarded, err := um.IsOldPassDiscarded(ctx, user) if err != nil { return false, errors.Wrap(err, "is old password discarded") } @@ -1106,7 +1106,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(ctx context.Context, cr return nil } - sts :=statefulset.NewProxy(cr) + sts := statefulset.NewProxy(cr) pods := corev1.PodList{} err := r.client.List(ctx, &pods, &client.ListOptions{ @@ -1117,9 +1117,9 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(ctx context.Context, cr } for _, pod := range pods.Items { - um := users.NewManagerExec(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), "127.0.0.1") + um := users.NewManager(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), "127.0.0.1") - err = um.UpdateProxyUserExec(ctx, user) + err = um.UpdateProxyUser(ctx, user) if err != nil { return errors.Wrap(err, "update proxy users") } @@ -1128,7 +1128,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(ctx context.Context, cr return nil } -func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, user *users.SysUser, um *users.ManagerExec) error { +func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSysSecretObj *corev1.Secret, user *users.SysUser, um *users.Manager) error { log := logf.FromContext(ctx) annotationName := "grant-for-1.10.0-system-privilege" @@ -1136,7 +1136,7 @@ func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Con return nil } - if err := um.Update1100SystemUserPrivilegeExec(ctx, user); err != nil { + if err := um.Update1100SystemUserPrivilege(ctx, user); err != nil { return errors.Wrap(err, "grant system user privilege") } @@ -1154,7 +1154,7 @@ func (r *ReconcilePerconaXtraDBCluster) grantSystemUserPrivilege(ctx context.Con return nil } -func (r *ReconcilePerconaXtraDBCluster) getUserManager(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets *corev1.Secret) (*users.ManagerExec, error) { +func (r *ReconcilePerconaXtraDBCluster) getUserManager(ctx context.Context, cr *api.PerconaXtraDBCluster, secrets *corev1.Secret) (*users.Manager, error) { pxcUser := users.Root pxcPass := string(secrets.Data[users.Root]) if _, ok := secrets.Data[users.Operator]; ok { @@ -1168,7 +1168,7 @@ func (r *ReconcilePerconaXtraDBCluster) getUserManager(ctx context.Context, cr * } host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace - return users.NewManagerExec(&primary, r.clientcmd, pxcUser, pxcPass, host), nil + return users.NewManager(&primary, r.clientcmd, pxcUser, pxcPass, host), nil } func (r *ReconcilePerconaXtraDBCluster) updateUserPassExpirationPolicy(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSecrets *corev1.Secret, user *users.SysUser) error { @@ -1185,7 +1185,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassExpirationPolicy(ctx conte return err } - if err := um.UpdatePassExpirationPolicyExec(ctx, user); err != nil { + if err := um.UpdatePassExpirationPolicy(ctx, user); err != nil { return errors.Wrapf(err, "update %s user password expiration policy", user.Name) } diff --git a/pkg/controller/pxc/users_without_dp.go b/pkg/controller/pxc/users_without_dp.go index b00c2e49e2..d3d838296b 100644 --- a/pkg/controller/pxc/users_without_dp.go +++ b/pkg/controller/pxc/users_without_dp.go @@ -484,7 +484,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateUserPassWithoutDP(ctx context.Cont return err } - err = um.UpdateUserPassWithoutDPExec(ctx, user) + err = um.UpdateUserPassWithoutDP(ctx, user) if err != nil { return errors.Wrap(err, "update user pass") } diff --git a/pkg/controller/pxc/version.go b/pkg/controller/pxc/version.go index b1f48d4cf4..f048cf0451 100644 --- a/pkg/controller/pxc/version.go +++ b/pkg/controller/pxc/version.go @@ -300,9 +300,9 @@ func (r *ReconcilePerconaXtraDBCluster) mysqlVersion(ctx context.Context, cr *ap if err != nil { return "", errors.Wrap(err, "failed to get operator password") } - database := queries.NewExec(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) + database := queries.NewPXC(&pod, r.clientcmd, users.Operator, pass, pod.Name+"."+cr.Name+"-pxc."+cr.Namespace) - version, err := database.VersionExec(ctx) + version, err := database.Version(ctx) if err != nil { log.Error(err, "failed to get pxc version") continue diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index 59c5aaa817..d188b66740 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -1,17 +1,20 @@ package queries import ( + "bytes" "context" "database/sql" + "encoding/csv" "fmt" + "regexp" "strings" "github.com/pkg/errors" - "github.com/go-sql-driver/mysql" + "github.com/gocarina/gocsv" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-xtradb-cluster-operator/clientcmd" ) type ReplicationStatus int8 @@ -31,10 +34,6 @@ const ( // https://github.com/percona/percona-docker/blob/pxc-operator-1.3.0/proxysql/dockerdir/etc/proxysql-admin.cnf#L23 const writerID = 11 -type Database struct { - db *sql.DB -} - type ReplicationConfig struct { Source ReplicationChannelSource SourceRetryCount uint @@ -53,51 +52,77 @@ type ReplicationChannelSource struct { var ErrNotFound = errors.New("not found") -func New(client client.Client, namespace, secretName, user, host string, port int32, timeout int32) (Database, error) { - secretObj := corev1.Secret{} - err := client.Get(context.TODO(), - types.NamespacedName{ - Namespace: namespace, - Name: secretName, - }, - &secretObj, - ) +var sensitiveRegexp = regexp.MustCompile(":.*@") + +type Database struct { + client *clientcmd.Client + pod *corev1.Pod + container string + cmd []string +} + +// NewPXC creates a new Database instance for a given PXC pod +func NewPXC(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *Database { + cmd := []string{"mysql", "--database", "mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", host, "-e"} + return &Database{client: cliCmd, pod: pod, container: "pxc", cmd: cmd} +} + +// NewProxySQL creates a new Database instance for a given ProxySQL pod +func NewProxySQL(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *Database { + cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-P", "6032", "-e"} + return &Database{client: cliCmd, pod: pod, container: "proxysql", cmd: cmd} +} + +// NewHAProxy creates a new Database instance for a given HAProxy pod +func NewHAProxy(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *Database { + cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-e"} + return &Database{client: cliCmd, pod: pod, container: "haproxy", cmd: cmd} +} + +func (d *Database) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := append(d.cmd, stm) + err := d.client.Exec(d.pod, d.container, cmd, nil, stdout, stderr, false) if err != nil { - return Database{}, err + sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") + serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") + return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) } - timeoutStr := fmt.Sprintf("%ds", timeout) - config := mysql.NewConfig() - config.User = user - config.Passwd = string(secretObj.Data[user]) - config.Net = "tcp" - config.DBName = "mysql" - config.Addr = fmt.Sprintf("%s:%d", host, port) - config.Params = map[string]string{ - "interpolateParams": "true", - "timeout": timeoutStr, - "readTimeout": timeoutStr, - "writeTimeout": timeoutStr, - "tls": "preferred", + if strings.Contains(stderr.String(), "ERROR") { + return fmt.Errorf("sql error: %s", stderr) } - db, err := sql.Open("mysql", config.FormatDSN()) + return nil +} + +func (d *Database) query(ctx context.Context, query string, out interface{}) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, query, &outb, &errb) if err != nil { - return Database{}, err + return err } - err = db.Ping() - if err != nil { - return Database{}, err + if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { + return sql.ErrNoRows } - return Database{ - db: db, - }, nil + csv := csv.NewReader(bytes.NewReader(outb.Bytes())) + csv.Comma = '\t' + + if err = gocsv.UnmarshalCSV(csv, out); err != nil { + return err + } + + return nil } -func (p *Database) CurrentReplicationChannels() ([]string, error) { - rows, err := p.db.Query(`SELECT DISTINCT(Channel_name) from replication_asynchronous_connection_failover`) +func (d *Database) CurrentReplicationChannels(ctx context.Context) ([]string, error) { + rows := []*struct { + Name string `csv:"name"` + }{} + + q := `SELECT DISTINCT(Channel_name) as name from replication_asynchronous_connection_failover` + err := d.query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil @@ -105,151 +130,133 @@ func (p *Database) CurrentReplicationChannels() ([]string, error) { return nil, errors.Wrap(err, "select current replication channels") } - defer rows.Close() - result := make([]string, 0) - for rows.Next() { - src := "" - err = rows.Scan(&src) - if err != nil { - return nil, errors.Wrap(err, "scan channel name") - } - result = append(result, src) + for _, row := range rows { + result = append(result, row.Name) } return result, nil } -func (p *Database) ChangeChannelPassword(channel, password string) error { - tx, err := p.db.Begin() - if err != nil { - return errors.Wrap(err, "start transaction for updating channel password") - } - _, err = tx.Exec(`STOP REPLICA IO_THREAD FOR CHANNEL ?`, channel) - if err != nil { - errT := tx.Rollback() - if errT != nil { - return errors.Wrapf(err, "rollback STOP REPLICA IO_THREAD FOR CHANNEL %s", channel) - } - return errors.Wrapf(err, "stop replication IO thread for channel %s", channel) - } - _, err = tx.Exec(`CHANGE REPLICATION SOURCE TO SOURCE_PASSWORD=? FOR CHANNEL ?`, password, channel) +func (d *Database) ChangeChannelPassword(ctx context.Context, channel, password string) error { + var errb, outb bytes.Buffer + + q := fmt.Sprintf(`START TRANSACTION; + STOP REPLICA IO_THREAD FOR CHANNEL %s; + CHANGE REPLICATION SOURCE TO SOURCE_PASSWORD='%s' FOR CHANNEL %s; + START REPLICA IO_THREAD FOR CHANNEL %s; + COMMIT; + `, channel, password, channel, channel) + + err := d.exec(ctx, q, &outb, &errb) if err != nil { - errT := tx.Rollback() - if errT != nil { - return errors.Wrapf(err, "rollback CHANGE SOURCE_PASSWORD FOR CHANNEL %s", channel) - } - return errors.Wrapf(err, "change master password for channel %s", channel) + return errors.Wrap(err, "change channel password") } - _, err = tx.Exec(`START REPLICA IO_THREAD FOR CHANNEL ?`, channel) - if err != nil { - errT := tx.Rollback() - if errT != nil { - return errors.Wrapf(err, "rollback START REPLICA IO_THREAD FOR CHANNEL %s", channel) - } - return errors.Wrapf(err, "start io thread for channel %s", channel) - } - return tx.Commit() + + return nil } -func (p *Database) ReplicationStatus(channel string) (ReplicationStatus, error) { - rows, err := p.db.Query(`SHOW REPLICA STATUS FOR CHANNEL ?`, channel) +func (d *Database) ReplicationStatus(ctx context.Context, channel string) (ReplicationStatus, error) { + rows := []*struct { + IORunning string `csv:"Replica_IO_Running"` + SQLRunning string `csv:"Replica_SQL_Running"` + LastErrNo int `csv:"Last_Errno"` + }{} + + q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL %s", channel) + err := d.query(ctx, q, &rows) if err != nil { - if strings.HasSuffix(err.Error(), "does not exist.") || errors.Is(err, sql.ErrNoRows) { + if errors.Is(err, sql.ErrNoRows) { return ReplicationStatusNotInitiated, nil } - return ReplicationStatusError, errors.Wrap(err, "get current replica status") - } - - defer rows.Close() - cols, err := rows.Columns() - if err != nil { - return ReplicationStatusError, errors.Wrap(err, "get columns") - } - vals := make([]interface{}, len(cols)) - for i := range cols { - vals[i] = new(sql.RawBytes) + return ReplicationStatusError, errors.Wrap(err, "select replication status") } - for rows.Next() { - err = rows.Scan(vals...) - if err != nil { - return ReplicationStatusError, errors.Wrap(err, "scan replication status") - } - } + ioRunning := rows[0].IORunning == "Yes" + sqlRunning := rows[0].SQLRunning == "Yes" + lastErrNo := rows[0].LastErrNo - IORunning := string(*vals[10].(*sql.RawBytes)) - SQLRunning := string(*vals[11].(*sql.RawBytes)) - LastErrNo := string(*vals[18].(*sql.RawBytes)) - if IORunning == "Yes" && SQLRunning == "Yes" { + if ioRunning && sqlRunning { return ReplicationStatusActive, nil } - if IORunning == "No" && SQLRunning == "No" && LastErrNo == "0" { + if !ioRunning && !sqlRunning && lastErrNo == 0 { return ReplicationStatusNotInitiated, nil } return ReplicationStatusError, nil } -func (p *Database) StopAllReplication() error { - _, err := p.db.Exec("STOP REPLICA") - return errors.Wrap(err, "failed to stop replication") +func (d *Database) StopAllReplication(ctx context.Context) error { + var errb, outb bytes.Buffer + if err := d.exec(ctx, "STOP REPLICA", &outb, &errb); err != nil { + return errors.Wrap(err, "failed to stop replication") + } + return nil } -func (p *Database) AddReplicationSource(name, host string, port, weight int) error { - _, err := p.db.Exec("SELECT asynchronous_connection_failover_add_source(?, ?, ?, null, ?)", name, host, port, weight) - return errors.Wrap(err, "add replication source") +func (d *Database) AddReplicationSource(ctx context.Context, name, host string, port, weight int) error { + var errb, outb bytes.Buffer + q := fmt.Sprintf("SELECT asynchronous_connection_failover_add_source('%s', '%s', %d, null, %d)", name, host, port, weight) + err := d.exec(ctx, q, &outb, &errb) + if err != nil { + return errors.Wrap(err, "add replication source") + } + return nil } -func (p *Database) ReplicationChannelSources(channelName string) ([]ReplicationChannelSource, error) { - rows, err := p.db.Query(` - SELECT host, - port, - weight - FROM replication_asynchronous_connection_failover - WHERE channel_name = ? - `, channelName) +func (d *Database) ReplicationChannelSources(ctx context.Context, channelName string) ([]ReplicationChannelSource, error) { + rows := []*struct { + Host string `csv:"host"` + Port int `csv:"port"` + Wieght int `csv:"weight"` + }{} + + q := fmt.Sprintf("SELECT host, port, weight FROM replication_asynchronous_connection_failover WHERE Channel_name = '%s'", channelName) + err := d.query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound } return nil, errors.Wrap(err, "get replication channels") } - defer rows.Close() + result := make([]ReplicationChannelSource, 0) - for rows.Next() { - r := ReplicationChannelSource{} - err = rows.Scan(&r.Host, &r.Port, &r.Weight) - if err != nil { - return nil, errors.Wrap(err, "read replication channel info") - } - result = append(result, r) + for _, row := range rows { + result = append(result, ReplicationChannelSource{Host: row.Host, Port: row.Port, Weight: row.Wieght}) } return result, nil } -func (p *Database) StopReplication(name string) error { - _, err := p.db.Exec("STOP REPLICA FOR CHANNEL ?", name) +func (d *Database) StopReplication(ctx context.Context, name string) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, fmt.Sprintf("STOP REPLICA FOR CHANNEL '%s'", name), &outb, &errb) return errors.Wrap(err, "stop replication for channel "+name) } -func (p *Database) EnableReadonly() error { - _, err := p.db.Exec("SET GLOBAL READ_ONLY=1") +func (d *Database) EnableReadonly(ctx context.Context) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, "SET GLOBAL READ_ONLY=1", &outb, &errb) return errors.Wrap(err, "set global read_only param to 1") } -func (p *Database) DisableReadonly() error { - _, err := p.db.Exec("SET GLOBAL READ_ONLY=0") +func (d *Database) DisableReadonly(ctx context.Context) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, "SET GLOBAL READ_ONLY=0", &outb, &errb) return errors.Wrap(err, "set global read_only param to 0") } -func (p *Database) IsReadonly() (bool, error) { - readonly := 0 - err := p.db.QueryRow("select @@read_only").Scan(&readonly) - return readonly == 1, errors.Wrap(err, "select global read_only param") +func (p *Database) IsReadonlyExec(ctx context.Context) (bool, error) { + rows := []*struct { + ReadOnly int `csv:"readOnly"` + }{} + err := p.query(ctx, "select @@read_only as readOnly", &rows) + if err != nil { + return false, errors.Wrap(err, "select global read_only param") + } + return rows[0].ReadOnly == 1, nil } -func (p *Database) StartReplication(replicaPass string, config ReplicationConfig) error { +func (d *Database) StartReplication(ctx context.Context, replicaPass string, config ReplicationConfig) error { var ca string var ssl int if config.SSL { @@ -262,37 +269,51 @@ func (p *Database) StartReplication(replicaPass string, config ReplicationConfig sslVerify = 1 } - _, err := p.db.Exec(` - CHANGE REPLICATION SOURCE TO - SOURCE_USER='replication', - SOURCE_PASSWORD=?, - SOURCE_HOST=?, - SOURCE_PORT=?, - SOURCE_CONNECTION_AUTO_FAILOVER=1, - SOURCE_AUTO_POSITION=1, - SOURCE_RETRY_COUNT=?, - SOURCE_CONNECT_RETRY=?, - SOURCE_SSL=?, - SOURCE_SSL_CA=?, - SOURCE_SSL_VERIFY_SERVER_CERT=? - FOR CHANNEL ? -`, replicaPass, config.Source.Host, config.Source.Port, config.SourceRetryCount, config.SourceConnectRetry, ssl, ca, sslVerify, config.Source.Name) + q := fmt.Sprintf(` + CHANGE REPLICATION SOURCE TO + SOURCE_USER='replication', + SOURCE_PASSWORD='%s', + SOURCE_HOST='%s', + SOURCE_PORT=%d, + SOURCE_CONNECTION_AUTO_FAILOVER=1, + SOURCE_AUTO_POSITION=1, + SOURCE_RETRY_COUNT=%d, + SOURCE_CONNECT_RETRY=%d, + SOURCE_SSL=%d, + SOURCE_SSL_CA='%s', + SOURCE_SSL_VERIFY_SERVER_CERT=%d + FOR CHANNEL '%s' + `, replicaPass, config.Source.Host, config.Source.Port, config.SourceRetryCount, config.SourceConnectRetry, ssl, ca, sslVerify, config.Source.Name) + + var errb, outb bytes.Buffer + err := d.exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrapf(err, "change source for channel %s", config.Source.Name) } - _, err = p.db.Exec(`START REPLICA FOR CHANNEL ?`, config.Source.Name) + outb.Reset() + errb.Reset() + err = d.exec(ctx, fmt.Sprintf(`START REPLICA FOR CHANNEL '%s'`, config.Source.Name), &outb, &errb) return errors.Wrapf(err, "start replica for source %s", config.Source.Name) } -func (p *Database) DeleteReplicationSource(name, host string, port int) error { - _, err := p.db.Exec("SELECT asynchronous_connection_failover_delete_source(?, ?, ?, null)", name, host, port) +func (d *Database) DeleteReplicationSource(ctx context.Context, name, host string, port int) error { + var errb, outb bytes.Buffer + q := fmt.Sprintf("SELECT asynchronous_connection_failover_delete_source('%s', '%s', %d, null)", name, host, port) + err := d.exec(ctx, q, &outb, &errb) return errors.Wrap(err, "delete replication source "+name) } -func (p *Database) ProxySQLInstanceStatus(host string) ([]string, error) { - rows, err := p.db.Query("SELECT status FROM mysql_servers WHERE hostname LIKE ?;", host+"%") +func (d *Database) ProxySQLInstanceStatus(ctx context.Context, host string) ([]string, error) { + + rows := []*struct { + Status string `csv:"status"` + }{} + + q := fmt.Sprintf("SELECT status FROM proxysql_servers WHERE hostname LIKE '%s%%'", host) + + err := d.query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound @@ -301,42 +322,46 @@ func (p *Database) ProxySQLInstanceStatus(host string) ([]string, error) { } statuses := []string{} - for rows.Next() { - var status string - - err := rows.Scan(&status) - if err != nil { - return nil, err - } - - statuses = append(statuses, status) + for _, row := range rows { + statuses = append(statuses, row.Status) } return statuses, nil } -func (p *Database) PresentInHostgroups(host string) (bool, error) { +func (d *Database) PresentInHostgroups(ctx context.Context, host string) (bool, error) { hostgroups := []string{WriterHostgroup, ReaderHostgroup} - query := fmt.Sprintf(`SELECT COUNT(*) FROM mysql_servers + + rows := []*struct { + Count int `csv:"count"` + }{} + + q := fmt.Sprintf(` + SELECT COUNT(*) FROM mysql_servers INNER JOIN mysql_galera_hostgroups ON hostgroup_id IN (%s) - WHERE hostname LIKE ? GROUP BY hostname`, strings.Join(hostgroups, ",")) - var count int - err := p.db.QueryRow(query, host+"%").Scan(&count) + WHERE hostname LIKE '%s' GROUP BY hostname`, strings.Join(hostgroups, ","), host+"%") + + err := d.query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return false, ErrNotFound } return false, err } - if count != len(hostgroups) { + if rows[0].Count != len(hostgroups) { return false, nil } return true, nil } -func (p *Database) PrimaryHost() (string, error) { - var host string - err := p.db.QueryRow("SELECT hostname FROM runtime_mysql_servers WHERE hostgroup_id = ?", writerID).Scan(&host) +func (d *Database) PrimaryHost(ctx context.Context) (string, error) { + rows := []*struct { + Hostname string `csv:"host"` + }{} + + q := fmt.Sprintf("SELECT hostname as host FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) + + err := d.query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return "", ErrNotFound @@ -344,12 +369,15 @@ func (p *Database) PrimaryHost() (string, error) { return "", err } - return host, nil + return rows[0].Hostname, nil } -func (p *Database) Hostname() (string, error) { - var hostname string - err := p.db.QueryRow("SELECT @@hostname hostname").Scan(&hostname) +func (d *Database) Hostname(ctx context.Context) (string, error) { + rows := []*struct { + Hostname string `csv:"hostname"` + }{} + + err := d.query(ctx, "SELECT @@hostname hostname", &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return "", ErrNotFound @@ -357,14 +385,16 @@ func (p *Database) Hostname() (string, error) { return "", err } - return hostname, nil + return rows[0].Hostname, nil } -func (p *Database) WsrepLocalStateComment() (string, error) { - var variable_name string - var value string +func (d *Database) WsrepLocalStateComment(ctx context.Context) (string, error) { + rows := []*struct { + VariableName string `csv:"Variable_name"` + Value string `csv:"Value"` + }{} - err := p.db.QueryRow("SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'").Scan(&variable_name, &value) + err := d.query(ctx, "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'", &rows) if err != nil { if err == sql.ErrNoRows { return "", fmt.Errorf("variable was not found") @@ -372,13 +402,15 @@ func (p *Database) WsrepLocalStateComment() (string, error) { return "", err } - return value, nil + return rows[0].Value, nil } -func (p *Database) Version() (string, error) { - var version string +func (d *Database) Version(ctx context.Context) (string, error) { + rows := []*struct { + Version string `csv:"version"` + }{} - err := p.db.QueryRow("select @@VERSION;").Scan(&version) + err := d.query(ctx, "select @@VERSION as version;", &rows) if err != nil { if err == sql.ErrNoRows { return "", fmt.Errorf("variable was not found") @@ -386,9 +418,5 @@ func (p *Database) Version() (string, error) { return "", err } - return version, nil -} - -func (p *Database) Close() error { - return p.db.Close() + return rows[0].Version, nil } diff --git a/pkg/pxc/queries/queries_exec.go b/pkg/pxc/queries/queries_exec.go deleted file mode 100644 index 369126641e..0000000000 --- a/pkg/pxc/queries/queries_exec.go +++ /dev/null @@ -1,387 +0,0 @@ -package queries - -import ( - "bytes" - "context" - "database/sql" - "encoding/csv" - "fmt" - "regexp" - "strings" - - "github.com/pkg/errors" - - "github.com/gocarina/gocsv" - corev1 "k8s.io/api/core/v1" - - "github.com/percona/percona-xtradb-cluster-operator/clientcmd" -) - -var sensitiveRegexp = regexp.MustCompile(":.*@") - -type DatabaseExec struct { - client *clientcmd.Client - pod *corev1.Pod - container string - cmd []string -} - -// NewExec creates a new DatabaseExec instance for a given PXC pod -func NewExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *DatabaseExec { - cmd := []string{"mysql", "--database", "mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", host, "-e"} - return &DatabaseExec{client: cliCmd, pod: pod, container: "pxc", cmd: cmd} -} - -// NewProxySQL creates a new DatabaseExec instance for a given ProxySQL pod -func NewProxySQL(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *DatabaseExec { - cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-P", "6032", "-e"} - return &DatabaseExec{client: cliCmd, pod: pod, container: "proxysql", cmd: cmd} -} - -// NewHAProxy creates a new DatabaseExec instance for a given HAProxy pod -func NewHAProxy(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *DatabaseExec { - cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-e"} - return &DatabaseExec{client: cliCmd, pod: pod, container: "haproxy", cmd: cmd} -} - -func (d *DatabaseExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := append(d.cmd, stm) - err := d.client.Exec(d.pod, d.container, cmd, nil, stdout, stderr, false) - if err != nil { - sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") - serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") - return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) - } - - if strings.Contains(stderr.String(), "ERROR") { - return fmt.Errorf("sql error: %s", stderr) - } - - return nil -} - -func (d *DatabaseExec) query(ctx context.Context, query string, out interface{}) error { - var errb, outb bytes.Buffer - err := d.exec(ctx, query, &outb, &errb) - if err != nil { - return err - } - - if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { - return sql.ErrNoRows - } - - csv := csv.NewReader(bytes.NewReader(outb.Bytes())) - csv.Comma = '\t' - - if err = gocsv.UnmarshalCSV(csv, out); err != nil { - return err - } - - return nil -} - -func (p *DatabaseExec) CurrentReplicationChannelsExec(ctx context.Context) ([]string, error) { - rows := []*struct { - Name string `csv:"name"` - }{} - - q := `SELECT DISTINCT(Channel_name) as name from replication_asynchronous_connection_failover` - err := p.query(ctx, q, &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, nil - } - return nil, errors.Wrap(err, "select current replication channels") - } - - result := make([]string, 0) - for _, row := range rows { - result = append(result, row.Name) - } - return result, nil -} - -func (p *DatabaseExec) ChangeChannelPasswordExec(ctx context.Context, channel, password string) error { - var errb, outb bytes.Buffer - - q := fmt.Sprintf(`START TRANSACTION; - STOP REPLICA IO_THREAD FOR CHANNEL %s; - CHANGE REPLICATION SOURCE TO SOURCE_PASSWORD='%s' FOR CHANNEL %s; - START REPLICA IO_THREAD FOR CHANNEL %s; - COMMIT; - `, channel, password, channel, channel) - - err := p.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "change channel password") - } - - return nil -} - -func (p *DatabaseExec) ReplicationStatusExec(ctx context.Context, channel string) (ReplicationStatus, error) { - rows := []*struct { - IORunning string `csv:"Replica_IO_Running"` - SQLRunning string `csv:"Replica_SQL_Running"` - LastErrNo int `csv:"Last_Errno"` - }{} - - q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL %s", channel) - err := p.query(ctx, q, &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return ReplicationStatusNotInitiated, nil - } - return ReplicationStatusError, errors.Wrap(err, "select replication status") - } - - ioRunning := rows[0].IORunning == "Yes" - sqlRunning := rows[0].SQLRunning == "Yes" - lastErrNo := rows[0].LastErrNo - - if ioRunning && sqlRunning { - return ReplicationStatusActive, nil - } - - if !ioRunning && !sqlRunning && lastErrNo == 0 { - return ReplicationStatusNotInitiated, nil - } - - return ReplicationStatusError, nil -} - -func (p *DatabaseExec) StopAllReplicationExec(ctx context.Context) error { - var errb, outb bytes.Buffer - if err := p.exec(ctx, "STOP REPLICA", &outb, &errb); err != nil { - return errors.Wrap(err, "failed to stop replication") - } - return nil -} - -func (p *DatabaseExec) AddReplicationSourceExec(ctx context.Context, name, host string, port, weight int) error { - var errb, outb bytes.Buffer - q := fmt.Sprintf("SELECT asynchronous_connection_failover_add_source('%s', '%s', %d, null, %d)", name, host, port, weight) - err := p.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "add replication source") - } - return nil -} - -func (p *DatabaseExec) ReplicationChannelSourcesExec(ctx context.Context, channelName string) ([]ReplicationChannelSource, error) { - rows := []*struct { - Host string `csv:"host"` - Port int `csv:"port"` - Wieght int `csv:"weight"` - }{} - - q := fmt.Sprintf("SELECT host, port, weight FROM replication_asynchronous_connection_failover WHERE Channel_name = '%s'", channelName) - err := p.query(ctx, q, &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, ErrNotFound - } - return nil, errors.Wrap(err, "get replication channels") - } - - result := make([]ReplicationChannelSource, 0) - for _, row := range rows { - result = append(result, ReplicationChannelSource{Host: row.Host, Port: row.Port, Weight: row.Wieght}) - } - return result, nil -} - -func (p *DatabaseExec) StopReplicationExec(ctx context.Context, name string) error { - var errb, outb bytes.Buffer - err := p.exec(ctx, fmt.Sprintf("STOP REPLICA FOR CHANNEL '%s'", name), &outb, &errb) - return errors.Wrap(err, "stop replication for channel "+name) -} - -func (p *DatabaseExec) EnableReadonlyExec(ctx context.Context) error { - var errb, outb bytes.Buffer - err := p.exec(ctx, "SET GLOBAL READ_ONLY=1", &outb, &errb) - return errors.Wrap(err, "set global read_only param to 1") -} - -func (p *DatabaseExec) DisableReadonlyExec(ctx context.Context) error { - var errb, outb bytes.Buffer - err := p.exec(ctx, "SET GLOBAL READ_ONLY=0", &outb, &errb) - return errors.Wrap(err, "set global read_only param to 0") -} - -func (p *DatabaseExec) IsReadonlyExec(ctx context.Context) (bool, error) { - rows := []*struct { - ReadOnly int `csv:"readOnly"` - }{} - err := p.query(ctx, "select @@read_only as readOnly", &rows) - if err != nil { - return false, errors.Wrap(err, "select global read_only param") - } - return rows[0].ReadOnly == 1, nil -} - -func (p *DatabaseExec) StartReplicationExec(ctx context.Context, replicaPass string, config ReplicationConfig) error { - var ca string - var ssl int - if config.SSL { - ssl = 1 - ca = config.CA - } - - var sslVerify int - if !config.SSLSkipVerify { - sslVerify = 1 - } - - q := fmt.Sprintf(` - CHANGE REPLICATION SOURCE TO - SOURCE_USER='replication', - SOURCE_PASSWORD='%s', - SOURCE_HOST='%s', - SOURCE_PORT=%d, - SOURCE_CONNECTION_AUTO_FAILOVER=1, - SOURCE_AUTO_POSITION=1, - SOURCE_RETRY_COUNT=%d, - SOURCE_CONNECT_RETRY=%d, - SOURCE_SSL=%d, - SOURCE_SSL_CA='%s', - SOURCE_SSL_VERIFY_SERVER_CERT=%d - FOR CHANNEL '%s' - `, replicaPass, config.Source.Host, config.Source.Port, config.SourceRetryCount, config.SourceConnectRetry, ssl, ca, sslVerify, config.Source.Name) - - var errb, outb bytes.Buffer - err := p.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrapf(err, "change source for channel %s", config.Source.Name) - } - - outb.Reset() - errb.Reset() - err = p.exec(ctx, fmt.Sprintf(`START REPLICA FOR CHANNEL '%s'`, config.Source.Name), &outb, &errb) - return errors.Wrapf(err, "start replica for source %s", config.Source.Name) - -} - -func (p *DatabaseExec) DeleteReplicationSourceExec(ctx context.Context, name, host string, port int) error { - var errb, outb bytes.Buffer - q := fmt.Sprintf("SELECT asynchronous_connection_failover_delete_source('%s', '%s', %d, null)", name, host, port) - err := p.exec(ctx, q, &outb, &errb) - return errors.Wrap(err, "delete replication source "+name) -} - -func (p *DatabaseExec) ProxySQLInstanceStatusExec(ctx context.Context, host string) ([]string, error) { - - rows := []*struct { - Status string `csv:"status"` - }{} - - q := fmt.Sprintf("SELECT status FROM proxysql_servers WHERE hostname LIKE '%s%%'", host) - - err := p.query(ctx, q, &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, ErrNotFound - } - return nil, err - } - - statuses := []string{} - for _, row := range rows { - statuses = append(statuses, row.Status) - } - - return statuses, nil -} - -func (p *DatabaseExec) PresentInHostgroupsExec(ctx context.Context, host string) (bool, error) { - hostgroups := []string{WriterHostgroup, ReaderHostgroup} - - rows := []*struct { - Count int `csv:"count"` - }{} - - q := fmt.Sprintf(` - SELECT COUNT(*) FROM mysql_servers - INNER JOIN mysql_galera_hostgroups ON hostgroup_id IN (%s) - WHERE hostname LIKE '%s' GROUP BY hostname`, strings.Join(hostgroups, ","), host+"%") - - err := p.query(ctx, q, &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return false, ErrNotFound - } - return false, err - } - if rows[0].Count != len(hostgroups) { - return false, nil - } - return true, nil -} - -func (p *DatabaseExec) PrimaryHostExec(ctx context.Context) (string, error) { - rows := []*struct { - Hostname string `csv:"host"` - }{} - - q := fmt.Sprintf("SELECT hostname as host FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) - - err := p.query(ctx, q, &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return "", ErrNotFound - } - return "", err - } - - return rows[0].Hostname, nil -} - -func (p *DatabaseExec) HostnameExec(ctx context.Context) (string, error) { - rows := []*struct { - Hostname string `csv:"hostname"` - }{} - - err := p.query(ctx, "SELECT @@hostname hostname", &rows) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return "", ErrNotFound - } - return "", err - } - - return rows[0].Hostname, nil -} - -func (p *DatabaseExec) WsrepLocalStateCommentExec(ctx context.Context) (string, error) { - rows := []*struct { - VariableName string `csv:"Variable_name"` - Value string `csv:"Value"` - }{} - - err := p.query(ctx, "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'", &rows) - if err != nil { - if err == sql.ErrNoRows { - return "", fmt.Errorf("variable was not found") - } - return "", err - } - - return rows[0].Value, nil -} - -func (p *DatabaseExec) VersionExec(ctx context.Context) (string, error) { - rows := []*struct { - Version string `csv:"version"` - }{} - - err := p.query(ctx, "select @@VERSION as version;", &rows) - if err != nil { - if err == sql.ErrNoRows { - return "", fmt.Errorf("variable was not found") - } - return "", err - } - - return rows[0].Version, nil -} diff --git a/pkg/pxc/users/users.go b/pkg/pxc/users/users.go index c41a4d5eed..e726616167 100644 --- a/pkg/pxc/users/users.go +++ b/pkg/pxc/users/users.go @@ -1,11 +1,20 @@ package users import ( + "bytes" + "context" "database/sql" + "encoding/csv" "fmt" + "regexp" + "strings" - "github.com/go-sql-driver/mysql" "github.com/pkg/errors" + + "github.com/gocarina/gocsv" + corev1 "k8s.io/api/core/v1" + + "github.com/percona/percona-xtradb-cluster-operator/clientcmd" ) const ( @@ -24,55 +33,76 @@ var UserNames = []string{Root, Operator, Monitor, Xtrabackup, Replication, ProxyAdmin, Clustercheck, PMMServer, PMMServerKey} -type Manager struct { - db *sql.DB -} - type SysUser struct { Name string `yaml:"username"` Pass string `yaml:"password"` Hosts []string `yaml:"hosts"` } -func NewManager(addr string, user, pass string, timeout int32) (Manager, error) { - var um Manager - - timeoutStr := fmt.Sprintf("%ds", timeout) - config := mysql.NewConfig() - config.User = user - config.Passwd = pass - config.Net = "tcp" - config.Addr = addr - config.DBName = "mysql" - config.Params = map[string]string{ - "interpolateParams": "true", - "timeout": timeoutStr, - "readTimeout": timeoutStr, - "writeTimeout": timeoutStr, - "tls": "preferred", - } +var sensitiveRegexp = regexp.MustCompile(":.*@") - mysqlDB, err := sql.Open("mysql", config.FormatDSN()) +type Manager struct { + client *clientcmd.Client + pod *corev1.Pod + user string + pass string + host string +} + +func NewManager(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *Manager { + return &Manager{client: cliCmd, pod: pod, user: user, pass: pass, host: host} +} + +func (d *Manager) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} + + err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) if err != nil { - return um, errors.Wrap(err, "cannot connect to any host") + sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") + serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") + return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) } - um.db = mysqlDB + if strings.Contains(stderr.String(), "ERROR") { + return fmt.Errorf("sql error: %s", stderr) + } - return um, nil + return nil } -func (u *Manager) Close() error { - return u.db.Close() +func (d *Manager) query(ctx context.Context, query string, out interface{}) error { + var errb, outb bytes.Buffer + err := d.exec(ctx, query, &outb, &errb) + if err != nil { + return err + } + + if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { + return sql.ErrNoRows + } + + csv := csv.NewReader(bytes.NewReader(outb.Bytes())) + csv.Comma = '\t' + + if err = gocsv.UnmarshalCSV(csv, out); err != nil { + return err + } + + return nil } -func (u *Manager) CreateOperatorUser(pass string) error { - _, err := u.db.Exec("CREATE USER IF NOT EXISTS 'operator'@'%' IDENTIFIED BY ?", pass) +func (u *Manager) CreateOperatorUser(ctx context.Context, pass string) error { + var errb, outb bytes.Buffer + + q := fmt.Sprintf("CREATE USER IF NOT EXISTS 'operator'@'%%' IDENTIFIED BY '%s'", pass) + err := u.exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "create operator user") } - _, err = u.db.Exec("GRANT ALL ON *.* TO 'operator'@'%' WITH GRANT OPTION") + outb.Reset() + errb.Reset() + err = u.exec(ctx, "GRANT ALL ON *.* TO 'operator'@'%' WITH GRANT OPTION", &outb, &errb) if err != nil { return errors.Wrap(err, "grant operator user") } @@ -80,15 +110,17 @@ func (u *Manager) CreateOperatorUser(pass string) error { return nil } -// UpdateUserPassWithoutDP updates user pass without Dual Password +// UpdateUserPassWithoutDPExec updates user pass without Dual Password // feature introduced in MsSQL 8 -func (u *Manager) UpdateUserPassWithoutDP(user *SysUser) error { +func (u *Manager) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser) error { if user == nil { return nil } + var errb, outb bytes.Buffer for _, host := range user.Hosts { - _, err := u.db.Exec("ALTER USER ?@? IDENTIFIED BY ?", user.Name, host, user.Pass) + q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user.Name, host, user.Pass) + err := u.exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update password") } @@ -99,73 +131,48 @@ func (u *Manager) UpdateUserPassWithoutDP(user *SysUser) error { // UpdateUserPass updates user passwords but retains the current password // using Dual Password feature of MySQL 8. -func (m *Manager) UpdateUserPass(user *SysUser) error { +func (m *Manager) UpdateUserPass(ctx context.Context, user *SysUser) error { if user == nil { return nil } - tx, err := m.db.Begin() - if err != nil { - return errors.Wrap(err, "begin transaction") - } - for _, host := range user.Hosts { - _, err = tx.Exec("ALTER USER ?@? IDENTIFIED BY ? RETAIN CURRENT PASSWORD", user.Name, host, user.Pass) + var errb, outb bytes.Buffer + q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s' RETAIN CURRENT PASSWORD", user.Name, host, user.Pass) + err := m.exec(ctx, q, &outb, &errb) if err != nil { - err = errors.Wrap(err, "alter user") - - if errT := tx.Rollback(); errT != nil { - return errors.Wrap(errors.Wrap(errT, "rollback"), err.Error()) - } - return err } } - if err := tx.Commit(); err != nil { - return errors.Wrap(err, "commit transaction") - } - return nil } // DiscardOldPassword discards old passwords of given users -func (m *Manager) DiscardOldPassword(user *SysUser) error { +func (m *Manager) DiscardOldPassword(ctx context.Context, user *SysUser) error { if user == nil { return nil } - tx, err := m.db.Begin() - if err != nil { - return errors.Wrap(err, "begin transaction") - } - for _, host := range user.Hosts { - _, err = tx.Exec("ALTER USER ?@? DISCARD OLD PASSWORD", user.Name, host) + var errb, outb bytes.Buffer + q := fmt.Sprintf("ALTER USER '%s'@'%s' DISCARD OLD PASSWORD", user.Name, host) + err := m.exec(ctx, q, &outb, &errb) if err != nil { - err = errors.Wrap(err, "alter user") - - if errT := tx.Rollback(); errT != nil { - return errors.Wrap(errors.Wrap(errT, "rollback"), err.Error()) - } - return err } } - if err := tx.Commit(); err != nil { - return errors.Wrap(err, "commit transaction") - } - return nil } -// DiscardOldPassword discards old passwords of given users -func (m *Manager) IsOldPassDiscarded(user *SysUser) (bool, error) { - var attributes sql.NullString - r := m.db.QueryRow("SELECT User_attributes FROM mysql.user WHERE user=?", user.Name) +// IsOldPassDiscarded checks if old password is discarded +func (m *Manager) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bool, error) { + rows := []*struct { + HasAttr int `csv:"has_attr"` + }{} - err := r.Scan(&attributes) + err := m.query(ctx, fmt.Sprintf("SELECT IF(User_attributes IS NULL, TRUE, FALSE) AS has_attr FROM mysql.user WHERE user='%s'", user.Name), &rows) if err != nil { if err == sql.ErrNoRows { return true, nil @@ -173,47 +180,58 @@ func (m *Manager) IsOldPassDiscarded(user *SysUser) (bool, error) { return false, errors.Wrap(err, "select User_attributes field") } - if attributes.Valid { + if rows[0].HasAttr == 0 { return false, nil } return true, nil } -func (u *Manager) UpdateProxyUser(user *SysUser) error { - switch user.Name { - case ProxyAdmin: - _, err := u.db.Exec("UPDATE global_variables SET variable_value=? WHERE variable_name='admin-admin_credentials'", "proxyadmin:"+user.Pass) - if err != nil { - return errors.Wrap(err, "update proxy admin password") - } - _, err = u.db.Exec("UPDATE global_variables SET variable_value=? WHERE variable_name='admin-cluster_password'", user.Pass) +// UpdateProxyUser updates proxy admin and monitor user passwords within ProxySQL +func (e *Manager) UpdateProxyUser(ctx context.Context, user *SysUser) error { + exec := func(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { + cmd := []string{"mysql", fmt.Sprintf("-p%s", e.pass), "-u", string(e.user), "-h", e.host, "-P 6032", "-e", stm} + + err := e.client.Exec(e.pod, "proxysql", cmd, nil, stdout, stderr, false) if err != nil { - return errors.Wrap(err, "update proxy admin password") + sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") + serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") + return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) } - _, err = u.db.Exec("LOAD ADMIN VARIABLES TO RUNTIME") - if err != nil { - return errors.Wrap(err, "load to runtime") + + if strings.Contains(stderr.String(), "ERROR") { + return fmt.Errorf("sql error: %s", stderr) } - _, err = u.db.Exec("SAVE ADMIN VARIABLES TO DISK") + return nil + } + + switch user.Name { + case ProxyAdmin: + q := fmt.Sprintf(` + UPDATE global_variables SET variable_value='%s' WHERE variable_name='admin-admin_credentials'; + UPDATE global_variables SET variable_value='%s' WHERE variable_name='admin-cluster_password'; + LOAD ADMIN VARIABLES TO RUNTIME; + SAVE ADMIN VARIABLES TO DISK; + `, "proxyadmin:"+user.Pass, user.Pass) + + var errb, outb bytes.Buffer + err := exec(ctx, q, &outb, &errb) if err != nil { - return errors.Wrap(err, "save to disk") + return errors.Wrap(err, "update proxy admin password") } case Monitor: - _, err := u.db.Exec("UPDATE global_variables SET variable_value=? WHERE variable_name='mysql-monitor_password'", user.Pass) + q := fmt.Sprintf(` + UPDATE global_variables SET variable_value='%s' WHERE variable_name='mysql-monitor_password'; + LOAD MYSQL VARIABLES TO RUNTIME; + SAVE MYSQL VARIABLES TO DISK; + `, user.Pass) + + var errb, outb bytes.Buffer + err := exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update proxy monitor password") } - _, err = u.db.Exec("LOAD MYSQL VARIABLES TO RUNTIME") - if err != nil { - return errors.Wrap(err, "load to runtime") - } - - _, err = u.db.Exec("SAVE MYSQL VARIABLES TO DISK") - if err != nil { - return errors.Wrap(err, "save to disk") - } } return nil @@ -221,51 +239,48 @@ func (u *Manager) UpdateProxyUser(user *SysUser) error { // Update160MonitorUserGrant grants SERVICE_CONNECTION_ADMIN rights to the monitor user // if pxc version is 8 or more and sets the MAX_USER_CONNECTIONS parameter to 100 (empirically determined) -func (u *Manager) Update160MonitorUserGrant(pass string) (err error) { - - _, err = u.db.Exec("CREATE USER IF NOT EXISTS 'monitor'@'%' IDENTIFIED BY ?", pass) - if err != nil { - return errors.Wrap(err, "create operator user") - } - - _, err = u.db.Exec("/*!80015 GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%' */") - if err != nil { - return errors.Wrapf(err, "grant service_connection to user monitor") - } - - _, err = u.db.Exec("ALTER USER 'monitor'@'%' WITH MAX_USER_CONNECTIONS 100") +func (u *Manager) Update160MonitorUserGrant(ctx context.Context, pass string) (err error) { + q := fmt.Sprintf(` + CREATE USER IF NOT EXISTS 'monitor'@'%%' IDENTIFIED BY '%s'; + /*!80015 GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%' */; + ALTER USER 'monitor'@'%%' WITH MAX_USER_CONNECTIONS 100; + `, pass) + + var errb, outb bytes.Buffer + err = u.exec(ctx, q, &outb, &errb) if err != nil { - return errors.Wrapf(err, "set max connections to user monitor") + return errors.Wrap(err, "update monitor user grants") } return nil } // Update170XtrabackupUser grants all needed rights to the xtrabackup user -func (u *Manager) Update170XtrabackupUser(pass string) (err error) { - - _, err = u.db.Exec("CREATE USER IF NOT EXISTS 'xtrabackup'@'%' IDENTIFIED BY ?", pass) - if err != nil { - return errors.Wrap(err, "create operator user") - } - - _, err = u.db.Exec("GRANT ALL ON *.* TO 'xtrabackup'@'%'") +func (u *Manager) Update170XtrabackupUser(ctx context.Context, pass string) (err error) { + q := fmt.Sprintf(` + CREATE USER IF NOT EXISTS 'xtrabackup'@'%%' IDENTIFIED BY '%s'; + GRANT ALL ON *.* TO 'xtrabackup'@'%%'; + `, pass) + var errb, outb bytes.Buffer + err = u.exec(ctx, q, &outb, &errb) if err != nil { - return errors.Wrapf(err, "grant privileges to user xtrabackup") + return errors.Wrap(err, "update xtrabackup user grants") } return nil } // Update1100SystemUserPrivilege grants system_user privilege for monitor and clustercheck users -func (u *Manager) Update1100SystemUserPrivilege(user *SysUser) (err error) { +func (u *Manager) Update1100SystemUserPrivilege(ctx context.Context, user *SysUser) (err error) { switch user.Name { case Monitor: - if _, err := u.db.Exec("GRANT SYSTEM_USER ON *.* TO 'monitor'@'%'"); err != nil { + var errb, outb bytes.Buffer + if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'monitor'@'%'", &outb, &errb); err != nil { return errors.Wrap(err, "monitor user") } case Clustercheck: - if _, err := u.db.Exec("GRANT SYSTEM_USER ON *.* TO 'clustercheck'@'localhost'"); err != nil { + var errb, outb bytes.Buffer + if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'clustercheck'@'localhost'", &outb, &errb); err != nil { return errors.Wrap(err, "clustercheck user") } } @@ -273,29 +288,30 @@ func (u *Manager) Update1100SystemUserPrivilege(user *SysUser) (err error) { return nil } -func (u *Manager) CreateReplicationUser(password string) error { - - _, err := u.db.Exec("CREATE USER IF NOT EXISTS 'replication'@'%' IDENTIFIED BY ?", password) +func (u *Manager) CreateReplicationUser(ctx context.Context, password string) error { + q := fmt.Sprintf(` + CREATE USER IF NOT EXISTS 'replication'@'%%' IDENTIFIED BY '%s'; + GRANT REPLICATION SLAVE ON *.* to 'replication'@'%%'; + `, password) + var errb, outb bytes.Buffer + err := u.exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "create replication user") } - _, err = u.db.Exec("GRANT REPLICATION SLAVE ON *.* to 'replication'@'%'") - if err != nil { - return errors.Wrap(err, "grant replication user") - } - return nil } // UpdatePassExpirationPolicy sets user password expiration policy to never -func (u *Manager) UpdatePassExpirationPolicy(user *SysUser) error { +func (u *Manager) UpdatePassExpirationPolicy(ctx context.Context, user *SysUser) error { if user == nil { return nil } for _, host := range user.Hosts { - _, err := u.db.Exec("ALTER USER ?@? PASSWORD EXPIRE NEVER", user.Name, host) + var errb, outb bytes.Buffer + q := fmt.Sprintf("ALTER USER '%s'@'%s' PASSWORD EXPIRE NEVER", user.Name, host) + err := u.exec(ctx, q, &outb, &errb) if err != nil { return err } diff --git a/pkg/pxc/users/users_exec.go b/pkg/pxc/users/users_exec.go deleted file mode 100644 index 888b4f607c..0000000000 --- a/pkg/pxc/users/users_exec.go +++ /dev/null @@ -1,298 +0,0 @@ -package users - -import ( - "bytes" - "context" - "database/sql" - "encoding/csv" - "fmt" - "regexp" - "strings" - - "github.com/pkg/errors" - - "github.com/gocarina/gocsv" - corev1 "k8s.io/api/core/v1" - - "github.com/percona/percona-xtradb-cluster-operator/clientcmd" -) - -var sensitiveRegexp = regexp.MustCompile(":.*@") - -type ManagerExec struct { - client *clientcmd.Client - pod *corev1.Pod - user string - pass string - host string -} - -func NewManagerExec(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *ManagerExec { - return &ManagerExec{client: cliCmd, pod: pod, user: user, pass: pass, host: host} -} - -func (d *ManagerExec) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} - - err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) - if err != nil { - sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") - serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") - return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) - } - - if strings.Contains(stderr.String(), "ERROR") { - return fmt.Errorf("sql error: %s", stderr) - } - - return nil -} - -func (d *ManagerExec) query(ctx context.Context, query string, out interface{}) error { - var errb, outb bytes.Buffer - err := d.exec(ctx, query, &outb, &errb) - if err != nil { - return err - } - - if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { - return sql.ErrNoRows - } - - csv := csv.NewReader(bytes.NewReader(outb.Bytes())) - csv.Comma = '\t' - - if err = gocsv.UnmarshalCSV(csv, out); err != nil { - return err - } - - return nil -} - -func (u *ManagerExec) CreateOperatorUserExec(ctx context.Context, pass string) error { - var errb, outb bytes.Buffer - - q := fmt.Sprintf("CREATE USER IF NOT EXISTS 'operator'@'%%' IDENTIFIED BY '%s'", pass) - err := u.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "create operator user") - } - - outb.Reset() - errb.Reset() - err = u.exec(ctx, "GRANT ALL ON *.* TO 'operator'@'%' WITH GRANT OPTION", &outb, &errb) - if err != nil { - return errors.Wrap(err, "grant operator user") - } - - return nil -} - -// UpdateUserPassWithoutDPExec updates user pass without Dual Password -// feature introduced in MsSQL 8 -func (u *ManagerExec) UpdateUserPassWithoutDPExec(ctx context.Context, user *SysUser) error { - if user == nil { - return nil - } - - var errb, outb bytes.Buffer - for _, host := range user.Hosts { - q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user.Name, host, user.Pass) - err := u.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "update password") - } - } - - return nil -} - -// UpdateUserPassExec updates user passwords but retains the current password -// using Dual Password feature of MySQL 8. -func (m *ManagerExec) UpdateUserPassExec(ctx context.Context, user *SysUser) error { - if user == nil { - return nil - } - - for _, host := range user.Hosts { - var errb, outb bytes.Buffer - q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s' RETAIN CURRENT PASSWORD", user.Name, host, user.Pass) - err := m.exec(ctx, q, &outb, &errb) - if err != nil { - return err - } - } - - return nil -} - -// DiscardOldPasswordExec discards old passwords of given users -func (m *ManagerExec) DiscardOldPasswordExec(ctx context.Context, user *SysUser) error { - if user == nil { - return nil - } - - for _, host := range user.Hosts { - var errb, outb bytes.Buffer - q := fmt.Sprintf("ALTER USER '%s'@'%s' DISCARD OLD PASSWORD", user.Name, host) - err := m.exec(ctx, q, &outb, &errb) - if err != nil { - return err - } - } - - return nil -} - -// IsOldPassDiscarded checks if old password is discarded -func (m *ManagerExec) IsOldPassDiscardedExec(ctx context.Context, user *SysUser) (bool, error) { - rows := []*struct { - HasAttr int `csv:"has_attr"` - }{} - - err := m.query(ctx, fmt.Sprintf("SELECT IF(User_attributes IS NULL, TRUE, FALSE) AS has_attr FROM mysql.user WHERE user='%s'", user.Name), &rows) - if err != nil { - if err == sql.ErrNoRows { - return true, nil - } - return false, errors.Wrap(err, "select User_attributes field") - } - - if rows[0].HasAttr == 0 { - return false, nil - } - - return true, nil -} - -// UpdateProxyUserExec updates proxy admin and monitor user passwords within ProxySQL -func (e *ManagerExec) UpdateProxyUserExec(ctx context.Context, user *SysUser) error { - exec := func(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := []string{"mysql", fmt.Sprintf("-p%s", e.pass), "-u", string(e.user), "-h", e.host, "-P 6032", "-e", stm} - - err := e.client.Exec(e.pod, "proxysql", cmd, nil, stdout, stderr, false) - if err != nil { - sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") - serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") - return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) - } - - if strings.Contains(stderr.String(), "ERROR") { - return fmt.Errorf("sql error: %s", stderr) - } - - return nil - } - - switch user.Name { - case ProxyAdmin: - q := fmt.Sprintf(` - UPDATE global_variables SET variable_value='%s' WHERE variable_name='admin-admin_credentials'; - UPDATE global_variables SET variable_value='%s' WHERE variable_name='admin-cluster_password'; - LOAD ADMIN VARIABLES TO RUNTIME; - SAVE ADMIN VARIABLES TO DISK; - `, "proxyadmin:"+user.Pass, user.Pass) - - var errb, outb bytes.Buffer - err := exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "update proxy admin password") - } - case Monitor: - q := fmt.Sprintf(` - UPDATE global_variables SET variable_value='%s' WHERE variable_name='mysql-monitor_password'; - LOAD MYSQL VARIABLES TO RUNTIME; - SAVE MYSQL VARIABLES TO DISK; - `, user.Pass) - - var errb, outb bytes.Buffer - err := exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "update proxy monitor password") - } - } - - return nil -} - -// Update160MonitorUserGrantExec grants SERVICE_CONNECTION_ADMIN rights to the monitor user -// if pxc version is 8 or more and sets the MAX_USER_CONNECTIONS parameter to 100 (empirically determined) -func (u *ManagerExec) Update160MonitorUserGrantExec(ctx context.Context, pass string) (err error) { - q := fmt.Sprintf(` - CREATE USER IF NOT EXISTS 'monitor'@'%%' IDENTIFIED BY '%s'; - /*!80015 GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%' */; - ALTER USER 'monitor'@'%%' WITH MAX_USER_CONNECTIONS 100; - `, pass) - - var errb, outb bytes.Buffer - err = u.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "update monitor user grants") - } - - return nil -} - -// Update170XtrabackupUserExec grants all needed rights to the xtrabackup user -func (u *ManagerExec) Update170XtrabackupUserExec(ctx context.Context, pass string) (err error) { - q := fmt.Sprintf(` - CREATE USER IF NOT EXISTS 'xtrabackup'@'%%' IDENTIFIED BY '%s'; - GRANT ALL ON *.* TO 'xtrabackup'@'%%'; - `, pass) - var errb, outb bytes.Buffer - err = u.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "update xtrabackup user grants") - } - - return nil -} - -// Update1100SystemUserPrivilegeExec grants system_user privilege for monitor and clustercheck users -func (u *ManagerExec) Update1100SystemUserPrivilegeExec(ctx context.Context, user *SysUser) (err error) { - switch user.Name { - case Monitor: - var errb, outb bytes.Buffer - if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'monitor'@'%'", &outb, &errb); err != nil { - return errors.Wrap(err, "monitor user") - } - case Clustercheck: - var errb, outb bytes.Buffer - if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'clustercheck'@'localhost'", &outb, &errb); err != nil { - return errors.Wrap(err, "clustercheck user") - } - } - - return nil -} - -func (u *ManagerExec) CreateReplicationUserExec(ctx context.Context, password string) error { - q := fmt.Sprintf(` - CREATE USER IF NOT EXISTS 'replication'@'%%' IDENTIFIED BY '%s'; - GRANT REPLICATION SLAVE ON *.* to 'replication'@'%%'; - `, password) - var errb, outb bytes.Buffer - err := u.exec(ctx, q, &outb, &errb) - if err != nil { - return errors.Wrap(err, "create replication user") - } - - return nil -} - -// UpdatePassExpirationPolicyExec sets user password expiration policy to never -func (u *ManagerExec) UpdatePassExpirationPolicyExec(ctx context.Context, user *SysUser) error { - if user == nil { - return nil - } - - for _, host := range user.Hosts { - var errb, outb bytes.Buffer - q := fmt.Sprintf("ALTER USER '%s'@'%s' PASSWORD EXPIRE NEVER", user.Name, host) - err := u.exec(ctx, q, &outb, &errb) - if err != nil { - return err - } - } - return nil -} From 79740c7c95866f55b2977d248171e165057561a7 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 24 Nov 2023 14:55:56 +0100 Subject: [PATCH 25/32] Set propper database for user manager. --- pkg/pxc/users/users.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pxc/users/users.go b/pkg/pxc/users/users.go index e726616167..56e693b9e0 100644 --- a/pkg/pxc/users/users.go +++ b/pkg/pxc/users/users.go @@ -54,7 +54,7 @@ func NewManager(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host stri } func (d *Manager) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := []string{"mysql", "--database", "performance_schema", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} + cmd := []string{"mysql", "--database", "mysql", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) if err != nil { From 23961c9207e5c9f409e660291dd8917f4d247bd8 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 24 Nov 2023 15:19:52 +0100 Subject: [PATCH 26/32] Refactor user.Manager. --- pkg/controller/pxc/users.go | 7 +-- pkg/pxc/queries/queries.go | 64 +++++++++---------- pkg/pxc/users/users.go | 119 +++++++++--------------------------- 3 files changed, 66 insertions(+), 124 deletions(-) diff --git a/pkg/controller/pxc/users.go b/pkg/controller/pxc/users.go index a93c4552cd..5279502961 100644 --- a/pkg/controller/pxc/users.go +++ b/pkg/controller/pxc/users.go @@ -357,7 +357,7 @@ func (r *ReconcilePerconaXtraDBCluster) manageOperatorAdminUser(ctx context.Cont } host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace - um := users.NewManager(&primary, r.clientcmd, users.Root, string(secrets.Data[users.Root]), host) + um := users.NewPXCManager(&primary, r.clientcmd, users.Root, string(secrets.Data[users.Root]), host) err = um.CreateOperatorUser(ctx, string(pass)) if err != nil { @@ -1117,8 +1117,7 @@ func (r *ReconcilePerconaXtraDBCluster) updateProxyUser(ctx context.Context, cr } for _, pod := range pods.Items { - um := users.NewManager(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin]), "127.0.0.1") - + um := users.NewProxySQLManager(&pod, r.clientcmd, users.ProxyAdmin, string(internalSecrets.Data[users.ProxyAdmin])) err = um.UpdateProxyUser(ctx, user) if err != nil { return errors.Wrap(err, "update proxy users") @@ -1168,7 +1167,7 @@ func (r *ReconcilePerconaXtraDBCluster) getUserManager(ctx context.Context, cr * } host := primary.Name + "." + cr.Name + "-pxc." + cr.Namespace - return users.NewManager(&primary, r.clientcmd, pxcUser, pxcPass, host), nil + return users.NewPXCManager(&primary, r.clientcmd, pxcUser, pxcPass, host), nil } func (r *ReconcilePerconaXtraDBCluster) updateUserPassExpirationPolicy(ctx context.Context, cr *api.PerconaXtraDBCluster, internalSecrets *corev1.Secret, user *users.SysUser) error { diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index d188b66740..bda6d9621a 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -9,9 +9,8 @@ import ( "regexp" "strings" - "github.com/pkg/errors" - "github.com/gocarina/gocsv" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "github.com/percona/percona-xtradb-cluster-operator/clientcmd" @@ -55,33 +54,35 @@ var ErrNotFound = errors.New("not found") var sensitiveRegexp = regexp.MustCompile(":.*@") type Database struct { - client *clientcmd.Client - pod *corev1.Pod - container string + Client *clientcmd.Client + Pod *corev1.Pod cmd []string + container string } // NewPXC creates a new Database instance for a given PXC pod func NewPXC(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *Database { cmd := []string{"mysql", "--database", "mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", host, "-e"} - return &Database{client: cliCmd, pod: pod, container: "pxc", cmd: cmd} + return &Database{Client: cliCmd, Pod: pod, container: "pxc", cmd: cmd} } // NewProxySQL creates a new Database instance for a given ProxySQL pod func NewProxySQL(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *Database { cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-P", "6032", "-e"} - return &Database{client: cliCmd, pod: pod, container: "proxysql", cmd: cmd} + return &Database{Client: cliCmd, Pod: pod, container: "proxysql", cmd: cmd} } // NewHAProxy creates a new Database instance for a given HAProxy pod func NewHAProxy(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *Database { cmd := []string{"mysql", fmt.Sprintf("-p%s", pass), "-u", string(user), "-h", "127.0.0.1", "-e"} - return &Database{client: cliCmd, pod: pod, container: "haproxy", cmd: cmd} + return &Database{Client: cliCmd, Pod: pod, container: "haproxy", cmd: cmd} } -func (d *Database) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { +// Exec executes a given SQL statement on a database and populates +// stdout and stderr buffers with the output. +func (d *Database) Exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { cmd := append(d.cmd, stm) - err := d.client.Exec(d.pod, d.container, cmd, nil, stdout, stderr, false) + err := d.Client.Exec(d.Pod, d.container, cmd, nil, stdout, stderr, false) if err != nil { sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") @@ -95,9 +96,10 @@ func (d *Database) exec(ctx context.Context, stm string, stdout, stderr *bytes.B return nil } -func (d *Database) query(ctx context.Context, query string, out interface{}) error { +// Query executes a given SQL statement on a database and populates out with the result +func (d *Database) Query(ctx context.Context, query string, out interface{}) error { var errb, outb bytes.Buffer - err := d.exec(ctx, query, &outb, &errb) + err := d.Exec(ctx, query, &outb, &errb) if err != nil { return err } @@ -122,7 +124,7 @@ func (d *Database) CurrentReplicationChannels(ctx context.Context) ([]string, er }{} q := `SELECT DISTINCT(Channel_name) as name from replication_asynchronous_connection_failover` - err := d.query(ctx, q, &rows) + err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil @@ -147,7 +149,7 @@ func (d *Database) ChangeChannelPassword(ctx context.Context, channel, password COMMIT; `, channel, password, channel, channel) - err := d.exec(ctx, q, &outb, &errb) + err := d.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "change channel password") } @@ -163,7 +165,7 @@ func (d *Database) ReplicationStatus(ctx context.Context, channel string) (Repli }{} q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL %s", channel) - err := d.query(ctx, q, &rows) + err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return ReplicationStatusNotInitiated, nil @@ -188,7 +190,7 @@ func (d *Database) ReplicationStatus(ctx context.Context, channel string) (Repli func (d *Database) StopAllReplication(ctx context.Context) error { var errb, outb bytes.Buffer - if err := d.exec(ctx, "STOP REPLICA", &outb, &errb); err != nil { + if err := d.Exec(ctx, "STOP REPLICA", &outb, &errb); err != nil { return errors.Wrap(err, "failed to stop replication") } return nil @@ -197,7 +199,7 @@ func (d *Database) StopAllReplication(ctx context.Context) error { func (d *Database) AddReplicationSource(ctx context.Context, name, host string, port, weight int) error { var errb, outb bytes.Buffer q := fmt.Sprintf("SELECT asynchronous_connection_failover_add_source('%s', '%s', %d, null, %d)", name, host, port, weight) - err := d.exec(ctx, q, &outb, &errb) + err := d.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "add replication source") } @@ -212,7 +214,7 @@ func (d *Database) ReplicationChannelSources(ctx context.Context, channelName st }{} q := fmt.Sprintf("SELECT host, port, weight FROM replication_asynchronous_connection_failover WHERE Channel_name = '%s'", channelName) - err := d.query(ctx, q, &rows) + err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound @@ -229,19 +231,19 @@ func (d *Database) ReplicationChannelSources(ctx context.Context, channelName st func (d *Database) StopReplication(ctx context.Context, name string) error { var errb, outb bytes.Buffer - err := d.exec(ctx, fmt.Sprintf("STOP REPLICA FOR CHANNEL '%s'", name), &outb, &errb) + err := d.Exec(ctx, fmt.Sprintf("STOP REPLICA FOR CHANNEL '%s'", name), &outb, &errb) return errors.Wrap(err, "stop replication for channel "+name) } func (d *Database) EnableReadonly(ctx context.Context) error { var errb, outb bytes.Buffer - err := d.exec(ctx, "SET GLOBAL READ_ONLY=1", &outb, &errb) + err := d.Exec(ctx, "SET GLOBAL READ_ONLY=1", &outb, &errb) return errors.Wrap(err, "set global read_only param to 1") } func (d *Database) DisableReadonly(ctx context.Context) error { var errb, outb bytes.Buffer - err := d.exec(ctx, "SET GLOBAL READ_ONLY=0", &outb, &errb) + err := d.Exec(ctx, "SET GLOBAL READ_ONLY=0", &outb, &errb) return errors.Wrap(err, "set global read_only param to 0") } @@ -249,7 +251,7 @@ func (p *Database) IsReadonlyExec(ctx context.Context) (bool, error) { rows := []*struct { ReadOnly int `csv:"readOnly"` }{} - err := p.query(ctx, "select @@read_only as readOnly", &rows) + err := p.Query(ctx, "select @@read_only as readOnly", &rows) if err != nil { return false, errors.Wrap(err, "select global read_only param") } @@ -286,14 +288,14 @@ func (d *Database) StartReplication(ctx context.Context, replicaPass string, con `, replicaPass, config.Source.Host, config.Source.Port, config.SourceRetryCount, config.SourceConnectRetry, ssl, ca, sslVerify, config.Source.Name) var errb, outb bytes.Buffer - err := d.exec(ctx, q, &outb, &errb) + err := d.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrapf(err, "change source for channel %s", config.Source.Name) } outb.Reset() errb.Reset() - err = d.exec(ctx, fmt.Sprintf(`START REPLICA FOR CHANNEL '%s'`, config.Source.Name), &outb, &errb) + err = d.Exec(ctx, fmt.Sprintf(`START REPLICA FOR CHANNEL '%s'`, config.Source.Name), &outb, &errb) return errors.Wrapf(err, "start replica for source %s", config.Source.Name) } @@ -301,7 +303,7 @@ func (d *Database) StartReplication(ctx context.Context, replicaPass string, con func (d *Database) DeleteReplicationSource(ctx context.Context, name, host string, port int) error { var errb, outb bytes.Buffer q := fmt.Sprintf("SELECT asynchronous_connection_failover_delete_source('%s', '%s', %d, null)", name, host, port) - err := d.exec(ctx, q, &outb, &errb) + err := d.Exec(ctx, q, &outb, &errb) return errors.Wrap(err, "delete replication source "+name) } @@ -313,7 +315,7 @@ func (d *Database) ProxySQLInstanceStatus(ctx context.Context, host string) ([]s q := fmt.Sprintf("SELECT status FROM proxysql_servers WHERE hostname LIKE '%s%%'", host) - err := d.query(ctx, q, &rows) + err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound @@ -341,7 +343,7 @@ func (d *Database) PresentInHostgroups(ctx context.Context, host string) (bool, INNER JOIN mysql_galera_hostgroups ON hostgroup_id IN (%s) WHERE hostname LIKE '%s' GROUP BY hostname`, strings.Join(hostgroups, ","), host+"%") - err := d.query(ctx, q, &rows) + err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return false, ErrNotFound @@ -361,7 +363,7 @@ func (d *Database) PrimaryHost(ctx context.Context) (string, error) { q := fmt.Sprintf("SELECT hostname as host FROM runtime_mysql_servers WHERE hostgroup_id = %d", writerID) - err := d.query(ctx, q, &rows) + err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return "", ErrNotFound @@ -377,7 +379,7 @@ func (d *Database) Hostname(ctx context.Context) (string, error) { Hostname string `csv:"hostname"` }{} - err := d.query(ctx, "SELECT @@hostname hostname", &rows) + err := d.Query(ctx, "SELECT @@hostname hostname", &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { return "", ErrNotFound @@ -394,7 +396,7 @@ func (d *Database) WsrepLocalStateComment(ctx context.Context) (string, error) { Value string `csv:"Value"` }{} - err := d.query(ctx, "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'", &rows) + err := d.Query(ctx, "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'", &rows) if err != nil { if err == sql.ErrNoRows { return "", fmt.Errorf("variable was not found") @@ -410,7 +412,7 @@ func (d *Database) Version(ctx context.Context) (string, error) { Version string `csv:"version"` }{} - err := d.query(ctx, "select @@VERSION as version;", &rows) + err := d.Query(ctx, "select @@VERSION as version;", &rows) if err != nil { if err == sql.ErrNoRows { return "", fmt.Errorf("variable was not found") diff --git a/pkg/pxc/users/users.go b/pkg/pxc/users/users.go index 56e693b9e0..5ab9252f86 100644 --- a/pkg/pxc/users/users.go +++ b/pkg/pxc/users/users.go @@ -4,17 +4,13 @@ import ( "bytes" "context" "database/sql" - "encoding/csv" "fmt" - "regexp" - "strings" "github.com/pkg/errors" - - "github.com/gocarina/gocsv" corev1 "k8s.io/api/core/v1" "github.com/percona/percona-xtradb-cluster-operator/clientcmd" + "github.com/percona/percona-xtradb-cluster-operator/pkg/pxc/queries" ) const ( @@ -39,70 +35,32 @@ type SysUser struct { Hosts []string `yaml:"hosts"` } -var sensitiveRegexp = regexp.MustCompile(":.*@") - type Manager struct { - client *clientcmd.Client - pod *corev1.Pod - user string - pass string - host string + db *queries.Database } -func NewManager(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *Manager { - return &Manager{client: cliCmd, pod: pod, user: user, pass: pass, host: host} +// NewPXCManager creates a new Manager for a given PXC pod +func NewPXCManager(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass, host string) *Manager { + return &Manager{db: queries.NewPXC(pod, cliCmd, user, pass, host)} } -func (d *Manager) exec(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := []string{"mysql", "--database", "mysql", fmt.Sprintf("-p%s", d.pass), "-u", string(d.user), "-h", d.host, "-e", stm} - - err := d.client.Exec(d.pod, "pxc", cmd, nil, stdout, stderr, false) - if err != nil { - sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") - serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") - return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) - } - - if strings.Contains(stderr.String(), "ERROR") { - return fmt.Errorf("sql error: %s", stderr) - } - - return nil -} - -func (d *Manager) query(ctx context.Context, query string, out interface{}) error { - var errb, outb bytes.Buffer - err := d.exec(ctx, query, &outb, &errb) - if err != nil { - return err - } - - if !strings.Contains(errb.String(), "ERROR") && outb.Len() == 0 { - return sql.ErrNoRows - } - - csv := csv.NewReader(bytes.NewReader(outb.Bytes())) - csv.Comma = '\t' - - if err = gocsv.UnmarshalCSV(csv, out); err != nil { - return err - } - - return nil +// NewProxySQLManager creates a new Manager for a given ProxySQL pod +func NewProxySQLManager(pod *corev1.Pod, cliCmd *clientcmd.Client, user, pass string) *Manager { + return &Manager{db: queries.NewProxySQL(pod, cliCmd, user, pass)} } -func (u *Manager) CreateOperatorUser(ctx context.Context, pass string) error { +func (m *Manager) CreateOperatorUser(ctx context.Context, pass string) error { var errb, outb bytes.Buffer q := fmt.Sprintf("CREATE USER IF NOT EXISTS 'operator'@'%%' IDENTIFIED BY '%s'", pass) - err := u.exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "create operator user") } outb.Reset() errb.Reset() - err = u.exec(ctx, "GRANT ALL ON *.* TO 'operator'@'%' WITH GRANT OPTION", &outb, &errb) + err = m.db.Exec(ctx, "GRANT ALL ON *.* TO 'operator'@'%' WITH GRANT OPTION", &outb, &errb) if err != nil { return errors.Wrap(err, "grant operator user") } @@ -112,7 +70,7 @@ func (u *Manager) CreateOperatorUser(ctx context.Context, pass string) error { // UpdateUserPassWithoutDPExec updates user pass without Dual Password // feature introduced in MsSQL 8 -func (u *Manager) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser) error { +func (m *Manager) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser) error { if user == nil { return nil } @@ -120,7 +78,7 @@ func (u *Manager) UpdateUserPassWithoutDP(ctx context.Context, user *SysUser) er var errb, outb bytes.Buffer for _, host := range user.Hosts { q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user.Name, host, user.Pass) - err := u.exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update password") } @@ -139,7 +97,7 @@ func (m *Manager) UpdateUserPass(ctx context.Context, user *SysUser) error { for _, host := range user.Hosts { var errb, outb bytes.Buffer q := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s' RETAIN CURRENT PASSWORD", user.Name, host, user.Pass) - err := m.exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return err } @@ -157,7 +115,7 @@ func (m *Manager) DiscardOldPassword(ctx context.Context, user *SysUser) error { for _, host := range user.Hosts { var errb, outb bytes.Buffer q := fmt.Sprintf("ALTER USER '%s'@'%s' DISCARD OLD PASSWORD", user.Name, host) - err := m.exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return err } @@ -172,7 +130,7 @@ func (m *Manager) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bool, HasAttr int `csv:"has_attr"` }{} - err := m.query(ctx, fmt.Sprintf("SELECT IF(User_attributes IS NULL, TRUE, FALSE) AS has_attr FROM mysql.user WHERE user='%s'", user.Name), &rows) + err := m.db.Query(ctx, fmt.Sprintf("SELECT IF(User_attributes IS NULL, TRUE, FALSE) AS has_attr FROM mysql.user WHERE user='%s'", user.Name), &rows) if err != nil { if err == sql.ErrNoRows { return true, nil @@ -188,24 +146,7 @@ func (m *Manager) IsOldPassDiscarded(ctx context.Context, user *SysUser) (bool, } // UpdateProxyUser updates proxy admin and monitor user passwords within ProxySQL -func (e *Manager) UpdateProxyUser(ctx context.Context, user *SysUser) error { - exec := func(ctx context.Context, stm string, stdout, stderr *bytes.Buffer) error { - cmd := []string{"mysql", fmt.Sprintf("-p%s", e.pass), "-u", string(e.user), "-h", e.host, "-P 6032", "-e", stm} - - err := e.client.Exec(e.pod, "proxysql", cmd, nil, stdout, stderr, false) - if err != nil { - sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") - serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") - return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) - } - - if strings.Contains(stderr.String(), "ERROR") { - return fmt.Errorf("sql error: %s", stderr) - } - - return nil - } - +func (m *Manager) UpdateProxyUser(ctx context.Context, user *SysUser) error { switch user.Name { case ProxyAdmin: q := fmt.Sprintf(` @@ -216,7 +157,7 @@ func (e *Manager) UpdateProxyUser(ctx context.Context, user *SysUser) error { `, "proxyadmin:"+user.Pass, user.Pass) var errb, outb bytes.Buffer - err := exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update proxy admin password") } @@ -228,7 +169,7 @@ func (e *Manager) UpdateProxyUser(ctx context.Context, user *SysUser) error { `, user.Pass) var errb, outb bytes.Buffer - err := exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update proxy monitor password") } @@ -239,7 +180,7 @@ func (e *Manager) UpdateProxyUser(ctx context.Context, user *SysUser) error { // Update160MonitorUserGrant grants SERVICE_CONNECTION_ADMIN rights to the monitor user // if pxc version is 8 or more and sets the MAX_USER_CONNECTIONS parameter to 100 (empirically determined) -func (u *Manager) Update160MonitorUserGrant(ctx context.Context, pass string) (err error) { +func (m *Manager) Update160MonitorUserGrant(ctx context.Context, pass string) (err error) { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'monitor'@'%%' IDENTIFIED BY '%s'; /*!80015 GRANT SERVICE_CONNECTION_ADMIN ON *.* TO 'monitor'@'%%' */; @@ -247,7 +188,7 @@ func (u *Manager) Update160MonitorUserGrant(ctx context.Context, pass string) (e `, pass) var errb, outb bytes.Buffer - err = u.exec(ctx, q, &outb, &errb) + err = m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update monitor user grants") } @@ -256,13 +197,13 @@ func (u *Manager) Update160MonitorUserGrant(ctx context.Context, pass string) (e } // Update170XtrabackupUser grants all needed rights to the xtrabackup user -func (u *Manager) Update170XtrabackupUser(ctx context.Context, pass string) (err error) { +func (m *Manager) Update170XtrabackupUser(ctx context.Context, pass string) (err error) { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'xtrabackup'@'%%' IDENTIFIED BY '%s'; GRANT ALL ON *.* TO 'xtrabackup'@'%%'; `, pass) var errb, outb bytes.Buffer - err = u.exec(ctx, q, &outb, &errb) + err = m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "update xtrabackup user grants") } @@ -271,16 +212,16 @@ func (u *Manager) Update170XtrabackupUser(ctx context.Context, pass string) (err } // Update1100SystemUserPrivilege grants system_user privilege for monitor and clustercheck users -func (u *Manager) Update1100SystemUserPrivilege(ctx context.Context, user *SysUser) (err error) { +func (m *Manager) Update1100SystemUserPrivilege(ctx context.Context, user *SysUser) (err error) { switch user.Name { case Monitor: var errb, outb bytes.Buffer - if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'monitor'@'%'", &outb, &errb); err != nil { + if err := m.db.Exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'monitor'@'%'", &outb, &errb); err != nil { return errors.Wrap(err, "monitor user") } case Clustercheck: var errb, outb bytes.Buffer - if err := u.exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'clustercheck'@'localhost'", &outb, &errb); err != nil { + if err := m.db.Exec(ctx, "GRANT SYSTEM_USER ON *.* TO 'clustercheck'@'localhost'", &outb, &errb); err != nil { return errors.Wrap(err, "clustercheck user") } } @@ -288,13 +229,13 @@ func (u *Manager) Update1100SystemUserPrivilege(ctx context.Context, user *SysUs return nil } -func (u *Manager) CreateReplicationUser(ctx context.Context, password string) error { +func (m *Manager) CreateReplicationUser(ctx context.Context, password string) error { q := fmt.Sprintf(` CREATE USER IF NOT EXISTS 'replication'@'%%' IDENTIFIED BY '%s'; GRANT REPLICATION SLAVE ON *.* to 'replication'@'%%'; `, password) var errb, outb bytes.Buffer - err := u.exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return errors.Wrap(err, "create replication user") } @@ -303,7 +244,7 @@ func (u *Manager) CreateReplicationUser(ctx context.Context, password string) er } // UpdatePassExpirationPolicy sets user password expiration policy to never -func (u *Manager) UpdatePassExpirationPolicy(ctx context.Context, user *SysUser) error { +func (m *Manager) UpdatePassExpirationPolicy(ctx context.Context, user *SysUser) error { if user == nil { return nil } @@ -311,7 +252,7 @@ func (u *Manager) UpdatePassExpirationPolicy(ctx context.Context, user *SysUser) for _, host := range user.Hosts { var errb, outb bytes.Buffer q := fmt.Sprintf("ALTER USER '%s'@'%s' PASSWORD EXPIRE NEVER", user.Name, host) - err := u.exec(ctx, q, &outb, &errb) + err := m.db.Exec(ctx, q, &outb, &errb) if err != nil { return err } From 0c9084135b67426ad5365c40cf5c374be59273f4 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 24 Nov 2023 15:42:38 +0100 Subject: [PATCH 27/32] Lint fix. --- pkg/controller/pxc/upgrade.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controller/pxc/upgrade.go b/pkg/controller/pxc/upgrade.go index 48b999e6ae..c7eb7fa858 100644 --- a/pkg/controller/pxc/upgrade.go +++ b/pkg/controller/pxc/upgrade.go @@ -477,7 +477,7 @@ func (r *ReconcilePerconaXtraDBCluster) connectProxy(ctx context.Context, cr *ap LabelSelector: labels.SelectorFromSet(sfs.Labels()), }, ); err != nil { - return nil, errors.Wrapf(err, "failed to get pods for statefulset %s", sfs.Name) + return nil, errors.Wrapf(err, "failed to get pods for statefulset %s", sfs.Name()) } return pods.Items, nil From 88c7afffb7cf02ebf353114901aec1ea38983c13 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 29 Nov 2023 07:43:48 +0100 Subject: [PATCH 28/32] Fix getting replication status query. --- pkg/pxc/queries/queries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index bda6d9621a..bdfa229bb1 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -164,7 +164,7 @@ func (d *Database) ReplicationStatus(ctx context.Context, channel string) (Repli LastErrNo int `csv:"Last_Errno"` }{} - q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL %s", channel) + q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL '%s'", channel) err := d.Query(ctx, q, &rows) if err != nil { if errors.Is(err, sql.ErrNoRows) { From 6170d6818993268ac94a8f62a5484e4b10ef8928 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 29 Nov 2023 08:49:53 +0100 Subject: [PATCH 29/32] Fix pass leak. --- pkg/pxc/queries/queries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index bdfa229bb1..17667f0895 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -86,7 +86,7 @@ func (d *Database) Exec(ctx context.Context, stm string, stdout, stderr *bytes.B if err != nil { sout := sensitiveRegexp.ReplaceAllString(stdout.String(), ":*****@") serr := sensitiveRegexp.ReplaceAllString(stderr.String(), ":*****@") - return errors.Wrapf(err, "run %s, stdout: %s, stderr: %s", cmd, sout, serr) + return errors.Wrapf(err, "stdout: %s, stderr: %s", sout, serr) } if strings.Contains(stderr.String(), "ERROR") { From 7e998cac6d834a204ff9cce5c0aa2f15cb0e4c5b Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Wed, 29 Nov 2023 15:24:50 +0100 Subject: [PATCH 30/32] Fix checking replication status. --- pkg/pxc/queries/queries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index 17667f0895..e5fa320ed8 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -167,7 +167,7 @@ func (d *Database) ReplicationStatus(ctx context.Context, channel string) (Repli q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL '%s'", channel) err := d.Query(ctx, q, &rows) if err != nil { - if errors.Is(err, sql.ErrNoRows) { + if strings.HasSuffix(err.Error(), "does not exist.") || errors.Is(err, sql.ErrNoRows) { return ReplicationStatusNotInitiated, nil } return ReplicationStatusError, errors.Wrap(err, "select replication status") From fb40ef746120742ee4dc5681097f50c7a048cecd Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 29 Dec 2023 10:25:58 +0100 Subject: [PATCH 31/32] Implement database.ShowReplicaStatus. --- pkg/pxc/queries/queries.go | 73 +++++--------------------------------- 1 file changed, 8 insertions(+), 65 deletions(-) diff --git a/pkg/pxc/queries/queries.go b/pkg/pxc/queries/queries.go index 89ad908f84..a57c8f522a 100644 --- a/pkg/pxc/queries/queries.go +++ b/pkg/pxc/queries/queries.go @@ -162,6 +162,7 @@ func (d *Database) ShowReplicaStatus(ctx context.Context, channel string) (map[s IORunning string `csv:"Replica_IO_Running"` SQLRunning string `csv:"Replica_SQL_Running"` LastErrNo int `csv:"Last_Errno"` + LastIOErr string `csv:"Last_IO_Err"` }{} q := fmt.Sprintf("SHOW REPLICA STATUS FOR CHANNEL '%s'", channel) @@ -170,73 +171,15 @@ func (d *Database) ShowReplicaStatus(ctx context.Context, channel string) (map[s return nil, err } - // ioRunning := rows[0].IORunning == "Yes" - // sqlRunning := rows[0].SQLRunning == "Yes" - // lastErrNo := rows[0].LastErrNo - - return nil, nil - - // defer rows.Close() - // columns, err := rows.Columns() - // if err != nil { - // return nil, err - // } - // ok := rows.Next() - // if !ok { - // return make(map[string]string), nil - // } - - // values := make([]any, 0, len(columns)) - // for range columns { - // values = append(values, new([]byte)) - // } - // status := make(map[string]string, len(columns)) - - // if err := rows.Scan(values...); err != nil { - // return nil, err - // } - - // for i, name := range columns { - // ptr, ok := values[i].(*[]byte) - // if !ok { - // return nil, errors.Errorf("failed to convert %T to *[]byte: %s", values[i], name) - // } - // status[name] = string(*ptr) - // } - - // return status, nil + status := make(map[string]string, 4) + status["Replica_IO_Running"] = rows[0].IORunning + status["Replica_SQL_Running"] = rows[0].SQLRunning + status["Last_Errno"] = fmt.Sprintf("%d", rows[0].LastErrNo) + status["Last_IO_Err"] = rows[0].LastIOErr + + return status, nil } -// func (p *Database) ReplicationStatus(ctx context.Context, channel string) (ReplicationStatus, error) { -// statusMap, err := p.ShowReplicaStatus(ctx, channel) -// if err != nil { -// if strings.HasSuffix(err.Error(), "does not exist.") || errors.Is(err, sql.ErrNoRows) { -// return ReplicationStatusNotInitiated, nil -// } -// return ReplicationStatusError, errors.Wrap(err, "select replication status") -// } - -// <<<<<<< HEAD -// ioRunning := rows[0].IORunning == "Yes" -// sqlRunning := rows[0].SQLRunning == "Yes" -// lastErrNo := rows[0].LastErrNo - -// if ioRunning && sqlRunning { -// ======= -// IORunning := statusMap["Replica_IO_Running"] -// SQLRunning := statusMap["Replica_SQL_Running"] -// LastErrNo := statusMap["Last_Errno"] -// if IORunning == "Yes" && SQLRunning == "Yes" { -// >>>>>>> main -// return ReplicationStatusActive, nil -// } - -// if !ioRunning && !sqlRunning && lastErrNo == 0 { -// return ReplicationStatusNotInitiated, nil -// } - -// return ReplicationStatusError, nil -// } func (d *Database) ReplicationStatus(ctx context.Context, channel string) (ReplicationStatus, error) { statusMap, err := d.ShowReplicaStatus(ctx, channel) if err != nil { From 1ed4605b677654d7ec76c0662b204abb3cbe9a67 Mon Sep 17 00:00:00 2001 From: Inel Pandzic Date: Fri, 29 Dec 2023 11:04:30 +0100 Subject: [PATCH 32/32] Revert cr.yaml file. --- deploy/cr.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 85d61656a6..eaeae7851f 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -187,7 +187,7 @@ spec: storage: 6G gracePeriod: 600 haproxy: - enabled: false + enabled: true size: 3 image: perconalab/percona-xtradb-cluster-operator:main-haproxy # imagePullPolicy: Always @@ -352,7 +352,7 @@ spec: # minAvailable: 0 gracePeriod: 30 proxysql: - enabled: true + enabled: false size: 3 image: perconalab/percona-xtradb-cluster-operator:main-proxysql # imagePullPolicy: Always