Skip to content

Commit af61d2f

Browse files
committed
make gitops common
Signed-off-by: obaydullahmhs <obaydullah@appscode.com>
1 parent f524c8a commit af61d2f

File tree

4 files changed

+58
-226
lines changed

4 files changed

+58
-226
lines changed

pkg/cmds/debug.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ func NewCmdDebug(f cmdutil.Factory) *cobra.Command {
6363
cmd.AddCommand(debug.PostgresDebugCMD(f))
6464
cmd.AddCommand(debug.ProxySQLDebugCMD(f))
6565
cmd.AddCommand(debug.RedisDebugCMD(f))
66-
cmd.AddCommand(debug.GitOpsDebugCMD(f))
6766

6867
// KubeDB v1alpha2 databases
6968
cmd.AddCommand(debug.CassandraDebugCMD(f))

pkg/debug/common.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,16 @@ func (opts *dbOpts) collectALl() error {
117117
if err != nil {
118118
return err
119119
}
120+
if IsOwnByGitOpsObject(opts.db.GetOwnerReferences(), opts.db.GetName(), opts.kind) {
121+
gitOpsOpts, err := newGitOpsOpts(opts.kc, opts.db.GetName(), opts.db.GetNamespace(), opts.kind, path.Join(opts.dir, "gitops"))
122+
if err != nil {
123+
return err
124+
}
125+
err = gitOpsOpts.collectGitOpsYamls()
126+
if err != nil {
127+
return err
128+
}
129+
}
120130
return nil
121131
}
122132

pkg/debug/gitops.go

Lines changed: 38 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,23 @@ limitations under the License.
1717
package debug
1818

1919
import (
20-
"bytes"
2120
"context"
2221
"fmt"
2322
"log"
2423
"os"
2524
"path"
26-
"strings"
2725

2826
gitops "kubedb.dev/apimachinery/apis/gitops/v1alpha1"
29-
dbapi "kubedb.dev/apimachinery/apis/kubedb/v1"
3027
opsapi "kubedb.dev/apimachinery/apis/ops/v1alpha1"
31-
kubedbscheme "kubedb.dev/apimachinery/client/clientset/versioned/scheme"
3228

33-
"github.com/spf13/cobra"
34-
corev1 "k8s.io/api/core/v1"
35-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3629
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3730
"k8s.io/apimachinery/pkg/runtime"
31+
"k8s.io/apimachinery/pkg/runtime/schema"
3832
"k8s.io/apimachinery/pkg/types"
39-
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
40-
"k8s.io/client-go/discovery"
41-
"k8s.io/client-go/kubernetes"
42-
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
4333
_ "k8s.io/client-go/plugin/pkg/client/auth"
44-
"k8s.io/client-go/rest"
45-
cmdutil "k8s.io/kubectl/pkg/cmd/util"
4634
"sigs.k8s.io/controller-runtime/pkg/client"
4735
)
4836

49-
var scheme = runtime.NewScheme()
50-
51-
func init() {
52-
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
53-
utilruntime.Must(kubedbscheme.AddToScheme(scheme))
54-
}
55-
5637
type GitOpsStatus struct {
5738
GitOps gitops.GitOpsStatus `json:"gitops,omitempty" yaml:"gitops,omitempty"`
5839
}
@@ -66,118 +47,58 @@ type Ops struct {
6647
}
6748

6849
type dbInfo struct {
69-
resource string
50+
kind string
7051
name string
7152
namespace string
7253
}
7354

7455
type gitOpsOpts struct {
75-
kc client.Client
76-
config *rest.Config
77-
db dbInfo
78-
kubeClient kubernetes.Interface
56+
kc client.Client
57+
db dbInfo
7958

80-
operatorNamespace string
81-
dir string
82-
errWriter *bytes.Buffer
83-
resMap map[string]string
84-
summary []string
59+
dir string
60+
summary []string
8561
}
8662

87-
func GitOpsDebugCMD(f cmdutil.Factory) *cobra.Command {
88-
var dbName string
89-
opts := newGitOpsOpts(f)
90-
gitOpsDebugCmd := &cobra.Command{
91-
Use: "gitops",
92-
Aliases: []string{
93-
"git",
94-
},
95-
Short: "Debug helper for gitops databases",
96-
Example: `kubectl dba debug gitops --db-type mysql -n demo sample-mysql --operator-namespace kubedb`,
97-
Run: func(cmd *cobra.Command, args []string) {
98-
if len(args) == 0 {
99-
log.Fatal("Enter mysql object's name as an argument")
100-
}
101-
dbName = args[0]
102-
103-
pwd, _ := os.Getwd()
104-
dir := path.Join(pwd, dbName)
105-
err := os.MkdirAll(path.Join(dir, logsDir), dirPerm)
106-
if err != nil {
107-
log.Fatalln(fmt.Errorf("failed to create directory %s: %w", dir, err))
108-
}
109-
err = os.MkdirAll(path.Join(dir, yamlsDir), dirPerm)
110-
if err != nil {
111-
log.Fatalln(fmt.Errorf("failed to create directory %s: %w", dir, err))
112-
}
113-
opts.dir = dir
114-
opts.db.name = dbName
115-
116-
err = opts.populateResourceMap()
117-
if err != nil {
118-
log.Fatal(err)
119-
}
120-
121-
err = opts.collectGitOpsDatabase()
122-
if err != nil {
123-
log.Fatal(err)
124-
}
125-
126-
err = opts.collectDatabase()
127-
if err != nil {
128-
log.Fatal(err)
129-
}
130-
131-
err = opts.collectOperatorLogs(opts.operatorNamespace)
132-
if err != nil {
133-
log.Fatal(err)
134-
}
135-
136-
fmt.Println("Summary:")
137-
for _, line := range opts.summary {
138-
fmt.Println("- ", line)
139-
}
140-
fmt.Println("--------------- Done ---------------")
141-
},
142-
}
143-
144-
gitOpsDebugCmd.Flags().StringVarP(&opts.db.namespace, "namespace", "n", "demo", "Database namespace")
145-
gitOpsDebugCmd.Flags().StringVarP(&opts.operatorNamespace, "operator-namespace", "o", "kubedb", "the namespace where the kubedb gitops operator is installed")
146-
gitOpsDebugCmd.Flags().StringVarP(&opts.db.resource, "db-type", "t", "postgres", "database type")
147-
148-
return gitOpsDebugCmd
149-
}
150-
151-
func newGitOpsOpts(f cmdutil.Factory) *gitOpsOpts {
152-
config, err := f.ToRESTConfig()
63+
func (g *gitOpsOpts) collectGitOpsYamls() error {
64+
err := g.collectGitOpsDatabase()
15365
if err != nil {
154-
log.Fatalln(err)
66+
return err
15567
}
15668

157-
kc, err := client.New(config, client.Options{Scheme: scheme})
158-
if err != nil {
159-
log.Fatalf("failed to create client: %v", err)
69+
fmt.Println("Summary:")
70+
for _, line := range g.summary {
71+
fmt.Println("- ", line)
16072
}
73+
fmt.Println("--------------- Done ---------------")
74+
return nil
75+
}
16176

162-
cs, err := kubernetes.NewForConfig(config)
77+
func newGitOpsOpts(kc client.Client, name, namespace, kind, dir string) (*gitOpsOpts, error) {
78+
err := os.MkdirAll(dir, dirPerm)
16379
if err != nil {
164-
log.Fatalf("failed to create kube client: %v", err)
80+
return nil, err
16581
}
166-
16782
opts := &gitOpsOpts{
168-
kc: kc,
169-
config: config,
170-
errWriter: &bytes.Buffer{},
171-
kubeClient: cs,
172-
resMap: make(map[string]string),
173-
summary: make([]string, 0),
83+
kc: kc,
84+
db: dbInfo{
85+
kind: kind,
86+
name: name,
87+
namespace: namespace,
88+
},
89+
dir: dir,
90+
summary: make([]string, 0),
17491
}
175-
return opts
92+
return opts, nil
17693
}
17794

17895
func (g *gitOpsOpts) collectGitOpsDatabase() error {
17996
var uns unstructured.Unstructured
180-
uns.SetGroupVersionKind(gitops.SchemeGroupVersion.WithKind(g.getKindFromResource(g.db.resource)))
97+
uns.SetGroupVersionKind(schema.GroupVersionKind{
98+
Group: gitops.SchemeGroupVersion.Group,
99+
Version: gitops.SchemeGroupVersion.Version,
100+
Kind: g.db.kind,
101+
})
181102
err := g.kc.Get(context.Background(), types.NamespacedName{
182103
Namespace: g.db.namespace,
183104
Name: g.db.name,
@@ -219,15 +140,19 @@ func (g *gitOpsOpts) collectGitOpsDatabase() error {
219140
}
220141

221142
func (g *gitOpsOpts) collectOpsRequests(gitOpsStatus GitOpsStatus) error {
222-
opsYamlDir := path.Join(g.dir, yamlsDir, "ops")
143+
opsYamlDir := path.Join(g.dir, "ops")
223144
err := os.MkdirAll(opsYamlDir, dirPerm)
224145
if err != nil {
225146
return err
226147
}
227148
for _, info := range gitOpsStatus.GitOps.GitOpsInfo {
228149
for _, op := range info.Operations {
229150
var uns unstructured.Unstructured
230-
uns.SetGroupVersionKind(opsapi.SchemeGroupVersion.WithKind(g.getKindFromResource(g.db.resource + "opsrequest")))
151+
uns.SetGroupVersionKind(schema.GroupVersionKind{
152+
Group: opsapi.SchemeGroupVersion.Group,
153+
Version: opsapi.SchemeGroupVersion.Version,
154+
Kind: g.db.kind + "OpsRequest",
155+
})
231156
err := g.kc.Get(context.Background(), types.NamespacedName{
232157
Namespace: g.db.namespace,
233158
Name: op.Name,
@@ -258,115 +183,3 @@ func (g *gitOpsOpts) collectOpsRequests(gitOpsStatus GitOpsStatus) error {
258183

259184
return nil
260185
}
261-
262-
func (g *gitOpsOpts) collectDatabase() error {
263-
var uns unstructured.Unstructured
264-
uns.SetGroupVersionKind(dbapi.SchemeGroupVersion.WithKind(g.getKindFromResource(g.db.resource)))
265-
err := g.kc.Get(context.Background(), types.NamespacedName{
266-
Namespace: g.db.namespace,
267-
Name: g.db.name,
268-
}, &uns)
269-
if err != nil {
270-
log.Fatalf("failed to get database: %v", err)
271-
}
272-
273-
return writeYaml(&uns, path.Join(g.dir, yamlsDir))
274-
}
275-
276-
func (g *gitOpsOpts) collectOperatorLogs(operatorNamespace string) error {
277-
pods, err := g.kubeClient.CoreV1().Pods(operatorNamespace).List(context.TODO(), metav1.ListOptions{})
278-
if err != nil {
279-
return err
280-
}
281-
for _, pod := range pods.Items {
282-
isOperatorPod := false
283-
for _, container := range pod.Spec.Containers {
284-
if container.Name == operatorContainerName {
285-
isOperatorPod = true
286-
}
287-
}
288-
if isOperatorPod {
289-
err = g.writeLogs(pod.Name, pod.Namespace, operatorContainerName)
290-
if err != nil {
291-
return err
292-
}
293-
}
294-
}
295-
return nil
296-
}
297-
298-
func (g *gitOpsOpts) populateResourceMap() error {
299-
dc, err := discovery.NewDiscoveryClientForConfig(g.config)
300-
if err != nil {
301-
return err
302-
}
303-
g.resMap = make(map[string]string)
304-
305-
if err := g.populate(dc, "kubedb.com/v1"); err != nil {
306-
return err
307-
}
308-
if err := g.populate(dc, "kubedb.com/v1alpha2"); err != nil {
309-
return err
310-
}
311-
if err := g.populate(dc, "gitops.kubedb.com/v1alpha1"); err != nil {
312-
return err
313-
}
314-
if err := g.populate(dc, "ops.kubedb.com/v1alpha1"); err != nil {
315-
return err
316-
}
317-
return nil
318-
}
319-
320-
func (g *gitOpsOpts) populate(dc *discovery.DiscoveryClient, gv string) error {
321-
resources, err := dc.ServerResourcesForGroupVersion(gv)
322-
if err != nil {
323-
return err
324-
}
325-
for _, r := range resources.APIResources {
326-
if !strings.ContainsAny(r.Name, "/") {
327-
g.resMap[r.Name] = r.Kind
328-
g.resMap[r.SingularName] = r.Kind
329-
for _, s := range r.ShortNames {
330-
g.resMap[s] = r.Kind
331-
}
332-
g.resMap[r.Kind] = r.Kind
333-
}
334-
}
335-
return nil
336-
}
337-
338-
func (g *gitOpsOpts) getKindFromResource(res string) string {
339-
kind, exists := g.resMap[res]
340-
if !exists {
341-
_ = fmt.Errorf("resource %s not supported", res)
342-
}
343-
return kind
344-
}
345-
346-
func (g *gitOpsOpts) writeLogs(podName, ns, container string) error {
347-
req := g.kubeClient.CoreV1().Pods(ns).GetLogs(podName, &corev1.PodLogOptions{
348-
Container: container,
349-
})
350-
351-
podLogs, err := req.Stream(context.TODO())
352-
if err != nil {
353-
return err
354-
}
355-
defer podLogs.Close()
356-
357-
logFile, err := os.Create(path.Join(g.dir, logsDir, podName+"_"+container+".log"))
358-
if err != nil {
359-
return err
360-
}
361-
defer logFile.Close()
362-
363-
buf := make([]byte, 1024)
364-
for {
365-
bytesRead, err := podLogs.Read(buf)
366-
if err != nil {
367-
break
368-
}
369-
_, _ = logFile.Write(buf[:bytesRead])
370-
}
371-
return nil
372-
}

pkg/debug/helpers.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,20 @@ import (
2020
"os"
2121
"path"
2222

23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2324
"sigs.k8s.io/controller-runtime/pkg/client"
2425
"sigs.k8s.io/yaml"
2526
)
2627

28+
func IsOwnByGitOpsObject(owners []metav1.OwnerReference, name, kind string) bool {
29+
for _, owner := range owners {
30+
if owner.Kind == kind && owner.Name == name && owner.APIVersion == "gitops.kubedb.com/v1alpha1" {
31+
return true
32+
}
33+
}
34+
return false
35+
}
36+
2737
func writeYaml(obj client.Object, fullPath string) error {
2838
b, err := yaml.Marshal(obj)
2939
if err != nil {

0 commit comments

Comments
 (0)