PT-2134 - support for PostgreSQL and MySQL operators (#567)

* PT-2134 - Support for PostgreSQL and PS MySQL operators

For PS MySQL operator: added support of pt-mysql-summary
For PostgreSQL operator: added support for pg_gather
Options added:
  - kubeconfig - path to kubeconfig
  - forwardport - port to use when calling pt-*-summary tools ad pt_gather
Options changed:
  - resource - now default value is  (was pxc). New values added:
    psql - for PostgreSQL operator
    ps - for PS MySQL operator
    if default value () is used: only K8 information is collected
    Otherwise resource-specific summary is collected

* PT-2134_support_for_PostgreSQL_and_MySQL_operators

Fixed summary collection when connecting to PostgreSQL opertor and no resource specified

* PT-2134 - support for PostgreSQL and MySQL operators

Added test case for full supported set of values for option --resource,
added --kubeconfig and --forwardport options for test cases,
added support for environment variables KUBECONFIG_PXC, KUBECONFIG_PS, KUBECONFIG_PSMDB, KUBECONFIG_PSQL, FORWARDPORT for test cases

* PT-2134 - support for PostgreSQL and MySQL operators

updated docs/pt-k8s-debug-collector.rst,
replaced README.md in src/go/pt-k8s-debug-collector wih symbolic link to docs/pt-k8s-debug-collector.rst
to avoid having inconsistent documentation

* PT-2134 - support for PostgreSQL and MySQL operators

Removed curl STDERR from the command output

* PT-2134 - support for PostgreSQL and MySQL operators

typo in pt-k8s-debug-collector.rst

* PT-2134 - support for PostgreSQL and MySQL operators

Renamed --resource=psql to --resource=pg after review suggestion by Ege
and collecting feedback from potential users

Co-authored-by: EvgeniyPatlan <evgeniy.patlan@percona.com>
Co-authored-by: Carlos Salguero <carlos.salguero@percona.com>
This commit is contained in:
Sveta Smirnova
2022-12-19 18:48:51 +03:00
committed by GitHub
parent 7e5c51d0fb
commit e8ebc855d0
6 changed files with 491 additions and 135 deletions

View File

@@ -46,6 +46,13 @@ Data, collected for PXC
"perconaxtradbclusterrestores",
"perconaxtradbclusters"
Summary, collected for PXC (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pt-mysql-summary"
Individual files, collected for PXC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -60,6 +67,22 @@ Individual files, collected for PXC
"var/lib/mysql/mysqld.post.processing.log",
"var/lib/mysql/auto.cnf"
Data, collected for MySQL
~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"perconaservermysqlbackups",
"perconaservermysqlrestores",
"perconaservermysqls"
Summary, collected for MySQL (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pt-mysql-summary"
Data, collected for MongoDB
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -69,22 +92,90 @@ Data, collected for MongoDB
"perconaservermongodbrestores",
"perconaservermongodbs"
Summary, collected for MongoDB (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pt-mongodb-summary"
Data, collected for PostgreSQL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"perconapgclusters",
"pgclusters",
"pgpolicies",
"pgreplicas",
"pgtasks"
Summary, collected for PostgreSQL (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pg_gather"
Usage
=====
``pt-k8s-debug-collector <flags>``
Flags:
Supported Flags:
================
``--resource` targeted custom resource name (default "pxc")``
``--resource``
``--namespace` targeted namespace. By default data will be collected from all namespaces``
Targeted custom resource name. Supported values:
``--cluster` targeted pxc/psmdb cluster. By default data from all available clusters to be collected``
* ``pxc`` - PXC
* ``psmdb`` - MongoDB
* ``pg`` - PostgreSQL
* ``ps`` - MySQL
* ``none`` - Collect only general Kubernetes data, do not collect anything specific to the particular operator).
Default: ``none``
``--namespace``
Targeted namespace. By default data will be collected from all namespaces
``--cluster``
Targeted cluster. By default data from all available clusters to be collected
``--kubeconfig``
Path to kubeconfig. Default configuration be used if none specified
``--forwardport``
Port to use when collecting database-specific summaries. By default, 3306 will be used for PXC and MySQL, 27017 for MongoDB, and 5432 for PostgreSQL
Requirements
============
- Installed and configured ``kubectl``
- Installed and configured ``pt-mysql-summary``
- Installed and configured ``pt-mongodb-summary``
- Installed, configured, and available in PATH ``kubectl``
- Installed, configured, and available in PATH ``pt-mysql-summary`` for PXC and MySQL
- Installed, configured, and available in PATH ``pt-mongodb-summary`` for MongoDB
Known Issues
============
On Kubernetes 1.21 - 1.24 warning is printed:
.. code-block:: bash
2022/12/15 17:43:16 Error: get resource podsecuritypolicies in namespace default: error: <nil>, stderr: Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
, stdout: apiVersion: v1
items: []
kind: List
metadata:
resourceVersion: ""
This warning is harmless and does not affect data collection. We will remove podsecuritypolicies once everyone upgrade to Kubernetes 1.25 or newer. Before that we advise to ignore this warning.

View File

@@ -1,84 +0,0 @@
# Debug collector tool
Collects debug data (logs, resource statuses etc.) from a k8s/OpenShift cluster. Data is packed into the `cluster-dump.tar.gz` archive in the current working directory.
## Data that will be collected
### Data, collected for all resources
```
"pods",
"replicasets",
"deployments",
"statefulsets",
"replicationcontrollers",
"events",
"configmaps",
"cronjobs",
"jobs",
"podsecuritypolicies",
"poddisruptionbudgets",
"perconaxtradbbackups",
"perconaxtradbclusterbackups",
"perconaxtradbclusterrestores",
"perconaxtradbclusters",
"clusterrolebindings",
"clusterroles",
"rolebindings",
"roles",
"storageclasses",
"persistentvolumeclaims",
"persistentvolumes",
"modes",
"your-custom-resource" (depends on 'resource' flag)
```
### Data, collected for PXC
```
"perconaxtradbbackups",
"perconaxtradbclusterbackups",
"perconaxtradbclusterrestores",
"perconaxtradbclusters"
```
### Individual files, collected for PXC
```
"var/lib/mysql/mysqld-error.log",
"var/lib/mysql/innobackup.backup.log",
"var/lib/mysql/innobackup.move.log",
"var/lib/mysql/innobackup.prepare.log",
"var/lib/mysql/grastate.dat",
"var/lib/mysql/gvwstate.dat",
"var/lib/mysql/mysqld.post.processing.log",
"var/lib/mysql/auto.cnf"
```
### Data, collected for MongoDB
```
"perconaservermongodbbackups",
"perconaservermongodbrestores",
"perconaservermongodbs"
```
## Usage
`pt-k8s-debug-collector <flags>`
Flags:
`--resource` targeted custom resource name (default "pxc")
`--namespace` targeted namespace. By default, data will be collected from all namespaces
`--cluster` targeted pxc/psmdb cluster. By default, data from all available clusters to be collected
## Requirements
- Installed and configured 'kubectl'
- Installed and configured 'pt-mysql-summary'
- Installed and configured 'pt-mongodb-summary'

View File

@@ -0,0 +1,181 @@
.. _pt-k8s-debug-collector:
==================================
:program:`pt-k8s-debug-collector`
==================================
Collects debug data (logs, resource statuses etc.) from a k8s/OpenShift cluster. Data is packed into the ``cluster-dump.tar.gz`` archive in the current working directory.
Data that will be collected
===========================
.. code-block:: bash
"pods",
"replicasets",
"deployments",
"statefulsets",
"replicationcontrollers",
"events",
"configmaps",
"cronjobs",
"jobs",
"podsecuritypolicies",
"poddisruptionbudgets",
"perconaxtradbbackups",
"perconaxtradbclusterbackups",
"perconaxtradbclusterrestores",
"perconaxtradbclusters",
"clusterrolebindings",
"clusterroles",
"rolebindings",
"roles",
"storageclasses",
"persistentvolumeclaims",
"persistentvolumes",
"modes",
"your-custom-resource" (depends on 'resource' flag)
Data, collected for PXC
~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"perconaxtradbbackups",
"perconaxtradbclusterbackups",
"perconaxtradbclusterrestores",
"perconaxtradbclusters"
Summary, collected for PXC (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pt-mysql-summary"
Individual files, collected for PXC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"var/lib/mysql/mysqld-error.log",
"var/lib/mysql/innobackup.backup.log",
"var/lib/mysql/innobackup.move.log",
"var/lib/mysql/innobackup.prepare.log",
"var/lib/mysql/grastate.dat",
"var/lib/mysql/gvwstate.dat",
"var/lib/mysql/mysqld.post.processing.log",
"var/lib/mysql/auto.cnf"
Data, collected for MySQL
~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"perconaservermysqlbackups",
"perconaservermysqlrestores",
"perconaservermysqls"
Summary, collected for MySQL (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pt-mysql-summary"
Data, collected for MongoDB
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"perconaservermongodbbackups",
"perconaservermongodbrestores",
"perconaservermongodbs"
Summary, collected for MongoDB (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pt-mongodb-summary"
Data, collected for PostgreSQL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"perconapgclusters",
"pgclusters",
"pgpolicies",
"pgreplicas",
"pgtasks"
Summary, collected for PostgreSQL (available in file summary.txt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
"pg_gather"
Usage
=====
``pt-k8s-debug-collector <flags>``
Supported Flags:
================
``--resource``
Targeted custom resource name. Supported values:
* ``pxc`` - PXC
* ``psmdb`` - MongoDB
* ``pg`` - PostgreSQL
* ``ps`` - MySQL
* ``none`` - Collect only general Kubernetes data, do not collect anything specific to the particular operator).
Default: ``none``
``--namespace``
Targeted namespace. By default data will be collected from all namespaces
``--cluster``
Targeted cluster. By default data from all available clusters to be collected
``--kubeconfig``
Path to kubeconfig. Default configuration be used if none specified
``--forwardport``
Port to use when collecting database-specific summaries. By default, 3306 will be used for PXC and MySQL, 27017 for MongoDB, and 5432 for PostgreSQL
Requirements
============
- Installed, configured, and available in PATH ``kubectl``
- Installed, configured, and available in PATH ``pt-mysql-summary`` for PXC and MySQL
- Installed, configured, and available in PATH ``pt-mongodb-summary`` for MongoDB
Known Issues
============
On Kubernetes 1.21 - 1.24 warning is printed:
.. code-block:: bash
2022/12/15 17:43:16 Error: get resource podsecuritypolicies in namespace default: error: <nil>, stderr: Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
, stdout: apiVersion: v1
items: []
kind: List
metadata:
resourceVersion: ""
This warning is harmless and does not affect data collection. We will remove podsecuritypolicies once everyone upgrade to Kubernetes 1.25 or newer. Before that we advise to ignore this warning.

View File

@@ -21,6 +21,7 @@ import (
// Dumper struct is for dumping cluster
type Dumper struct {
cmd string
kubeconfig string
resources []string
filePaths []string
namespace string
@@ -28,10 +29,11 @@ type Dumper struct {
errors string
mode int64
crType string
forwardport string
}
// New return new Dumper object
func New(location, namespace, resource string) Dumper {
func New(location, namespace, resource string, kubeconfig string, forwardport string) Dumper {
resources := []string{
"pods",
"replicasets",
@@ -54,11 +56,8 @@ func New(location, namespace, resource string) Dumper {
}
filePaths := make([]string, 0)
if len(resource) > 0 {
resources = append(resources, resource)
if resourceType(resource) == "pxc" {
resources = append(resources,
"perconaxtradbbackups",
"perconaxtradbclusterbackups",
"perconaxtradbclusterrestores",
"perconaxtradbclusters")
@@ -78,16 +77,32 @@ func New(location, namespace, resource string) Dumper {
"perconaservermongodbrestores",
"perconaservermongodbs",
)
} else if resourceType(resource) == "pg" {
resources = append(resources,
"perconapgclusters",
"pgclusters",
"pgpolicies",
"pgreplicas",
"pgtasks",
)
} else if resourceType(resource) == "ps" {
resources = append(resources,
"perconaservermysqlbackups",
"perconaservermysqlrestores",
"perconaservermysqls",
)
}
}
return Dumper{
cmd: "kubectl",
kubeconfig: kubeconfig,
resources: resources,
filePaths: filePaths,
location: "cluster-dump",
mode: int64(0o777),
namespace: namespace,
crType: resource,
forwardport: forwardport,
}
}
@@ -187,11 +202,14 @@ func (d *Dumper) DumpCluster() error {
if len(pod.Labels) == 0 {
continue
}
location = filepath.Join(d.location, ns.Name, pod.Name, "/pt-summary.txt")
location = filepath.Join(d.location, ns.Name, pod.Name, "/summary.txt")
component := resourceType(d.crType)
if component == "psmdb" {
component = "mongod"
}
if component == "ps" {
component = "mysql"
}
if pod.Labels["app.kubernetes.io/instance"] != "" && pod.Labels["app.kubernetes.io/component"] != "" {
resource := "secret/" + pod.Labels["app.kubernetes.io/instance"] + "-" + pod.Labels["app.kubernetes.io/component"]
err = d.getResource(resource, ns.Name, true, tw)
@@ -199,20 +217,27 @@ func (d *Dumper) DumpCluster() error {
log.Printf("Error: get %s resource: %v", resource, err)
}
}
if pod.Labels["app.kubernetes.io/component"] == component {
if pod.Labels["app.kubernetes.io/component"] == component ||
(component == "pg" && pod.Labels["pgo-pg-database"] == "true") {
var crName string
if component == "pg" {
crName = pod.Labels["pg-cluster"]
} else {
crName = pod.Labels["app.kubernetes.io/instance"]
}
// Get summary
output, err = d.getPodSummary(resourceType(d.crType), pod.Name, pod.Labels["app.kubernetes.io/instance"], tw)
output, err = d.getPodSummary(resourceType(d.crType), pod.Name, crName, ns.Name, tw)
if err != nil {
d.logError(err.Error(), d.crType, pod.Name)
err = addToArchive(location, d.mode, []byte(err.Error()), tw)
if err != nil {
log.Printf("Error: create pt-summary errors archive for pod %s in namespace %s: %v", pod.Name, ns.Name, err)
log.Printf("Error: create summary errors archive for pod %s in namespace %s: %v", pod.Name, ns.Name, err)
}
} else {
err = addToArchive(location, d.mode, output, tw)
if err != nil {
d.logError(err.Error(), "create pt-summary archive for pod "+pod.Name)
log.Printf("Error: create pt-summary archive for pod %s: %v", pod.Name, err)
d.logError(err.Error(), "create summary archive for pod "+pod.Name)
log.Printf("Error: create summary archive for pod %s: %v", pod.Name, err)
}
}
@@ -247,6 +272,7 @@ func (d *Dumper) DumpCluster() error {
// runCmd run command (Dumper.cmd) with given args, return it output
func (d *Dumper) runCmd(args ...string) ([]byte, error) {
var outb, errb bytes.Buffer
args = append(args, "--kubeconfig", d.kubeconfig)
cmd := exec.Command(d.cmd, args...)
cmd.Stdout = &outb
cmd.Stderr = &errb
@@ -328,7 +354,7 @@ func (d *Dumper) getIndividualFiles(resource, namespace string, podName, path, l
return addToArchive(location+"/"+path, d.mode, output, tw)
}
func (d *Dumper) getPodSummary(resource, podName, crName string, tw *tar.Writer) ([]byte, error) {
func (d *Dumper) getPodSummary(resource, podName, crName string, namespace string, tw *tar.Writer) ([]byte, error) {
var (
summCmdName string
ports string
@@ -336,33 +362,86 @@ func (d *Dumper) getPodSummary(resource, podName, crName string, tw *tar.Writer)
)
switch resource {
case "ps":
fallthrough
case "pxc":
cr, err := d.getCR("pxc/" + crName)
var pass, port string
if d.forwardport != "" {
port = d.forwardport
} else {
port = "3306"
}
cr, err := d.getCR(resource+"/"+crName, namespace)
if err != nil {
return nil, errors.Wrap(err, "get cr")
}
pass, err := d.getDataFromSecret(cr.Spec.SecretName, "root")
if cr.Spec.SecretName != "" {
pass, err = d.getDataFromSecret(cr.Spec.SecretName, "root", namespace)
} else {
pass, err = d.getDataFromSecret(crName+"-secrets", "root", namespace)
}
if err != nil {
return nil, errors.Wrap(err, "get password from pxc users secret")
}
ports = "3306:3306"
ports = port + ":3306"
summCmdName = "pt-mysql-summary"
summCmdArgs = []string{"--host=127.0.0.1", "--port=3306", "--user=root", "--password=" + string(pass)}
case "psmdb":
cr, err := d.getCR("psmdb/" + crName)
summCmdArgs = []string{"--host=127.0.0.1", "--port=" + port, "--user=root", "--password=" + string(pass)}
case "pg":
var user, pass, port string
if d.forwardport != "" {
port = d.forwardport
} else {
port = "5432"
}
cr, err := d.getCR("pgclusters", namespace)
if err != nil {
return nil, errors.Wrap(err, "get cr")
}
pass, err := d.getDataFromSecret(cr.Spec.Secrets.Users, "MONGODB_CLUSTER_ADMIN_PASSWORD")
if cr.Spec.SecretName != "" {
user, err = d.getDataFromSecret(cr.Spec.SecretName, "username", namespace)
} else {
user, err = d.getDataFromSecret(crName+"-postgres-secret", "username", namespace)
}
if err != nil {
return nil, errors.Wrap(err, "get user from PostgreSQL users secret")
}
if cr.Spec.SecretName != "" {
pass, err = d.getDataFromSecret(cr.Spec.SecretName, "password", namespace)
} else {
pass, err = d.getDataFromSecret(crName+"-postgres-secret", "password", namespace)
}
if err != nil {
return nil, errors.Wrap(err, "get password from PostgreSQL users secret")
}
ports = port + ":5432"
summCmdName = "sh"
summCmdArgs = []string{"-c", "curl https://raw.githubusercontent.com/percona/support-snippets/master/postgresql/pg_gather/gather.sql" +
" 2>/dev/null | PGPASSWORD=" + string(pass) + " psql -X --host=127.0.0.1 --port=" + port + " --user=" + user}
case "psmdb":
var port string
if d.forwardport != "" {
port = d.forwardport
} else {
port = "27017"
}
cr, err := d.getCR("psmdb/"+crName, namespace)
if err != nil {
return nil, errors.Wrap(err, "get cr")
}
user, err := d.getDataFromSecret(cr.Spec.Secrets.Users, "MONGODB_DATABASE_ADMIN_USER", namespace)
if err != nil {
return nil, errors.Wrap(err, "get password from psmdb users secret")
}
ports = "27017:27017"
pass, err := d.getDataFromSecret(cr.Spec.Secrets.Users, "MONGODB_DATABASE_ADMIN_PASSWORD", namespace)
if err != nil {
return nil, errors.Wrap(err, "get password from psmdb users secret")
}
ports = port + ":27017"
summCmdName = "pt-mongodb-summary"
summCmdArgs = []string{"--username=clusterAdmin", "--password=" + pass, "--authenticationDatabase=admin", "127.0.0.1:27017"}
summCmdArgs = []string{"--username=" + user, "--password=" + pass, "--authenticationDatabase=admin", "127.0.0.1:" + port}
}
cmdPortFwd := exec.Command(d.cmd, "port-forward", "pod/"+podName, ports)
cmdPortFwd := exec.Command(d.cmd, "port-forward", "pod/"+podName, ports, "-n", namespace, "--kubeconfig", d.kubeconfig)
go func() {
err := cmdPortFwd.Run()
if err != nil {
@@ -390,22 +469,22 @@ func (d *Dumper) getPodSummary(resource, podName, crName string, tw *tar.Writer)
return []byte(fmt.Sprintf("stderr: %s, stdout: %s", errb.String(), outb.String())), nil
}
func (d *Dumper) getCR(crName string) (crSecrets, error) {
func (d *Dumper) getCR(crName string, namespace string) (crSecrets, error) {
var cr crSecrets
output, err := d.runCmd("get", crName, "-o", "json")
output, err := d.runCmd("get", crName, "-o", "json", "-n", namespace)
if err != nil {
return cr, errors.Wrap(err, "get "+crName)
}
err = json.Unmarshal(output, &cr)
if err != nil {
return cr, errors.Wrap(err, "unmarshal psmdb cr")
return cr, errors.Wrap(err, "unmarshal "+crName+" cr")
}
return cr, nil
}
func (d *Dumper) getDataFromSecret(secretName, dataName string) (string, error) {
passEncoded, err := d.runCmd("get", "secrets/"+secretName, "--template={{.data."+dataName+"}}")
func (d *Dumper) getDataFromSecret(secretName, dataName string, namespace string) (string, error) {
passEncoded, err := d.runCmd("get", "secrets/"+secretName, "--template={{.data."+dataName+"}}", "-n", namespace)
if err != nil {
return "", errors.Wrap(err, "run get secret cmd")
}
@@ -422,6 +501,10 @@ func resourceType(s string) string {
return "pxc"
} else if s == "psmdb" || strings.HasPrefix(s, "psmdb/") {
return "psmdb"
} else if s == "pg" || strings.HasPrefix(s, "pg/") {
return "pg"
} else if s == "ps" || strings.HasPrefix(s, "ps/") {
return "ps"
}
return s
}

View File

@@ -12,17 +12,21 @@ func main() {
namespace := ""
resource := ""
clusterName := ""
kubeconfig := ""
forwardport := ""
flag.StringVar(&namespace, "namespace", "", "Namespace for collecting data. If empty data will be collected from all namespaces")
flag.StringVar(&resource, "resource", "pxc", "Resource name. Default value - 'pxc'")
flag.StringVar(&resource, "resource", "none", "Collect data, specific to the resource. Supported values: pxc, psmdb, pg, ps, none")
flag.StringVar(&clusterName, "cluster", "", "Cluster name")
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to kubeconfig")
flag.StringVar(&forwardport, "forwardport", "", "Port to use for port forwarding")
flag.Parse()
if len(clusterName) > 0 {
resource += "/" + clusterName
}
d := dumper.New("", namespace, resource)
d := dumper.New("", namespace, resource, kubeconfig, forwardport)
log.Println("Start collecting cluster data")
err := d.DumpCluster()

View File

@@ -2,6 +2,7 @@ package main
import (
"bytes"
"os"
"os/exec"
"path"
"strings"
@@ -10,11 +11,33 @@ import (
"golang.org/x/exp/slices"
)
/*
This test requires:
- Running K8 Operator installation
- kubectl configuration files, one for each supported operator
-- KUBECONFIG_PXC for K8SPXC
-- KUBECONFIG_PS for K8SPS
-- KUBECONFIG_PSMDB for K8SPSMDB
-- KUBECONFIG_PG for K8SPG
You can additionally set option FORWARDPORT if you want to use custom port when testing summaries.
pt-mysql-summary and pt-mongodb-summary must be in the PATH.
Since running pt-k8s-debug-collector may take long time run go test with increase timeout:
go test -timeout 6000s
We do not explicitly test --kubeconfig and --forwardport options, because they are used in other tests.
*/
/*
Tests collection of the individual files by pt-k8s-debug-collector.
Requires running K8SPXC instance and kubectl, configured to access that instance by default.
*/
func TestIndividualFiles(t *testing.T) {
if os.Getenv("KUBECONFIG_PXC") == "" {
t.Skip("TestIndividualFiles requires K8SPXC")
}
tests := []struct {
name string
cmd []string
@@ -56,7 +79,7 @@ func TestIndividualFiles(t *testing.T) {
},
}
cmd := exec.Command("../../../bin/pt-k8s-debug-collector")
cmd := exec.Command("../../../bin/pt-k8s-debug-collector", "--kubeconfig", os.Getenv("KUBECONFIG_PXC"), "--forwardport", os.Getenv("FORWARDPORT"), "--resource", "pxc")
if err := cmd.Run(); err != nil {
t.Errorf("error executing pt-k8s-debug-collector: %s", err.Error())
}
@@ -77,3 +100,61 @@ func TestIndividualFiles(t *testing.T) {
}
}
}
/*
Tests for supported values of the --resource option
*/
func TestResourceOption(t *testing.T) {
testcmd := []string{"sh", "-c", "tar -tf cluster-dump.tar.gz --wildcards '*/summary.txt' 2>/dev/null | wc -l"}
tests := []struct {
name string
want string
kubeconfig string
}{
{
name: "none",
want: "0",
kubeconfig: "",
},
{
name: "pxc",
want: "3",
kubeconfig: os.Getenv("KUBECONFIG_PXC"),
},
{
name: "ps",
want: "3",
kubeconfig: os.Getenv("KUBECONFIG_PS"),
},
{
name: "psmdb",
want: "3",
kubeconfig: os.Getenv("KUBECONFIG_PSMDB"),
},
{
name: "pg",
want: "3",
kubeconfig: os.Getenv("KUBECONFIG_PG"),
},
}
for _, test := range tests {
cmd := exec.Command("../../../bin/pt-k8s-debug-collector", "--kubeconfig", test.kubeconfig, "--forwardport", os.Getenv("FORWARDPORT"), "--resource", test.name)
if err := cmd.Run(); err != nil {
t.Errorf("error executing pt-k8s-debug-collector: %s", err.Error())
}
defer func() {
cmd = exec.Command("rm", "-f", "cluster-dump.tar.gz")
if err := cmd.Run(); err != nil {
t.Errorf("error cleaning up test data: %s", err.Error())
}
}()
out, err := exec.Command(testcmd[0], testcmd[1:]...).Output()
if err != nil {
t.Errorf("test %s, error running command %s:\n%s\n\nCommand output:\n%s", test.name, testcmd, err.Error(), out)
}
if strings.TrimRight(bytes.NewBuffer(out).String(), "\n") != test.want {
t.Errorf("test %s, output is not as expected\nOutput: %s\nWanted: %s", test.name, out, test.want)
}
}
}