From 448d544a705a9c4b9b4101eed45f5cc09423f8d6 Mon Sep 17 00:00:00 2001 From: Arnob Kumar Saha Date: Thu, 29 Jan 2026 11:40:58 +0600 Subject: [PATCH] Implement license issue debug util Signed-off-by: Arnob kumar saha --- pkg/cmds/debug/debug.go | 2 + pkg/cmds/debug/license/helpers.go | 106 +++++++++++++++++++++++++ pkg/cmds/debug/license/license.go | 125 ++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 pkg/cmds/debug/license/helpers.go create mode 100644 pkg/cmds/debug/license/license.go diff --git a/pkg/cmds/debug/debug.go b/pkg/cmds/debug/debug.go index 4fd4ff25..d7130f65 100644 --- a/pkg/cmds/debug/debug.go +++ b/pkg/cmds/debug/debug.go @@ -19,6 +19,7 @@ package debug import ( "go.bytebuilders.dev/cli/pkg/cmds/debug/clientorg" "go.bytebuilders.dev/cli/pkg/cmds/debug/gateway" + "go.bytebuilders.dev/cli/pkg/cmds/debug/license" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" @@ -38,6 +39,7 @@ func NewCmdDebug() *cobra.Command { cmd.AddCommand(gateway.NewCmdGateway(f)) cmd.AddCommand(clientorg.NewCmdClientOrg(f)) + cmd.AddCommand(license.NewCmdLicense(f)) return cmd } diff --git a/pkg/cmds/debug/license/helpers.go b/pkg/cmds/debug/license/helpers.go new file mode 100644 index 00000000..a7274dcb --- /dev/null +++ b/pkg/cmds/debug/license/helpers.go @@ -0,0 +1,106 @@ +/* +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 license + +import ( + "fmt" + "os" + "path" + "strings" + + "gomodules.xyz/go-sh" +) + +const ( + dirPerm = 0o755 + filePerm = 0o644 + + kubectlCommand = "kubectl" + defaultDir = "license-debug-info" + defaultFile = "info.txt" +) + +func (g *licenseOpts) collectInfo() error { + out := []byte("\n\n===== License status =====\n") + args := []any{"get", "licensestatus"} + o, err := sh.Command(kubectlCommand, args...).Output() + if err != nil { + return err + } + out = append(out, o...) + + err = os.WriteFile(path.Join(g.rootPath, defaultFile), out, filePerm) // empty the file first, & write + if err != nil { + return err + } + // kube-system namespace + out = []byte("\n\n===== kube-system namespace =====\n") + args = []any{"get", "ns", "kube-system", "-o", "yaml"} + o, err = sh.Command(kubectlCommand, args...).Output() + if err != nil { + return err + } + out = append(out, o...) + + // license-proxyserver-licenses secret + out = append(out, []byte("\n\n===== License secret =====\n")...) + args = []any{"get", "secrets", "license-proxyserver-licenses", "-n", "kubeops", "-o", "yaml"} + o, err = sh.Command(kubectlCommand, args...).Output() + if err != nil { + return err + } + out = append(out, o...) + err = g.writeContent(defaultFile, out) + if err != nil { + return err + } + return nil +} + +func (g *licenseOpts) collectLogs(res, ns string) error { + args := []any{"logs", res, "-n", ns} + out, err := sh.Command(kubectlCommand, args...).Output() + if err != nil { + return err + } + + parts := strings.Split(res, "/") + if len(parts) != 2 { + return fmt.Errorf("unexpected res: %s", parts) + } + err = g.writeContent(parts[1]+".log", out) + if err != nil { + return err + } + return nil +} + +func (g *licenseOpts) writeContent(fileName string, content []byte) error { + f, err := os.OpenFile(path.Join(g.rootPath, fileName), os.O_APPEND|os.O_CREATE|os.O_WRONLY, filePerm) + if err != nil { + return err + } + defer func(f *os.File) { + _ = f.Close() + }(f) + + _, err = f.Write(content) + if err != nil { + return err + } + return nil +} diff --git a/pkg/cmds/debug/license/license.go b/pkg/cmds/debug/license/license.go new file mode 100644 index 00000000..e4d563c2 --- /dev/null +++ b/pkg/cmds/debug/license/license.go @@ -0,0 +1,125 @@ +/* +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 license + +import ( + "log" + "os" + "path" + + catalogapi "go.bytebuilders.dev/catalog/api/catalog/v1alpha1" + catgwapi "go.bytebuilders.dev/catalog/api/gateway/v1alpha1" + + acmev1 "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" + certv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + flux "github.com/fluxcd/helm-controller/api/v2" + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + kubedbscheme "kubedb.dev/apimachinery/client/clientset/versioned/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + gwapi "sigs.k8s.io/gateway-api/apis/v1" + gwapia3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + gwapib1 "sigs.k8s.io/gateway-api/apis/v1beta1" + vgapi "voyagermesh.dev/gateway-api/apis/gateway/v1alpha1" +) + +var scheme = runtime.NewScheme() + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(catalogapi.AddToScheme(scheme)) + utilruntime.Must(catgwapi.AddToScheme(scheme)) + utilruntime.Must(kubedbscheme.AddToScheme(scheme)) + utilruntime.Must(gwapi.Install(scheme)) + utilruntime.Must(gwapia3.Install(scheme)) + utilruntime.Must(gwapib1.Install(scheme)) + utilruntime.Must(vgapi.AddToScheme(scheme)) + utilruntime.Must(egv1a1.AddToScheme(scheme)) + utilruntime.Must(flux.AddToScheme(scheme)) + utilruntime.Must(certv1.AddToScheme(scheme)) + utilruntime.Must(acmev1.AddToScheme(scheme)) +} + +func NewCmdLicense(f cmdutil.Factory) *cobra.Command { + opt := newLicenseOrgOpts(f) + cmd := &cobra.Command{ + Use: "license", + Short: "License related info", + DisableAutoGenTag: true, + RunE: func(cmd *cobra.Command, args []string) error { + klog.Infof("The debug info will be generated in current directory under '%s' folder", defaultDir) + return opt.run() + }, + } + return cmd +} + +type licenseOpts struct { + kc client.Client + config *rest.Config + kubeClient kubernetes.Interface + rootPath string +} + +func newLicenseOrgOpts(f cmdutil.Factory) *licenseOpts { + config, err := f.ToRESTConfig() + if err != nil { + log.Fatal(err) + } + kc, err := client.New(config, client.Options{Scheme: scheme}) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + + cs, err := kubernetes.NewForConfig(config) + if err != nil { + log.Fatalf("failed to create kube client: %v", err) + } + + return &licenseOpts{ + kc: kc, + config: config, + kubeClient: cs, + } +} + +func (g *licenseOpts) run() error { + pwd, _ := os.Getwd() + g.rootPath = path.Join(pwd, defaultDir) + err := os.MkdirAll(g.rootPath, dirPerm) + if err != nil { + return err + } + + if err := g.collectInfo(); err != nil { + return err + } + if err := g.collectLogs("deploy/license-proxyserver", "kubeops"); err != nil { + return err + } + if err := g.collectLogs("sts/kubedb-kubedb-provisioner", "kubedb"); err != nil { + return err + } + return err +}