mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Add per-collector subcommands to the collect binary (#2071)
* Add per-collector subcommands to the collect binary Add `collect http|postgres|mysql|mssql|redis` subcommands that run a single collector and print its native result JSON to stdout, so a collector can run inside a Pod via the troubleshoot image (e.g. as a runPod collector). Each has its own flags mapping to the collector's spec fields and its own help. The Kubernetes client (used only for TLS-from-Secret) is built to match the production preflight/support-bundle path (QPS/Burst/UserAgent). * Add clickhouse subcommand to the collect binary Add `collect clickhouse`, matching the other per-collector subcommands, so the clickhouse collector can run inside a Pod via the troubleshoot image (e.g. as a runPod collector). Same flags as the other database collectors (--uri + --tls-*). * Make global flags work on the collect subcommands Register --debug and the Kubernetes flags (--kubeconfig, --context, etc.) as persistent flags, and move the shared setup to PersistentPreRun/PersistentPostRun, so the per-collector subcommands inherit the global flags and run the same logger/profiling setup as `collect [url]`. Previously these were local flags with setup in PreRun, so subcommands rejected --debug/--kubeconfig and ignored the setup.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// ClickhouseCmd runs the clickhouse collector against a single database and
|
||||
// prints the native result JSON ({"isConnected":..,"version":..,"error":..}).
|
||||
func ClickhouseCmd() *cobra.Command {
|
||||
var (
|
||||
uri string
|
||||
skipVerify bool
|
||||
caCert string
|
||||
clientCert string
|
||||
clientKey string
|
||||
secretName string
|
||||
secretNamespace string
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "clickhouse",
|
||||
Short: "Run the clickhouse collector against a database",
|
||||
Long: `Run the clickhouse collector: connect to a ClickHouse server, run "SELECT version()",
|
||||
and print the collector result as JSON.
|
||||
|
||||
--uri is a clickhouse-go DSN:
|
||||
clickhouse://user:password@host:9000/dbname
|
||||
|
||||
TLS material may be provided inline / by file path (--tls-cacert, --tls-client-cert,
|
||||
--tls-client-key) or sourced from a Secret (--tls-secret-name), which requires
|
||||
cluster access.
|
||||
|
||||
Example:
|
||||
collect clickhouse --uri "clickhouse://default:@ch.default.svc:9000/default"`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
db := &troubleshootv1beta2.Database{
|
||||
CollectorMeta: troubleshootv1beta2.CollectorMeta{CollectorName: "clickhouse"},
|
||||
URI: uri,
|
||||
}
|
||||
|
||||
var (
|
||||
client kubernetes.Interface
|
||||
cfg *rest.Config
|
||||
)
|
||||
if skipVerify || caCert != "" || clientCert != "" || clientKey != "" || secretName != "" {
|
||||
tls := &troubleshootv1beta2.TLSParams{
|
||||
SkipVerify: skipVerify,
|
||||
CACert: caCert,
|
||||
ClientCert: clientCert,
|
||||
ClientKey: clientKey,
|
||||
}
|
||||
if secretName != "" {
|
||||
tls.Secret = &troubleshootv1beta2.TLSSecret{Name: secretName, Namespace: secretNamespace}
|
||||
var err error
|
||||
client, cfg, err = k8sClientForCollectors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
db.TLS = tls
|
||||
}
|
||||
|
||||
c := &collect.CollectClickhouse{Collector: db, ClientConfig: cfg, Client: client, Context: cmd.Context()}
|
||||
res, err := c.Collect(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printCollectorResult(res)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&uri, "uri", "", "ClickHouse connection DSN, e.g. clickhouse://user:pass@host:9000/db (required)")
|
||||
cmd.MarkFlagRequired("uri")
|
||||
f.BoolVar(&skipVerify, "tls-skip-verify", false, "skip TLS certificate verification")
|
||||
f.StringVar(&caCert, "tls-cacert", "", "CA certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientCert, "tls-client-cert", "", "client certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientKey, "tls-client-key", "", "client key (PEM contents or a file path)")
|
||||
f.StringVar(&secretName, "tls-secret-name", "", "name of a Secret holding TLS material (requires cluster access)")
|
||||
f.StringVar(&secretNamespace, "tls-secret-namespace", "default", "namespace of the TLS Secret")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Package cli implements the `collect` command and its subcommands.
|
||||
//
|
||||
// The per-collector subcommands (http, postgres, mysql, mssql, redis) run a
|
||||
// single collector and print its native result JSON to stdout. This lets a
|
||||
// collector run inside a Pod using the troubleshoot image — e.g. as a runPod
|
||||
// collector — so the check executes from within the cluster instead of from
|
||||
// wherever the CLI happens to be invoked.
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/constants"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/version"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// printCollectorResult writes the native collector result JSON to stdout.
|
||||
// The single-collector subcommands run with an empty BundlePath, so the result
|
||||
// is held in memory (map value = the JSON bytes) rather than written to disk.
|
||||
func printCollectorResult(res collect.CollectorResult) error {
|
||||
for _, b := range res {
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// k8sClientForCollectors builds a Kubernetes client from the ambient kubeconfig
|
||||
// or in-cluster config. Only the collectors that resolve TLS material from a
|
||||
// Secret need this; plain connections and inline/file TLS do not.
|
||||
func k8sClientForCollectors() (kubernetes.Interface, *rest.Config, error) {
|
||||
cfg, err := k8sutil.GetRESTConfig()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
cfg.QPS = constants.DEFAULT_CLIENT_QPS
|
||||
cfg.Burst = constants.DEFAULT_CLIENT_BURST
|
||||
cfg.UserAgent = fmt.Sprintf("%s/%s", constants.DEFAULT_CLIENT_USER_AGENT, version.Version())
|
||||
client, err := kubernetes.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return client, cfg, nil
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// HTTPCmd runs the http collector against a single endpoint and prints the
|
||||
// native result JSON ({"response":{"status":...}} or {"error":{...}}).
|
||||
func HTTPCmd() *cobra.Command {
|
||||
var (
|
||||
method string
|
||||
url string
|
||||
headers map[string]string
|
||||
body string
|
||||
timeout string
|
||||
proxy string
|
||||
insecure bool
|
||||
caCert string
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "http",
|
||||
Short: "Run the http collector against an endpoint",
|
||||
Long: `Run the http collector: issue an HTTP request and print the collector result as JSON.
|
||||
|
||||
The result contains the response status, body and headers, or an error object.
|
||||
|
||||
Examples:
|
||||
collect http --url http://myapp.default.svc:8080/healthz
|
||||
collect http --method POST --url https://api.internal/ping \
|
||||
--header 'Content-Type=application/json' --body '{"ping":true}'`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var tls *troubleshootv1beta2.TLSParams
|
||||
if caCert != "" {
|
||||
tls = &troubleshootv1beta2.TLSParams{CACert: caCert}
|
||||
}
|
||||
|
||||
spec := &troubleshootv1beta2.HTTP{
|
||||
CollectorMeta: troubleshootv1beta2.CollectorMeta{CollectorName: "http"},
|
||||
}
|
||||
switch strings.ToUpper(method) {
|
||||
case "GET":
|
||||
spec.Get = &troubleshootv1beta2.Get{URL: url, Headers: headers, Timeout: timeout, Proxy: proxy, InsecureSkipVerify: insecure, TLS: tls}
|
||||
case "POST":
|
||||
spec.Post = &troubleshootv1beta2.Post{URL: url, Headers: headers, Body: body, Timeout: timeout, Proxy: proxy, InsecureSkipVerify: insecure, TLS: tls}
|
||||
case "PUT":
|
||||
spec.Put = &troubleshootv1beta2.Put{URL: url, Headers: headers, Body: body, Timeout: timeout, Proxy: proxy, InsecureSkipVerify: insecure, TLS: tls}
|
||||
default:
|
||||
return fmt.Errorf("unsupported --method %q (use GET, POST, or PUT)", method)
|
||||
}
|
||||
|
||||
c := &collect.CollectHTTP{Collector: spec}
|
||||
res, err := c.Collect(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printCollectorResult(res)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&url, "url", "", "request URL (required)")
|
||||
cmd.MarkFlagRequired("url")
|
||||
f.StringVar(&method, "method", "GET", "HTTP method: GET, POST, or PUT")
|
||||
f.StringToStringVar(&headers, "header", nil, "request header as key=value (repeatable)")
|
||||
f.StringVar(&body, "body", "", "request body (POST/PUT only)")
|
||||
f.StringVar(&timeout, "timeout", "", "request timeout, e.g. 15s (empty = no timeout)")
|
||||
f.StringVar(&proxy, "proxy", "", "proxy URL to use for the request")
|
||||
f.BoolVar(&insecure, "insecure-skip-verify", false, "do not verify the server's TLS certificate")
|
||||
f.StringVar(&caCert, "tls-cacert", "", "CA certificate to trust (PEM contents or a file path)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// MssqlCmd runs the mssql collector against a single database and prints the
|
||||
// native result JSON ({"isConnected":..,"version":..,"error":..}).
|
||||
//
|
||||
// Unlike the other database collectors, the mssql collector does not honor a
|
||||
// separate TLS field — TLS is configured through the connection URI query
|
||||
// parameters (e.g. encrypt=true) — so this subcommand only takes --uri.
|
||||
func MssqlCmd() *cobra.Command {
|
||||
var uri string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "mssql",
|
||||
Short: "Run the mssql collector against a database",
|
||||
Long: `Run the mssql collector: connect to a Microsoft SQL Server, run "select @@VERSION",
|
||||
and print the collector result as JSON.
|
||||
|
||||
--uri is a go-mssqldb connection URL; TLS options are passed as query parameters:
|
||||
sqlserver://user:password@host:1433?database=app&encrypt=true
|
||||
|
||||
Example:
|
||||
collect mssql --uri "sqlserver://sa:pass@mssql.default.svc:1433?encrypt=true"`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
db := &troubleshootv1beta2.Database{
|
||||
CollectorMeta: troubleshootv1beta2.CollectorMeta{CollectorName: "mssql"},
|
||||
URI: uri,
|
||||
}
|
||||
|
||||
c := &collect.CollectMssql{Collector: db, Context: cmd.Context()}
|
||||
res, err := c.Collect(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printCollectorResult(res)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&uri, "uri", "", "SQL Server connection URI, e.g. sqlserver://user:pass@host:1433 (required)")
|
||||
cmd.MarkFlagRequired("uri")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// MysqlCmd runs the mysql collector against a single database and prints the
|
||||
// native result JSON ({"isConnected":..,"version":..,"variables":..,"error":..}).
|
||||
func MysqlCmd() *cobra.Command {
|
||||
var (
|
||||
uri string
|
||||
parameters []string
|
||||
skipVerify bool
|
||||
caCert string
|
||||
clientCert string
|
||||
clientKey string
|
||||
secretName string
|
||||
secretNamespace string
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "mysql",
|
||||
Short: "Run the mysql collector against a database",
|
||||
Long: `Run the mysql collector: connect to a MySQL server, run "select version()",
|
||||
optionally collect server variables, and print the collector result as JSON.
|
||||
|
||||
--uri is a go-sql-driver DSN (note: not a URL):
|
||||
user:password@tcp(host:3306)/dbname
|
||||
|
||||
--parameters names server variables to collect via "SHOW VARIABLES"; the matching
|
||||
values are returned under "variables" in the result. This flag is unique to mysql.
|
||||
|
||||
Example:
|
||||
collect mysql --uri "root:pass@tcp(mysql.default.svc:3306)/" --parameters max_connections,version`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
db := &troubleshootv1beta2.Database{
|
||||
CollectorMeta: troubleshootv1beta2.CollectorMeta{CollectorName: "mysql"},
|
||||
URI: uri,
|
||||
Parameters: parameters,
|
||||
}
|
||||
|
||||
var (
|
||||
client kubernetes.Interface
|
||||
cfg *rest.Config
|
||||
)
|
||||
if skipVerify || caCert != "" || clientCert != "" || clientKey != "" || secretName != "" {
|
||||
tls := &troubleshootv1beta2.TLSParams{
|
||||
SkipVerify: skipVerify,
|
||||
CACert: caCert,
|
||||
ClientCert: clientCert,
|
||||
ClientKey: clientKey,
|
||||
}
|
||||
if secretName != "" {
|
||||
tls.Secret = &troubleshootv1beta2.TLSSecret{Name: secretName, Namespace: secretNamespace}
|
||||
var err error
|
||||
client, cfg, err = k8sClientForCollectors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
db.TLS = tls
|
||||
}
|
||||
|
||||
c := &collect.CollectMysql{Collector: db, ClientConfig: cfg, Client: client, Context: cmd.Context()}
|
||||
res, err := c.Collect(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printCollectorResult(res)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&uri, "uri", "", "MySQL connection DSN, e.g. user:pass@tcp(host:3306)/db (required)")
|
||||
cmd.MarkFlagRequired("uri")
|
||||
f.StringSliceVar(¶meters, "parameters", nil, "server variables to collect via SHOW VARIABLES (comma-separated or repeatable)")
|
||||
f.BoolVar(&skipVerify, "tls-skip-verify", false, "skip TLS certificate verification")
|
||||
f.StringVar(&caCert, "tls-cacert", "", "CA certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientCert, "tls-client-cert", "", "client certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientKey, "tls-client-key", "", "client key (PEM contents or a file path)")
|
||||
f.StringVar(&secretName, "tls-secret-name", "", "name of a Secret holding TLS material (requires cluster access)")
|
||||
f.StringVar(&secretNamespace, "tls-secret-namespace", "default", "namespace of the TLS Secret")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// PostgresCmd runs the postgres collector against a single database and prints
|
||||
// the native result JSON ({"isConnected":..,"version":..,"error":..}).
|
||||
func PostgresCmd() *cobra.Command {
|
||||
var (
|
||||
uri string
|
||||
skipVerify bool
|
||||
caCert string
|
||||
clientCert string
|
||||
clientKey string
|
||||
secretName string
|
||||
secretNamespace string
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "postgres",
|
||||
Short: "Run the postgres collector against a database",
|
||||
Long: `Run the postgres collector: connect to a PostgreSQL server, run "select version()",
|
||||
and print the collector result as JSON.
|
||||
|
||||
--uri is a libpq/pgx connection URI:
|
||||
postgres://user:password@host:5432/dbname?sslmode=disable
|
||||
|
||||
TLS material may be provided inline / by file path (--tls-cacert, --tls-client-cert,
|
||||
--tls-client-key) or sourced from a Secret (--tls-secret-name), which requires
|
||||
cluster access.
|
||||
|
||||
Example:
|
||||
collect postgres --uri "postgres://user:pass@pg.default.svc:5432/app?sslmode=disable"`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
db := &troubleshootv1beta2.Database{
|
||||
CollectorMeta: troubleshootv1beta2.CollectorMeta{CollectorName: "postgres"},
|
||||
URI: uri,
|
||||
}
|
||||
|
||||
var (
|
||||
client kubernetes.Interface
|
||||
cfg *rest.Config
|
||||
)
|
||||
if skipVerify || caCert != "" || clientCert != "" || clientKey != "" || secretName != "" {
|
||||
tls := &troubleshootv1beta2.TLSParams{
|
||||
SkipVerify: skipVerify,
|
||||
CACert: caCert,
|
||||
ClientCert: clientCert,
|
||||
ClientKey: clientKey,
|
||||
}
|
||||
if secretName != "" {
|
||||
tls.Secret = &troubleshootv1beta2.TLSSecret{Name: secretName, Namespace: secretNamespace}
|
||||
var err error
|
||||
client, cfg, err = k8sClientForCollectors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
db.TLS = tls
|
||||
}
|
||||
|
||||
c := &collect.CollectPostgres{Collector: db, ClientConfig: cfg, Client: client, Context: cmd.Context()}
|
||||
res, err := c.Collect(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printCollectorResult(res)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&uri, "uri", "", "PostgreSQL connection URI (required)")
|
||||
cmd.MarkFlagRequired("uri")
|
||||
f.BoolVar(&skipVerify, "tls-skip-verify", false, "skip TLS certificate verification")
|
||||
f.StringVar(&caCert, "tls-cacert", "", "CA certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientCert, "tls-client-cert", "", "client certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientKey, "tls-client-key", "", "client key (PEM contents or a file path)")
|
||||
f.StringVar(&secretName, "tls-secret-name", "", "name of a Secret holding TLS material (requires cluster access)")
|
||||
f.StringVar(&secretNamespace, "tls-secret-namespace", "default", "namespace of the TLS Secret")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// RedisCmd runs the redis collector against a single instance and prints the
|
||||
// native result JSON ({"isConnected":..,"version":..,"error":..}).
|
||||
func RedisCmd() *cobra.Command {
|
||||
var (
|
||||
uri string
|
||||
skipVerify bool
|
||||
caCert string
|
||||
clientCert string
|
||||
clientKey string
|
||||
secretName string
|
||||
secretNamespace string
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "redis",
|
||||
Short: "Run the redis collector against an instance",
|
||||
Long: `Run the redis collector: connect to a Redis server, read "INFO server" (server
|
||||
version), and print the collector result as JSON.
|
||||
|
||||
--uri is a go-redis connection URL:
|
||||
redis://host:6379 (plaintext)
|
||||
rediss://user:pass@host:6379 (TLS)
|
||||
|
||||
TLS material may be provided inline / by file path (--tls-cacert, --tls-client-cert,
|
||||
--tls-client-key) or sourced from a Secret (--tls-secret-name), which requires
|
||||
cluster access.
|
||||
|
||||
Example:
|
||||
collect redis --uri "redis://redis.default.svc:6379"`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
db := &troubleshootv1beta2.Database{
|
||||
CollectorMeta: troubleshootv1beta2.CollectorMeta{CollectorName: "redis"},
|
||||
URI: uri,
|
||||
}
|
||||
|
||||
var (
|
||||
client kubernetes.Interface
|
||||
cfg *rest.Config
|
||||
)
|
||||
if skipVerify || caCert != "" || clientCert != "" || clientKey != "" || secretName != "" {
|
||||
tls := &troubleshootv1beta2.TLSParams{
|
||||
SkipVerify: skipVerify,
|
||||
CACert: caCert,
|
||||
ClientCert: clientCert,
|
||||
ClientKey: clientKey,
|
||||
}
|
||||
if secretName != "" {
|
||||
tls.Secret = &troubleshootv1beta2.TLSSecret{Name: secretName, Namespace: secretNamespace}
|
||||
var err error
|
||||
client, cfg, err = k8sClientForCollectors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
db.TLS = tls
|
||||
}
|
||||
|
||||
c := &collect.CollectRedis{Collector: db, ClientConfig: cfg, Client: client, Context: cmd.Context()}
|
||||
res, err := c.Collect(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printCollectorResult(res)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&uri, "uri", "", "Redis connection URL, e.g. redis://host:6379 (required)")
|
||||
cmd.MarkFlagRequired("uri")
|
||||
f.BoolVar(&skipVerify, "tls-skip-verify", false, "skip TLS certificate verification")
|
||||
f.StringVar(&caCert, "tls-cacert", "", "CA certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientCert, "tls-client-cert", "", "client certificate (PEM contents or a file path)")
|
||||
f.StringVar(&clientKey, "tls-client-key", "", "client key (PEM contents or a file path)")
|
||||
f.StringVar(&secretName, "tls-secret-name", "", "name of a Secret holding TLS material (requires cluster access)")
|
||||
f.StringVar(&secretNamespace, "tls-secret-namespace", "default", "namespace of the TLS Secret")
|
||||
|
||||
return cmd
|
||||
}
|
||||
+17
-4
@@ -19,7 +19,9 @@ func RootCmd() *cobra.Command {
|
||||
Short: "Run a collector",
|
||||
Long: `Run a collector and output the results.`,
|
||||
SilenceUsage: true,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
// PersistentPreRun/PersistentPostRun (rather than PreRun/PostRun) so this
|
||||
// setup also runs for the per-collector subcommands, not just `collect [url]`.
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
v := viper.GetViper()
|
||||
v.BindPFlags(cmd.Flags())
|
||||
|
||||
@@ -38,7 +40,7 @@ func RootCmd() *cobra.Command {
|
||||
|
||||
return runCollect(v, args[0])
|
||||
},
|
||||
PostRun: func(cmd *cobra.Command, args []string) {
|
||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||
if err := util.StopProfiling(); err != nil {
|
||||
klog.Errorf("Failed to stop profiling: %v", err)
|
||||
}
|
||||
@@ -49,6 +51,17 @@ func RootCmd() *cobra.Command {
|
||||
|
||||
cmd.AddCommand(util.VersionCmd())
|
||||
|
||||
// Per-collector subcommands: run a single collector and print its native
|
||||
// result JSON. Each has its own flags and help. These let a collector run
|
||||
// inside a Pod via the troubleshoot image (e.g. as a runPod collector), so
|
||||
// the check executes from within the cluster rather than wherever the CLI runs.
|
||||
cmd.AddCommand(HTTPCmd())
|
||||
cmd.AddCommand(PostgresCmd())
|
||||
cmd.AddCommand(MysqlCmd())
|
||||
cmd.AddCommand(MssqlCmd())
|
||||
cmd.AddCommand(RedisCmd())
|
||||
cmd.AddCommand(ClickhouseCmd())
|
||||
|
||||
cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
|
||||
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
|
||||
cmd.Flags().String("format", "json", "output format, one of json or raw.")
|
||||
@@ -56,7 +69,7 @@ func RootCmd() *cobra.Command {
|
||||
cmd.Flags().String("collector-pull-policy", "", "the pull policy of the collector image")
|
||||
cmd.Flags().String("selector", "", "selector (label query) to filter remote collection nodes on.")
|
||||
cmd.Flags().Bool("collect-without-permissions", false, "always generate a support bundle, even if it some require additional permissions")
|
||||
cmd.Flags().Bool("debug", false, "enable debug logging")
|
||||
cmd.PersistentFlags().Bool("debug", false, "enable debug logging")
|
||||
cmd.Flags().String("chroot", "", "Chroot to path")
|
||||
|
||||
// hidden in favor of the `insecure-skip-tls-verify` flag
|
||||
@@ -67,7 +80,7 @@ func RootCmd() *cobra.Command {
|
||||
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
|
||||
k8sutil.AddFlags(cmd.Flags())
|
||||
k8sutil.AddFlags(cmd.PersistentFlags())
|
||||
|
||||
// Initialize klog flags
|
||||
logger.InitKlogFlags(cmd)
|
||||
|
||||
Reference in New Issue
Block a user