diff --git a/pkg/cmds/debug.go b/pkg/cmds/debug.go index 83b4d1435..769199dd0 100644 --- a/pkg/cmds/debug.go +++ b/pkg/cmds/debug.go @@ -50,12 +50,33 @@ func NewCmdDebug(f cmdutil.Factory) *cobra.Command { DisableAutoGenTag: true, } + // KubeDB v1 databases cmd.AddCommand(debug.ElasticsearchDebugCMD(f)) + cmd.AddCommand(debug.KafkaDebugCMD(f)) cmd.AddCommand(debug.MariaDBDebugCMD(f)) + cmd.AddCommand(debug.MemcachedDebugCMD(f)) cmd.AddCommand(debug.MongoDBDebugCMD(f)) cmd.AddCommand(debug.MySQLDebugCMD(f)) + cmd.AddCommand(debug.PerconaXtraDBDebugCMD(f)) + cmd.AddCommand(debug.PgBouncerDebugCMD(f)) cmd.AddCommand(debug.PostgresDebugCMD(f)) + cmd.AddCommand(debug.ProxySQLDebugCMD(f)) cmd.AddCommand(debug.RedisDebugCMD(f)) + // KubeDB v1alpha2 databases + cmd.AddCommand(debug.CassandraDebugCMD(f)) + cmd.AddCommand(debug.ClickHouseDebugCMD(f)) + cmd.AddCommand(debug.DruidDebugCMD(f)) + cmd.AddCommand(debug.FerretDBDebugCMD(f)) + cmd.AddCommand(debug.HazelcastDebugCMD(f)) + cmd.AddCommand(debug.IgniteDebugCMD(f)) + cmd.AddCommand(debug.MSSQLServerDebugCMD(f)) + cmd.AddCommand(debug.OracleDebugCMD(f)) + cmd.AddCommand(debug.PgpoolDebugCMD(f)) + cmd.AddCommand(debug.RabbitMQDebugCMD(f)) + cmd.AddCommand(debug.SinglestoreDebugCMD(f)) + cmd.AddCommand(debug.SolrDebugCMD(f)) + cmd.AddCommand(debug.ZooKeeperDebugCMD(f)) + return cmd } diff --git a/pkg/debug/cassandra.go b/pkg/debug/cassandra.go new file mode 100644 index 000000000..b5eaa77e2 --- /dev/null +++ b/pkg/debug/cassandra.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func CassandraDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "cassandra", + Aliases: []string{ + "cs", + "cassandras", + }, + Short: "Debug helper for Cassandra database", + Example: `kubectl dba debug cassandra -n demo sample-cassandra --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter cassandra object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindCassandra + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Cassandra + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/clickhouse.go b/pkg/debug/clickhouse.go new file mode 100644 index 000000000..03cce975c --- /dev/null +++ b/pkg/debug/clickhouse.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func ClickHouseDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "clickhouse", + Aliases: []string{ + "cl", + "clickhouses", + }, + Short: "Debug helper for ClickHouse database", + Example: `kubectl dba debug clickhouse -n demo sample-clickhouse --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter clickhouse object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindClickHouse + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.ClickHouse + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/common.go b/pkg/debug/common.go new file mode 100644 index 000000000..2159b2599 --- /dev/null +++ b/pkg/debug/common.go @@ -0,0 +1,287 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "bytes" + "context" + "fmt" + "os" + "path" + + autoscalerapi "kubedb.dev/apimachinery/apis/autoscaling/v1alpha1" + opsapi "kubedb.dev/apimachinery/apis/ops/v1alpha1" + kubedbscheme "kubedb.dev/apimachinery/client/clientset/versioned/scheme" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + _ "k8s.io/client-go/plugin/pkg/client/auth" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + psapi "kubeops.dev/petset/apis/apps/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var scheme = runtime.NewScheme() + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(kubedbscheme.AddToScheme(scheme)) + utilruntime.Must(psapi.AddToScheme(scheme)) +} + +type dbOpts struct { + kc client.Client + kubeClient *kubernetes.Clientset + kind string + db metav1.ObjectMeta + selectors map[string]string + + operatorNamespace string + dir string + errWriter *bytes.Buffer +} + +func newDBOpts(f cmdutil.Factory, gvk schema.GroupVersionKind, dbName, namespace, operatorNS string) (*dbOpts, error) { + config, err := f.ToRESTConfig() + if err != nil { + return nil, err + } + + kubeClient, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } + + kc, err := client.New(config, client.Options{Scheme: scheme}) + if err != nil { + return nil, err + } + + pwd, _ := os.Getwd() + dir := path.Join(pwd, dbName) + err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) + if err != nil { + return nil, err + } + err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) + if err != nil { + return nil, err + } + + opts := &dbOpts{ + kc: kc, + kubeClient: kubeClient, + kind: gvk.Kind, + db: metav1.ObjectMeta{Namespace: namespace, Name: dbName}, + operatorNamespace: operatorNS, + dir: dir, + errWriter: &bytes.Buffer{}, + } + return opts, nil +} + +func (opts *dbOpts) collectALl() error { + err := opts.collectOperatorLogs() + if err != nil { + return err + } + err = opts.collectForAllDBPetSets() + if err != nil { + return err + } + err = opts.collectForAllDBPods() + if err != nil { + return err + } + err = opts.collectOtherYamls() + if err != nil { + return err + } + return nil +} + +func (opts *dbOpts) collectOperatorLogs() error { + var pods corev1.PodList + err := opts.kc.List(context.TODO(), &pods, client.InNamespace(opts.operatorNamespace)) + if err != nil { + return err + } + for _, pod := range pods.Items { + isOperatorPod := false + for _, container := range pod.Spec.Containers { + if container.Name == operatorContainerName { + isOperatorPod = true + } + } + if isOperatorPod { + err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) + if err != nil { + return err + } + } + } + return nil +} + +func (opts *dbOpts) collectForAllDBPetSets() error { + var petsets psapi.PetSetList + err := opts.kc.List(context.TODO(), &petsets, client.MatchingLabels(opts.selectors), client.InNamespace(opts.db.GetNamespace())) + if err != nil { + return err + } + + psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") + err = os.MkdirAll(psYamlDir, dirPerm) + if err != nil { + return err + } + + for _, p := range petsets.Items { + err = writeYaml(&p, psYamlDir) + if err != nil { + return err + } + + } + return nil +} + +func (opts *dbOpts) collectForAllDBPods() error { + var pods corev1.PodList + err := opts.kc.List(context.TODO(), &pods, client.MatchingLabels(opts.selectors), client.InNamespace(opts.db.GetNamespace())) + if err != nil { + return err + } + + podYamlDir := path.Join(opts.dir, yamlsDir) + for _, pod := range pods.Items { + err = opts.writeLogsForSinglePod(pod) + if err != nil { + return err + } + + err = writeYaml(&pod, podYamlDir) + if err != nil { + return err + } + + } + return nil +} + +func (opts *dbOpts) writeLogsForSinglePod(pod corev1.Pod) error { + for _, c := range pod.Spec.Containers { + err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) + if err != nil { + return err + } + } + return nil +} + +func (opts *dbOpts) writeLogs(podName, ns, container string) error { + req := opts.kubeClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ + Container: container, + }) + + podLogs, err := req.Stream(context.TODO()) + if err != nil { + return err + } + defer podLogs.Close() + + logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) + if err != nil { + return err + } + defer logFile.Close() + + buf := make([]byte, 1024) + for { + bytesRead, err := podLogs.Read(buf) + if err != nil { + break + } + _, _ = logFile.Write(buf[:bytesRead]) + } + return nil +} + +func (opts *dbOpts) collectOtherYamls() error { + var opsReqs unstructured.UnstructuredList + opsReqs.SetGroupVersionKind(schema.GroupVersionKind{ + Group: opsapi.SchemeGroupVersion.Group, + Version: opsapi.SchemeGroupVersion.Version, + Kind: opts.kind + "OpsRequest", + }) + if err := opts.kc.List(context.Background(), &opsReqs, client.InNamespace(opts.db.GetNamespace())); err != nil { + return err + } + + opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") + err := os.MkdirAll(opsYamlDir, dirPerm) + if err != nil { + return err + } + for _, o := range opsReqs.Items { + var ops OpsRequest + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(o.Object, &ops); err != nil { + return fmt.Errorf("failed to unmarshal binding %s: %w", o.GetName(), err) + } + if ops.Spec.DatabaseRef.Name == opts.db.GetName() { + err = writeYaml(&o, opsYamlDir) + if err != nil { + return err + } + } + } + + var autoscalers unstructured.UnstructuredList + autoscalers.SetGroupVersionKind(schema.GroupVersionKind{ + Group: autoscalerapi.SchemeGroupVersion.Group, + Version: autoscalerapi.SchemeGroupVersion.Version, + Kind: opts.kind + "Autoscaler", + }) + if err := opts.kc.List(context.Background(), &autoscalers, client.InNamespace(opts.db.GetNamespace())); err != nil { + return err + } + + scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") + err = os.MkdirAll(scalerYamlDir, dirPerm) + if err != nil { + return err + } + for _, sc := range autoscalers.Items { + var autoscaler Autoscaler + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(sc.Object, &autoscaler); err != nil { + return fmt.Errorf("failed to unmarshal binding %s: %w", sc.GetName(), err) + } + if autoscaler.Spec.DatabaseRef.Name == opts.db.GetName() { + err = writeYaml(&sc, scalerYamlDir) + if err != nil { + return err + } + } + } + return nil +} diff --git a/pkg/debug/druid.go b/pkg/debug/druid.go new file mode 100644 index 000000000..4b6439f10 --- /dev/null +++ b/pkg/debug/druid.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func DruidDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "druid", + Aliases: []string{ + "dr", + "druids", + }, + Short: "Debug helper for Druid database", + Example: `kubectl dba debug druid -n demo sample-druid --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter druid object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindDruid + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Druid + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/elasticsearch.go b/pkg/debug/elasticsearch.go index c547bd803..0a0d3ce84 100644 --- a/pkg/debug/elasticsearch.go +++ b/pkg/debug/elasticsearch.go @@ -17,50 +17,32 @@ limitations under the License. package debug import ( - "bytes" "context" "log" - "os" - "path" dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" - cs "kubedb.dev/apimachinery/client/clientset/versioned" "github.com/spf13/cobra" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" - ps "kubeops.dev/petset/client/clientset/versioned" ) -type elasticsearchOpts struct { - db *dbapi.Elasticsearch - dbClient *cs.Clientset - psClient *ps.Clientset - podClient *kubernetes.Clientset - - operatorNamespace string - dir string - errWriter *bytes.Buffer -} - func ElasticsearchDebugCMD(f cmdutil.Factory) *cobra.Command { var ( dbName string operatorNamespace string ) - esDebugCmd := &cobra.Command{ + mdDebugCmd := &cobra.Command{ Use: "elasticsearch", Aliases: []string{ "es", "elasticsearches", }, - Short: "Debug helper for elasticsearch database", + Short: "Debug helper for Elasticsearch database", Example: `kubectl dba debug elasticsearch -n demo sample-elasticsearch --operator-namespace kubedb`, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 { @@ -73,231 +55,38 @@ func ElasticsearchDebugCMD(f cmdutil.Factory) *cobra.Command { klog.Error(err, "failed to get current namespace") } - opts, err := newElasticsearchOpts(f, dbName, namespace, operatorNamespace) + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindElasticsearch + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) if err != nil { log.Fatalln(err) } - err = opts.collectOperatorLogs() + var db dbapi.Elasticsearch + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) if err != nil { - log.Fatal(err) - } - - err = opts.collectForAllDBPetSets() - if err != nil { - log.Fatal(err) + log.Fatalln(err) } - err = opts.collectForAllDBPods() + err = writeYaml(&db, getDir(db.GetName())) if err != nil { - log.Fatal(err) + return } - - err = opts.collectOtherYamls() + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() if err != nil { - log.Fatal(err) + log.Fatalln(err) } }, } - esDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - - return esDebugCmd -} - -func newElasticsearchOpts(f cmdutil.Factory, dbName, namespace, operatorNS string) (*elasticsearchOpts, error) { - config, err := f.ToRESTConfig() - if err != nil { - return nil, err - } - - dbClient, err := cs.NewForConfig(config) - if err != nil { - return nil, err - } - - psClient, err := ps.NewForConfig(config) - if err != nil { - return nil, err - } - - podClient, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - db, err := dbClient.KubedbV1().Elasticsearches(namespace).Get(context.TODO(), dbName, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - pwd, _ := os.Getwd() - dir := path.Join(pwd, db.Name) - err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) - if err != nil { - return nil, err - } - err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) - if err != nil { - return nil, err - } - - opts := &elasticsearchOpts{ - db: db, - dbClient: dbClient, - psClient: psClient, - podClient: podClient, - operatorNamespace: operatorNS, - dir: dir, - errWriter: &bytes.Buffer{}, - } - return opts, writeYaml(db, path.Join(opts.dir, yamlsDir)) -} - -func (opts *elasticsearchOpts) collectOperatorLogs() error { - pods, err := opts.podClient.CoreV1().Pods(opts.operatorNamespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - for _, pod := range pods.Items { - isOperatorPod := false - for _, container := range pod.Spec.Containers { - if container.Name == operatorContainerName { - isOperatorPod = true - } - } - if isOperatorPod { - err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) - if err != nil { - return err - } - } - } - return nil -} - -func (opts *elasticsearchOpts) collectForAllDBPetSets() error { - psLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - petsets, err := opts.psClient.AppsV1().PetSets(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: psLabels, - }) - if err != nil { - return err - } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") - err = os.MkdirAll(psYamlDir, dirPerm) - if err != nil { - return err - } - - for _, p := range petsets.Items { - err = writeYaml(&p, psYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *elasticsearchOpts) collectForAllDBPods() error { - dbLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - pods, err := opts.podClient.CoreV1().Pods(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: dbLabels, - }) - if err != nil { - return err - } - - podYamlDir := path.Join(opts.dir, yamlsDir) - for _, pod := range pods.Items { - err = opts.writeLogsForSinglePod(pod) - if err != nil { - return err - } - - err = writeYaml(&pod, podYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *elasticsearchOpts) writeLogsForSinglePod(pod corev1.Pod) error { - for _, c := range pod.Spec.Containers { - err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) - if err != nil { - return err - } - } - return nil -} - -func (opts *elasticsearchOpts) writeLogs(podName, ns, container string) error { - req := opts.podClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ - Container: container, - }) - - podLogs, err := req.Stream(context.TODO()) - if err != nil { - return err - } - defer podLogs.Close() - - logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) - if err != nil { - return err - } - defer logFile.Close() - - buf := make([]byte, 1024) - for { - bytesRead, err := podLogs.Read(buf) - if err != nil { - break - } - _, _ = logFile.Write(buf[:bytesRead]) - } - return nil -} - -func (opts *elasticsearchOpts) collectOtherYamls() error { - opsReqs, err := opts.dbClient.OpsV1alpha1().ElasticsearchOpsRequests(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") - err = os.MkdirAll(opsYamlDir, dirPerm) - if err != nil { - return err - } - for _, ops := range opsReqs.Items { - if ops.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&ops, opsYamlDir) - if err != nil { - return err - } - } - } - - scalers, err := opts.dbClient.AutoscalingV1alpha1().ElasticsearchAutoscalers(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") - err = os.MkdirAll(scalerYamlDir, dirPerm) - if err != nil { - return err - } - for _, sc := range scalers.Items { - if sc.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&sc, scalerYamlDir) - if err != nil { - return err - } - } - } - return nil + return mdDebugCmd } diff --git a/pkg/debug/ferretdb.go b/pkg/debug/ferretdb.go new file mode 100644 index 000000000..ea7da0a26 --- /dev/null +++ b/pkg/debug/ferretdb.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func FerretDBDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "ferretdb", + Aliases: []string{ + "fr", + "ferretdbs", + }, + Short: "Debug helper for FerretDB database", + Example: `kubectl dba debug ferretdb -n demo sample-ferretdb --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter ferretdb object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindFerretDB + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.FerretDB + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/hazelcast.go b/pkg/debug/hazelcast.go new file mode 100644 index 000000000..4fb35c0f3 --- /dev/null +++ b/pkg/debug/hazelcast.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func HazelcastDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "hazelcast", + Aliases: []string{ + "hz", + "hazelcasts", + }, + Short: "Debug helper for Hazelcast database", + Example: `kubectl dba debug hazelcast -n demo sample-hazelcast --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter hazelcast object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindHazelcast + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Hazelcast + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/helpers.go b/pkg/debug/helpers.go index 57e2ec9d4..3ad2cd55f 100644 --- a/pkg/debug/helpers.go +++ b/pkg/debug/helpers.go @@ -31,3 +31,28 @@ func writeYaml(obj client.Object, fullPath string) error { } return os.WriteFile(path.Join(fullPath, obj.GetName()+".yaml"), b, filePerm) } + +func getDir(dbName string) string { + pwd, _ := os.Getwd() + dir := path.Join(pwd, dbName) + return dir +} + +type OpsRequest struct { + Spec OpsRequestSpec `json:"spec,omitempty" yaml:"spec,omitempty"` +} + +type OpsRequestSpec struct { + DatabaseRef DatabaseRef `json:"databaseRef,omitempty" yaml:"databaseRef,omitempty"` +} + +type Autoscaler struct { + Spec AutoscalerSpec `json:"spec,omitempty" yaml:"spec,omitempty"` +} + +type AutoscalerSpec struct { + DatabaseRef DatabaseRef `json:"databaseRef,omitempty" yaml:"databaseRef,omitempty"` +} +type DatabaseRef struct { + Name string `json:"name,omitempty" yaml:"name,omitempty"` +} diff --git a/pkg/debug/ignite.go b/pkg/debug/ignite.go new file mode 100644 index 000000000..d79d961b2 --- /dev/null +++ b/pkg/debug/ignite.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func IgniteDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "ignite", + Aliases: []string{ + "ig", + "ignites", + }, + Short: "Debug helper for Ignite database", + Example: `kubectl dba debug ignite -n demo sample-ignite --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter ignite object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindIgnite + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Ignite + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/kafka.go b/pkg/debug/kafka.go new file mode 100644 index 000000000..f18664a11 --- /dev/null +++ b/pkg/debug/kafka.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func KafkaDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "kafka", + Aliases: []string{ + "kf", + "kafkas", + }, + Short: "Debug helper for Kafka database", + Example: `kubectl dba debug kafka -n demo sample-kafka --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter kafka object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindKafka + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db dbapi.Kafka + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/mariadb.go b/pkg/debug/mariadb.go index 4682e249e..6a7260e5f 100644 --- a/pkg/debug/mariadb.go +++ b/pkg/debug/mariadb.go @@ -17,37 +17,19 @@ limitations under the License. package debug import ( - "bytes" "context" "log" - "os" - "path" dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" - cs "kubedb.dev/apimachinery/client/clientset/versioned" "github.com/spf13/cobra" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" - ps "kubeops.dev/petset/client/clientset/versioned" ) -type mariadbOpts struct { - db *dbapi.MariaDB - dbClient *cs.Clientset - psClient *ps.Clientset - podClient *kubernetes.Clientset - - operatorNamespace string - dir string - errWriter *bytes.Buffer -} - func MariaDBDebugCMD(f cmdutil.Factory) *cobra.Command { var ( dbName string @@ -60,7 +42,7 @@ func MariaDBDebugCMD(f cmdutil.Factory) *cobra.Command { "md", "mariadbs", }, - Short: "Debug helper for mariadb database", + Short: "Debug helper for MariaDB database", Example: `kubectl dba debug mariadb -n demo sample-mariadb --operator-namespace kubedb`, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 { @@ -73,29 +55,34 @@ func MariaDBDebugCMD(f cmdutil.Factory) *cobra.Command { klog.Error(err, "failed to get current namespace") } - opts, err := newMariadbOpts(f, dbName, namespace, operatorNamespace) + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindMariaDB + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) if err != nil { log.Fatalln(err) } - err = opts.collectOperatorLogs() + var db dbapi.MariaDB + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) if err != nil { - log.Fatal(err) - } - - err = opts.collectForAllDBPetSets() - if err != nil { - log.Fatal(err) + log.Fatalln(err) } - err = opts.collectForAllDBPods() + err = writeYaml(&db, getDir(db.GetName())) if err != nil { - log.Fatal(err) + return } - - err = opts.collectOtherYamls() + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() if err != nil { - log.Fatal(err) + log.Fatalln(err) } }, } @@ -103,201 +90,3 @@ func MariaDBDebugCMD(f cmdutil.Factory) *cobra.Command { return mdDebugCmd } - -func newMariadbOpts(f cmdutil.Factory, dbName, namespace, operatorNS string) (*mariadbOpts, error) { - config, err := f.ToRESTConfig() - if err != nil { - return nil, err - } - - dbClient, err := cs.NewForConfig(config) - if err != nil { - return nil, err - } - - psClient, err := ps.NewForConfig(config) - if err != nil { - return nil, err - } - - podClient, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - db, err := dbClient.KubedbV1().MariaDBs(namespace).Get(context.TODO(), dbName, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - pwd, _ := os.Getwd() - dir := path.Join(pwd, db.Name) - err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) - if err != nil { - return nil, err - } - err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) - if err != nil { - return nil, err - } - - opts := &mariadbOpts{ - db: db, - dbClient: dbClient, - psClient: psClient, - podClient: podClient, - operatorNamespace: operatorNS, - dir: dir, - errWriter: &bytes.Buffer{}, - } - return opts, writeYaml(db, path.Join(opts.dir, yamlsDir)) -} - -func (opts *mariadbOpts) collectOperatorLogs() error { - pods, err := opts.podClient.CoreV1().Pods(opts.operatorNamespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - for _, pod := range pods.Items { - isOperatorPod := false - for _, container := range pod.Spec.Containers { - if container.Name == operatorContainerName { - isOperatorPod = true - } - } - if isOperatorPod { - err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) - if err != nil { - return err - } - } - } - return nil -} - -func (opts *mariadbOpts) collectForAllDBPetSets() error { - psLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - petsets, err := opts.psClient.AppsV1().PetSets(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: psLabels, - }) - if err != nil { - return err - } - - psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") - err = os.MkdirAll(psYamlDir, dirPerm) - if err != nil { - return err - } - - for _, p := range petsets.Items { - err = writeYaml(&p, psYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *mariadbOpts) collectForAllDBPods() error { - dbLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - pods, err := opts.podClient.CoreV1().Pods(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: dbLabels, - }) - if err != nil { - return err - } - - podYamlDir := path.Join(opts.dir, yamlsDir) - for _, pod := range pods.Items { - err = opts.writeLogsForSinglePod(pod) - if err != nil { - return err - } - - err = writeYaml(&pod, podYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *mariadbOpts) writeLogsForSinglePod(pod corev1.Pod) error { - for _, c := range pod.Spec.Containers { - err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) - if err != nil { - return err - } - } - return nil -} - -func (opts *mariadbOpts) writeLogs(podName, ns, container string) error { - req := opts.podClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ - Container: container, - }) - - podLogs, err := req.Stream(context.TODO()) - if err != nil { - return err - } - defer podLogs.Close() - - logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) - if err != nil { - return err - } - defer logFile.Close() - - buf := make([]byte, 1024) - for { - bytesRead, err := podLogs.Read(buf) - if err != nil { - break - } - _, _ = logFile.Write(buf[:bytesRead]) - } - return nil -} - -func (opts *mariadbOpts) collectOtherYamls() error { - opsReqs, err := opts.dbClient.OpsV1alpha1().MariaDBOpsRequests(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") - err = os.MkdirAll(opsYamlDir, dirPerm) - if err != nil { - return err - } - for _, ops := range opsReqs.Items { - if ops.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&ops, opsYamlDir) - if err != nil { - return err - } - } - } - - scalers, err := opts.dbClient.AutoscalingV1alpha1().MariaDBAutoscalers(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") - err = os.MkdirAll(scalerYamlDir, dirPerm) - if err != nil { - return err - } - for _, sc := range scalers.Items { - if sc.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&sc, scalerYamlDir) - if err != nil { - return err - } - } - } - return nil -} diff --git a/pkg/debug/memcached.go b/pkg/debug/memcached.go new file mode 100644 index 000000000..c22ab0c40 --- /dev/null +++ b/pkg/debug/memcached.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func MemcachedDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "memcached", + Aliases: []string{ + "mc", + "memcacheds", + }, + Short: "Debug helper for Memcached database", + Example: `kubectl dba debug memcached -n demo sample-memcached --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter memcached object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindMemcached + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db dbapi.Memcached + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/mongodb.go b/pkg/debug/mongodb.go index c341f604f..612899a6c 100644 --- a/pkg/debug/mongodb.go +++ b/pkg/debug/mongodb.go @@ -17,50 +17,32 @@ limitations under the License. package debug import ( - "bytes" "context" "log" - "os" - "path" dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" - cs "kubedb.dev/apimachinery/client/clientset/versioned" "github.com/spf13/cobra" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" - ps "kubeops.dev/petset/client/clientset/versioned" ) -type mongodbOpts struct { - db *dbapi.MongoDB - dbClient *cs.Clientset - psClient *ps.Clientset - podClient *kubernetes.Clientset - - operatorNamespace string - dir string - errWriter *bytes.Buffer -} - func MongoDBDebugCMD(f cmdutil.Factory) *cobra.Command { var ( dbName string operatorNamespace string ) - mgDebugCmd := &cobra.Command{ + mdDebugCmd := &cobra.Command{ Use: "mongodb", Aliases: []string{ "mg", "mongodbs", }, - Short: "Debug helper for mongodb database", + Short: "Debug helper for MongoDB database", Example: `kubectl dba debug mongodb -n demo sample-mongodb --operator-namespace kubedb`, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 { @@ -73,231 +55,38 @@ func MongoDBDebugCMD(f cmdutil.Factory) *cobra.Command { klog.Error(err, "failed to get current namespace") } - opts, err := newMongodbOpts(f, dbName, namespace, operatorNamespace) + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindMongoDB + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) if err != nil { log.Fatalln(err) } - err = opts.collectOperatorLogs() + var db dbapi.MongoDB + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) if err != nil { - log.Fatal(err) - } - - err = opts.collectForAllDBPetSets() - if err != nil { - log.Fatal(err) + log.Fatalln(err) } - err = opts.collectForAllDBPods() + err = writeYaml(&db, getDir(db.GetName())) if err != nil { - log.Fatal(err) + return } - - err = opts.collectOtherYamls() + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() if err != nil { - log.Fatal(err) + log.Fatalln(err) } }, } - mgDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - - return mgDebugCmd -} - -func newMongodbOpts(f cmdutil.Factory, dbName, namespace, operatorNS string) (*mongodbOpts, error) { - config, err := f.ToRESTConfig() - if err != nil { - return nil, err - } - - dbClient, err := cs.NewForConfig(config) - if err != nil { - return nil, err - } - - psClient, err := ps.NewForConfig(config) - if err != nil { - return nil, err - } - - podClient, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - db, err := dbClient.KubedbV1().MongoDBs(namespace).Get(context.TODO(), dbName, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - pwd, _ := os.Getwd() - dir := path.Join(pwd, db.Name) - err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) - if err != nil { - return nil, err - } - err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) - if err != nil { - return nil, err - } - - opts := &mongodbOpts{ - db: db, - dbClient: dbClient, - psClient: psClient, - podClient: podClient, - operatorNamespace: operatorNS, - dir: dir, - errWriter: &bytes.Buffer{}, - } - return opts, writeYaml(db, path.Join(opts.dir, yamlsDir)) -} - -func (opts *mongodbOpts) collectOperatorLogs() error { - pods, err := opts.podClient.CoreV1().Pods(opts.operatorNamespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - for _, pod := range pods.Items { - isOperatorPod := false - for _, container := range pod.Spec.Containers { - if container.Name == operatorContainerName { - isOperatorPod = true - } - } - if isOperatorPod { - err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) - if err != nil { - return err - } - } - } - return nil -} - -func (opts *mongodbOpts) collectForAllDBPetSets() error { - psLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - petsets, err := opts.psClient.AppsV1().PetSets(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: psLabels, - }) - if err != nil { - return err - } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") - err = os.MkdirAll(psYamlDir, dirPerm) - if err != nil { - return err - } - - for _, p := range petsets.Items { - err = writeYaml(&p, psYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *mongodbOpts) collectForAllDBPods() error { - dbLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - pods, err := opts.podClient.CoreV1().Pods(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: dbLabels, - }) - if err != nil { - return err - } - - podYamlDir := path.Join(opts.dir, yamlsDir) - for _, pod := range pods.Items { - err = opts.writeLogsForSinglePod(pod) - if err != nil { - return err - } - - err = writeYaml(&pod, podYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *mongodbOpts) writeLogsForSinglePod(pod corev1.Pod) error { - for _, c := range pod.Spec.Containers { - err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) - if err != nil { - return err - } - } - return nil -} - -func (opts *mongodbOpts) writeLogs(podName, ns, container string) error { - req := opts.podClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ - Container: container, - }) - - podLogs, err := req.Stream(context.TODO()) - if err != nil { - return err - } - defer podLogs.Close() - - logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) - if err != nil { - return err - } - defer logFile.Close() - - buf := make([]byte, 1024) - for { - bytesRead, err := podLogs.Read(buf) - if err != nil { - break - } - _, _ = logFile.Write(buf[:bytesRead]) - } - return nil -} - -func (opts *mongodbOpts) collectOtherYamls() error { - opsReqs, err := opts.dbClient.OpsV1alpha1().MongoDBOpsRequests(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") - err = os.MkdirAll(opsYamlDir, dirPerm) - if err != nil { - return err - } - for _, ops := range opsReqs.Items { - if ops.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&ops, opsYamlDir) - if err != nil { - return err - } - } - } - - scalers, err := opts.dbClient.AutoscalingV1alpha1().MongoDBAutoscalers(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") - err = os.MkdirAll(scalerYamlDir, dirPerm) - if err != nil { - return err - } - for _, sc := range scalers.Items { - if sc.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&sc, scalerYamlDir) - if err != nil { - return err - } - } - } - return nil + return mdDebugCmd } diff --git a/pkg/debug/mssqlserver.go b/pkg/debug/mssqlserver.go new file mode 100644 index 000000000..c6d4e8ddb --- /dev/null +++ b/pkg/debug/mssqlserver.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func MSSQLServerDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "mssqlserver", + Aliases: []string{ + "ms", + "mssqlservers", + }, + Short: "Debug helper for MSSQLServer database", + Example: `kubectl dba debug mssqlserver -n demo sample-mssqlserver --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter mssqlserver object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindMSSQLServer + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.MSSQLServer + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/mysql.go b/pkg/debug/mysql.go index 2000d800e..dc71ddf91 100644 --- a/pkg/debug/mysql.go +++ b/pkg/debug/mysql.go @@ -17,50 +17,32 @@ limitations under the License. package debug import ( - "bytes" "context" "log" - "os" - "path" dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" - cs "kubedb.dev/apimachinery/client/clientset/versioned" "github.com/spf13/cobra" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" - ps "kubeops.dev/petset/client/clientset/versioned" ) -type mysqlOpts struct { - db *dbapi.MySQL - dbClient *cs.Clientset - psClient *ps.Clientset - podClient *kubernetes.Clientset - - operatorNamespace string - dir string - errWriter *bytes.Buffer -} - func MySQLDebugCMD(f cmdutil.Factory) *cobra.Command { var ( dbName string operatorNamespace string ) - myDebugCmd := &cobra.Command{ + mdDebugCmd := &cobra.Command{ Use: "mysql", Aliases: []string{ "my", "mysqls", }, - Short: "Debug helper for mysql database", + Short: "Debug helper for MySQL database", Example: `kubectl dba debug mysql -n demo sample-mysql --operator-namespace kubedb`, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 { @@ -73,231 +55,38 @@ func MySQLDebugCMD(f cmdutil.Factory) *cobra.Command { klog.Error(err, "failed to get current namespace") } - opts, err := newMysqlOpts(f, dbName, namespace, operatorNamespace) + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindMySQL + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) if err != nil { log.Fatalln(err) } - err = opts.collectOperatorLogs() + var db dbapi.MySQL + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) if err != nil { - log.Fatal(err) - } - - err = opts.collectForAllDBPetSets() - if err != nil { - log.Fatal(err) + log.Fatalln(err) } - err = opts.collectForAllDBPods() + err = writeYaml(&db, getDir(db.GetName())) if err != nil { - log.Fatal(err) + return } - - err = opts.collectOtherYamls() + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() if err != nil { - log.Fatal(err) + log.Fatalln(err) } }, } - myDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - - return myDebugCmd -} - -func newMysqlOpts(f cmdutil.Factory, dbName, namespace, operatorNS string) (*mysqlOpts, error) { - config, err := f.ToRESTConfig() - if err != nil { - return nil, err - } - - dbClient, err := cs.NewForConfig(config) - if err != nil { - return nil, err - } - - psClient, err := ps.NewForConfig(config) - if err != nil { - return nil, err - } - - podClient, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - db, err := dbClient.KubedbV1().MySQLs(namespace).Get(context.TODO(), dbName, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - pwd, _ := os.Getwd() - dir := path.Join(pwd, db.Name) - err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) - if err != nil { - return nil, err - } - err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) - if err != nil { - return nil, err - } - - opts := &mysqlOpts{ - db: db, - dbClient: dbClient, - psClient: psClient, - podClient: podClient, - operatorNamespace: operatorNS, - dir: dir, - errWriter: &bytes.Buffer{}, - } - return opts, writeYaml(db, path.Join(opts.dir, yamlsDir)) -} - -func (opts *mysqlOpts) collectOperatorLogs() error { - pods, err := opts.podClient.CoreV1().Pods(opts.operatorNamespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - for _, pod := range pods.Items { - isOperatorPod := false - for _, container := range pod.Spec.Containers { - if container.Name == operatorContainerName { - isOperatorPod = true - } - } - if isOperatorPod { - err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) - if err != nil { - return err - } - } - } - return nil -} - -func (opts *mysqlOpts) collectForAllDBPetSets() error { - psLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - petsets, err := opts.psClient.AppsV1().PetSets(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: psLabels, - }) - if err != nil { - return err - } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") - err = os.MkdirAll(psYamlDir, dirPerm) - if err != nil { - return err - } - - for _, p := range petsets.Items { - err = writeYaml(&p, psYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *mysqlOpts) collectForAllDBPods() error { - dbLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - pods, err := opts.podClient.CoreV1().Pods(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: dbLabels, - }) - if err != nil { - return err - } - - podYamlDir := path.Join(opts.dir, yamlsDir) - for _, pod := range pods.Items { - err = opts.writeLogsForSinglePod(pod) - if err != nil { - return err - } - - err = writeYaml(&pod, podYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *mysqlOpts) writeLogsForSinglePod(pod corev1.Pod) error { - for _, c := range pod.Spec.Containers { - err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) - if err != nil { - return err - } - } - return nil -} - -func (opts *mysqlOpts) writeLogs(podName, ns, container string) error { - req := opts.podClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ - Container: container, - }) - - podLogs, err := req.Stream(context.TODO()) - if err != nil { - return err - } - defer podLogs.Close() - - logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) - if err != nil { - return err - } - defer logFile.Close() - - buf := make([]byte, 1024) - for { - bytesRead, err := podLogs.Read(buf) - if err != nil { - break - } - _, _ = logFile.Write(buf[:bytesRead]) - } - return nil -} - -func (opts *mysqlOpts) collectOtherYamls() error { - opsReqs, err := opts.dbClient.OpsV1alpha1().MySQLOpsRequests(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") - err = os.MkdirAll(opsYamlDir, dirPerm) - if err != nil { - return err - } - for _, ops := range opsReqs.Items { - if ops.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&ops, opsYamlDir) - if err != nil { - return err - } - } - } - - scalers, err := opts.dbClient.AutoscalingV1alpha1().MySQLAutoscalers(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") - err = os.MkdirAll(scalerYamlDir, dirPerm) - if err != nil { - return err - } - for _, sc := range scalers.Items { - if sc.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&sc, scalerYamlDir) - if err != nil { - return err - } - } - } - return nil + return mdDebugCmd } diff --git a/pkg/debug/oracle.go b/pkg/debug/oracle.go new file mode 100644 index 000000000..477c1406f --- /dev/null +++ b/pkg/debug/oracle.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func OracleDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "oracle", + Aliases: []string{ + "or", + "oracles", + }, + Short: "Debug helper for Oracle database", + Example: `kubectl dba debug oracle -n demo sample-oracle --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter oracle object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindOracle + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Oracle + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/perconaxtradb.go b/pkg/debug/perconaxtradb.go new file mode 100644 index 000000000..f888df78c --- /dev/null +++ b/pkg/debug/perconaxtradb.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func PerconaXtraDBDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "perconaxtradb", + Aliases: []string{ + "prx", + "perconaxtradbs", + }, + Short: "Debug helper for PerconaXtraDB database", + Example: `kubectl dba debug perconaxtradb -n demo sample-perconaxtradb --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter perconaxtradb object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindPerconaXtraDB + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db dbapi.PerconaXtraDB + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/pgbouncer.go b/pkg/debug/pgbouncer.go new file mode 100644 index 000000000..8d075bc89 --- /dev/null +++ b/pkg/debug/pgbouncer.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func PgBouncerDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "pgbouncer", + Aliases: []string{ + "pb", + "pgbouncers", + }, + Short: "Debug helper for PgBouncer database", + Example: `kubectl dba debug pgbouncer -n demo sample-pgbouncer --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter pgbouncer object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindPgBouncer + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db dbapi.PgBouncer + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/pgpool.go b/pkg/debug/pgpool.go new file mode 100644 index 000000000..a4313fa07 --- /dev/null +++ b/pkg/debug/pgpool.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func PgpoolDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "pgpool", + Aliases: []string{ + "pp", + "pgpools", + }, + Short: "Debug helper for Pgpool database", + Example: `kubectl dba debug pgpool -n demo sample-pgpool --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter pgpool object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindPgpool + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Pgpool + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/postgres.go b/pkg/debug/postgres.go index c8abcbb17..58cb6afb3 100644 --- a/pkg/debug/postgres.go +++ b/pkg/debug/postgres.go @@ -17,50 +17,32 @@ limitations under the License. package debug import ( - "bytes" "context" "log" - "os" - "path" dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" - cs "kubedb.dev/apimachinery/client/clientset/versioned" "github.com/spf13/cobra" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" - ps "kubeops.dev/petset/client/clientset/versioned" ) -type postgresOpts struct { - db *dbapi.Postgres - dbClient *cs.Clientset - psClient *ps.Clientset - podClient *kubernetes.Clientset - - operatorNamespace string - dir string - errWriter *bytes.Buffer -} - func PostgresDebugCMD(f cmdutil.Factory) *cobra.Command { var ( dbName string operatorNamespace string ) - pgDebugCmd := &cobra.Command{ + mdDebugCmd := &cobra.Command{ Use: "postgres", Aliases: []string{ "pg", "postgreses", }, - Short: "Debug helper for postgres database", + Short: "Debug helper for Postgres database", Example: `kubectl dba debug postgres -n demo sample-postgres --operator-namespace kubedb`, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 { @@ -73,231 +55,38 @@ func PostgresDebugCMD(f cmdutil.Factory) *cobra.Command { klog.Error(err, "failed to get current namespace") } - opts, err := newPostgresOpts(f, dbName, namespace, operatorNamespace) + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindPostgres + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) if err != nil { log.Fatalln(err) } - err = opts.collectOperatorLogs() + var db dbapi.Postgres + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) if err != nil { - log.Fatal(err) - } - - err = opts.collectForAllDBPetSets() - if err != nil { - log.Fatal(err) + log.Fatalln(err) } - err = opts.collectForAllDBPods() + err = writeYaml(&db, getDir(db.GetName())) if err != nil { - log.Fatal(err) + return } - - err = opts.collectOtherYamls() + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() if err != nil { - log.Fatal(err) + log.Fatalln(err) } }, } - pgDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - - return pgDebugCmd -} - -func newPostgresOpts(f cmdutil.Factory, dbName, namespace, operatorNS string) (*postgresOpts, error) { - config, err := f.ToRESTConfig() - if err != nil { - return nil, err - } - - dbClient, err := cs.NewForConfig(config) - if err != nil { - return nil, err - } - - psClient, err := ps.NewForConfig(config) - if err != nil { - return nil, err - } - - podClient, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - db, err := dbClient.KubedbV1().Postgreses(namespace).Get(context.TODO(), dbName, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - pwd, _ := os.Getwd() - dir := path.Join(pwd, db.Name) - err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) - if err != nil { - return nil, err - } - err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) - if err != nil { - return nil, err - } - - opts := &postgresOpts{ - db: db, - dbClient: dbClient, - psClient: psClient, - podClient: podClient, - operatorNamespace: operatorNS, - dir: dir, - errWriter: &bytes.Buffer{}, - } - return opts, writeYaml(db, path.Join(opts.dir, yamlsDir)) -} - -func (opts *postgresOpts) collectOperatorLogs() error { - pods, err := opts.podClient.CoreV1().Pods(opts.operatorNamespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - for _, pod := range pods.Items { - isOperatorPod := false - for _, container := range pod.Spec.Containers { - if container.Name == operatorContainerName { - isOperatorPod = true - } - } - if isOperatorPod { - err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) - if err != nil { - return err - } - } - } - return nil -} - -func (opts *postgresOpts) collectForAllDBPetSets() error { - psLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - petsets, err := opts.psClient.AppsV1().PetSets(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: psLabels, - }) - if err != nil { - return err - } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") - err = os.MkdirAll(psYamlDir, dirPerm) - if err != nil { - return err - } - - for _, p := range petsets.Items { - err = writeYaml(&p, psYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *postgresOpts) collectForAllDBPods() error { - dbLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - pods, err := opts.podClient.CoreV1().Pods(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: dbLabels, - }) - if err != nil { - return err - } - - podYamlDir := path.Join(opts.dir, yamlsDir) - for _, pod := range pods.Items { - err = opts.writeLogsForSinglePod(pod) - if err != nil { - return err - } - - err = writeYaml(&pod, podYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *postgresOpts) writeLogsForSinglePod(pod corev1.Pod) error { - for _, c := range pod.Spec.Containers { - err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) - if err != nil { - return err - } - } - return nil -} - -func (opts *postgresOpts) writeLogs(podName, ns, container string) error { - req := opts.podClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ - Container: container, - }) - - podLogs, err := req.Stream(context.TODO()) - if err != nil { - return err - } - defer podLogs.Close() - - logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) - if err != nil { - return err - } - defer logFile.Close() - - buf := make([]byte, 1024) - for { - bytesRead, err := podLogs.Read(buf) - if err != nil { - break - } - _, _ = logFile.Write(buf[:bytesRead]) - } - return nil -} - -func (opts *postgresOpts) collectOtherYamls() error { - opsReqs, err := opts.dbClient.OpsV1alpha1().PostgresOpsRequests(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") - err = os.MkdirAll(opsYamlDir, dirPerm) - if err != nil { - return err - } - for _, ops := range opsReqs.Items { - if ops.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&ops, opsYamlDir) - if err != nil { - return err - } - } - } - - scalers, err := opts.dbClient.AutoscalingV1alpha1().PostgresAutoscalers(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") - err = os.MkdirAll(scalerYamlDir, dirPerm) - if err != nil { - return err - } - for _, sc := range scalers.Items { - if sc.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&sc, scalerYamlDir) - if err != nil { - return err - } - } - } - return nil + return mdDebugCmd } diff --git a/pkg/debug/proxysql.go b/pkg/debug/proxysql.go new file mode 100644 index 000000000..d7c1d1fde --- /dev/null +++ b/pkg/debug/proxysql.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func ProxySQLDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "proxysql", + Aliases: []string{ + "px", + "proxysqls", + }, + Short: "Debug helper for ProxySQL database", + Example: `kubectl dba debug proxysql -n demo sample-proxysql --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter proxysql object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindProxySQL + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db dbapi.ProxySQL + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/rabbitmq.go b/pkg/debug/rabbitmq.go new file mode 100644 index 000000000..57fa1a0c2 --- /dev/null +++ b/pkg/debug/rabbitmq.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func RabbitMQDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "rabbitmq", + Aliases: []string{ + "rm", + "rabbitmqs", + }, + Short: "Debug helper for Rabbitmq database", + Example: `kubectl dba debug rabbitmq -n demo sample-rabbitmq --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter rabbitmq object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindRabbitmq + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.RabbitMQ + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/redis.go b/pkg/debug/redis.go index 5f88f1c21..a29868cbe 100644 --- a/pkg/debug/redis.go +++ b/pkg/debug/redis.go @@ -17,50 +17,32 @@ limitations under the License. package debug import ( - "bytes" "context" "log" - "os" - "path" dbapi "kubedb.dev/apimachinery/apis/kubedb/v1" - cs "kubedb.dev/apimachinery/client/clientset/versioned" "github.com/spf13/cobra" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" - ps "kubeops.dev/petset/client/clientset/versioned" ) -type redisOpts struct { - db *dbapi.Redis - dbClient *cs.Clientset - psClient *ps.Clientset - podClient *kubernetes.Clientset - - operatorNamespace string - dir string - errWriter *bytes.Buffer -} - func RedisDebugCMD(f cmdutil.Factory) *cobra.Command { var ( dbName string operatorNamespace string ) - rdDebugCmd := &cobra.Command{ + mdDebugCmd := &cobra.Command{ Use: "redis", Aliases: []string{ "rd", "redises", }, - Short: "Debug helper for redis database", + Short: "Debug helper for Redis database", Example: `kubectl dba debug redis -n demo sample-redis --operator-namespace kubedb`, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 { @@ -73,231 +55,38 @@ func RedisDebugCMD(f cmdutil.Factory) *cobra.Command { klog.Error(err, "failed to get current namespace") } - opts, err := newRedisOpts(f, dbName, namespace, operatorNamespace) + gvk := func() schema.GroupVersionKind { + kind := dbapi.ResourceKindRedis + return schema.GroupVersionKind{ + Group: dbapi.SchemeGroupVersion.Group, + Version: dbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) if err != nil { log.Fatalln(err) } - err = opts.collectOperatorLogs() + var db dbapi.Redis + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) if err != nil { - log.Fatal(err) - } - - err = opts.collectForAllDBPetSets() - if err != nil { - log.Fatal(err) + log.Fatalln(err) } - err = opts.collectForAllDBPods() + err = writeYaml(&db, getDir(db.GetName())) if err != nil { - log.Fatal(err) + return } - - err = opts.collectOtherYamls() + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() if err != nil { - log.Fatal(err) + log.Fatalln(err) } }, } - rdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - - return rdDebugCmd -} - -func newRedisOpts(f cmdutil.Factory, dbName, namespace, operatorNS string) (*redisOpts, error) { - config, err := f.ToRESTConfig() - if err != nil { - return nil, err - } - - dbClient, err := cs.NewForConfig(config) - if err != nil { - return nil, err - } - - psClient, err := ps.NewForConfig(config) - if err != nil { - return nil, err - } - - podClient, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - db, err := dbClient.KubedbV1().Redises(namespace).Get(context.TODO(), dbName, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - pwd, _ := os.Getwd() - dir := path.Join(pwd, db.Name) - err = os.MkdirAll(path.Join(dir, logsDir), dirPerm) - if err != nil { - return nil, err - } - err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm) - if err != nil { - return nil, err - } - - opts := &redisOpts{ - db: db, - dbClient: dbClient, - psClient: psClient, - podClient: podClient, - operatorNamespace: operatorNS, - dir: dir, - errWriter: &bytes.Buffer{}, - } - return opts, writeYaml(db, path.Join(opts.dir, yamlsDir)) -} - -func (opts *redisOpts) collectOperatorLogs() error { - pods, err := opts.podClient.CoreV1().Pods(opts.operatorNamespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - for _, pod := range pods.Items { - isOperatorPod := false - for _, container := range pod.Spec.Containers { - if container.Name == operatorContainerName { - isOperatorPod = true - } - } - if isOperatorPod { - err = opts.writeLogs(pod.Name, pod.Namespace, operatorContainerName) - if err != nil { - return err - } - } - } - return nil -} - -func (opts *redisOpts) collectForAllDBPetSets() error { - psLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - petsets, err := opts.psClient.AppsV1().PetSets(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: psLabels, - }) - if err != nil { - return err - } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") - psYamlDir := path.Join(opts.dir, yamlsDir, "petsets") - err = os.MkdirAll(psYamlDir, dirPerm) - if err != nil { - return err - } - - for _, p := range petsets.Items { - err = writeYaml(&p, psYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *redisOpts) collectForAllDBPods() error { - dbLabels := labels.SelectorFromSet(opts.db.OffshootLabels()).String() - pods, err := opts.podClient.CoreV1().Pods(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{ - LabelSelector: dbLabels, - }) - if err != nil { - return err - } - - podYamlDir := path.Join(opts.dir, yamlsDir) - for _, pod := range pods.Items { - err = opts.writeLogsForSinglePod(pod) - if err != nil { - return err - } - - err = writeYaml(&pod, podYamlDir) - if err != nil { - return err - } - - } - return nil -} - -func (opts *redisOpts) writeLogsForSinglePod(pod corev1.Pod) error { - for _, c := range pod.Spec.Containers { - err := opts.writeLogs(pod.Name, pod.Namespace, c.Name) - if err != nil { - return err - } - } - return nil -} - -func (opts *redisOpts) writeLogs(podName, ns, container string) error { - req := opts.podClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{ - Container: container, - }) - - podLogs, err := req.Stream(context.TODO()) - if err != nil { - return err - } - defer podLogs.Close() - - logFile, err := os.Create(path.Join(opts.dir, logsDir, podName+"_"+container+".log")) - if err != nil { - return err - } - defer logFile.Close() - - buf := make([]byte, 1024) - for { - bytesRead, err := podLogs.Read(buf) - if err != nil { - break - } - _, _ = logFile.Write(buf[:bytesRead]) - } - return nil -} - -func (opts *redisOpts) collectOtherYamls() error { - opsReqs, err := opts.dbClient.OpsV1alpha1().RedisOpsRequests(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - opsYamlDir := path.Join(opts.dir, yamlsDir, "ops") - err = os.MkdirAll(opsYamlDir, dirPerm) - if err != nil { - return err - } - for _, ops := range opsReqs.Items { - if ops.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&ops, opsYamlDir) - if err != nil { - return err - } - } - } - - scalers, err := opts.dbClient.AutoscalingV1alpha1().RedisAutoscalers(opts.db.Namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - scalerYamlDir := path.Join(opts.dir, yamlsDir, "scaler") - err = os.MkdirAll(scalerYamlDir, dirPerm) - if err != nil { - return err - } - for _, sc := range scalers.Items { - if sc.Spec.DatabaseRef.Name == opts.db.Name { - err = writeYaml(&sc, scalerYamlDir) - if err != nil { - return err - } - } - } - return nil + return mdDebugCmd } diff --git a/pkg/debug/singlestore.go b/pkg/debug/singlestore.go new file mode 100644 index 000000000..3696077ae --- /dev/null +++ b/pkg/debug/singlestore.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func SinglestoreDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "singlestore", + Aliases: []string{ + "sdb", + "singlestores", + }, + Short: "Debug helper for Singlestore database", + Example: `kubectl dba debug singlestore -n demo sample-singlestore --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter singlestore object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindSinglestore + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Singlestore + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/solr.go b/pkg/debug/solr.go new file mode 100644 index 000000000..154339f43 --- /dev/null +++ b/pkg/debug/solr.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func SolrDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "solr", + Aliases: []string{ + "sl", + "solrs", + }, + Short: "Debug helper for Solr database", + Example: `kubectl dba debug solr -n demo sample-solr --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter solr object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindSolr + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.Solr + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/pkg/debug/zookeeper.go b/pkg/debug/zookeeper.go new file mode 100644 index 000000000..bbdbe2be6 --- /dev/null +++ b/pkg/debug/zookeeper.go @@ -0,0 +1,92 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package debug + +import ( + "context" + "log" + + olddbapi "kubedb.dev/apimachinery/apis/kubedb/v1alpha2" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func ZooKeeperDebugCMD(f cmdutil.Factory) *cobra.Command { + var ( + dbName string + operatorNamespace string + ) + + mdDebugCmd := &cobra.Command{ + Use: "zookeeper", + Aliases: []string{ + "zk", + "zookeepers", + }, + Short: "Debug helper for Zookeeper database", + Example: `kubectl dba debug zookeeper -n demo sample-zookeeper --operator-namespace kubedb`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatal("Enter zookeeper object's name as an argument") + } + dbName = args[0] + + namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + if err != nil { + klog.Error(err, "failed to get current namespace") + } + + gvk := func() schema.GroupVersionKind { + kind := olddbapi.ResourceKindZooKeeper + return schema.GroupVersionKind{ + Group: olddbapi.SchemeGroupVersion.Group, + Version: olddbapi.SchemeGroupVersion.Version, + Kind: kind, + } + }() + opts, err := newDBOpts(f, gvk, dbName, namespace, operatorNamespace) + if err != nil { + log.Fatalln(err) + } + + var db olddbapi.ZooKeeper + err = opts.kc.Get(context.TODO(), types.NamespacedName{Name: dbName, Namespace: namespace}, &db) + if err != nil { + log.Fatalln(err) + } + + err = writeYaml(&db, getDir(db.GetName())) + if err != nil { + return + } + opts.selectors = db.OffshootSelectors() + klog.Infof("db selectors: %v;\nDebug info has been generated in '%v' folder", opts.selectors, dbName) + err = opts.collectALl() + if err != nil { + log.Fatalln(err) + } + }, + } + mdDebugCmd.Flags().StringVarP(&operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb operator is installed") + + return mdDebugCmd +} diff --git a/vendor/kubeops.dev/petset/client/clientset/versioned/clientset.go b/vendor/kubeops.dev/petset/client/clientset/versioned/clientset.go deleted file mode 100644 index b6b66f75d..000000000 --- a/vendor/kubeops.dev/petset/client/clientset/versioned/clientset.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright AppsCode Inc. and Contributors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package versioned - -import ( - "fmt" - "net/http" - - appsv1 "kubeops.dev/petset/client/clientset/versioned/typed/apps/v1" - - discovery "k8s.io/client-go/discovery" - rest "k8s.io/client-go/rest" - flowcontrol "k8s.io/client-go/util/flowcontrol" -) - -type Interface interface { - Discovery() discovery.DiscoveryInterface - AppsV1() appsv1.AppsV1Interface -} - -// Clientset contains the clients for groups. -type Clientset struct { - *discovery.DiscoveryClient - appsV1 *appsv1.AppsV1Client -} - -// AppsV1 retrieves the AppsV1Client -func (c *Clientset) AppsV1() appsv1.AppsV1Interface { - return c.appsV1 -} - -// Discovery retrieves the DiscoveryClient -func (c *Clientset) Discovery() discovery.DiscoveryInterface { - if c == nil { - return nil - } - return c.DiscoveryClient -} - -// NewForConfig creates a new Clientset for the given config. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfig will generate a rate-limiter in configShallowCopy. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*Clientset, error) { - configShallowCopy := *c - - if configShallowCopy.UserAgent == "" { - configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() - } - - // share the transport between all clients - httpClient, err := rest.HTTPClientFor(&configShallowCopy) - if err != nil { - return nil, err - } - - return NewForConfigAndClient(&configShallowCopy, httpClient) -} - -// NewForConfigAndClient creates a new Clientset for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. -func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { - configShallowCopy := *c - if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { - if configShallowCopy.Burst <= 0 { - return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") - } - configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) - } - - var cs Clientset - var err error - cs.appsV1, err = appsv1.NewForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } - - cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } - return &cs, nil -} - -// NewForConfigOrDie creates a new Clientset for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *Clientset { - cs, err := NewForConfig(c) - if err != nil { - panic(err) - } - return cs -} - -// New creates a new Clientset for the given RESTClient. -func New(c rest.Interface) *Clientset { - var cs Clientset - cs.appsV1 = appsv1.New(c) - - cs.DiscoveryClient = discovery.NewDiscoveryClient(c) - return &cs -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 285a8b9ff..7ad574d7c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2581,7 +2581,6 @@ kubeops.dev/csi-driver-cacerts/crds # kubeops.dev/petset v0.0.12 ## explicit; go 1.24.0 kubeops.dev/petset/apis/apps/v1 -kubeops.dev/petset/client/clientset/versioned kubeops.dev/petset/client/clientset/versioned/scheme kubeops.dev/petset/client/clientset/versioned/typed/apps/v1 kubeops.dev/petset/client/listers/apps/v1