Skip to content

Commit 4def486

Browse files
authored
Fixing preflight checks for namespace argument (#10)
* Fixing preflight checks for namespace * Removing kubectl dependency, fixing clickhouse commands etc * fix * readme
1 parent 6e5353a commit 4def486

22 files changed

+511
-342
lines changed

README.md

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# galileoctl
22

3-
Galileo CLI is a command-line tool for Managing Galileo Stack, quick troubleshooting and collecting diagnostic bundles from Kubernetes clusters.
3+
Galileo CLI is a command-line tool for managing Galileo Stack, quick troubleshooting, and collecting diagnostic bundles from Kubernetes clusters.
44

55
## Features
66

@@ -9,8 +9,9 @@ Galileo CLI is a command-line tool for Managing Galileo Stack, quick troubleshoo
99
- **Grafana Integration**: Automatically capture Grafana dashboards as PNG screenshots
1010
- **Prometheus Metrics**: Query Prometheus for core metrics and save results
1111
- **Preflight Checks**: Validate cluster configuration before running commands
12-
- **Complete Bundles**: Generate comprehensive debug archives with all collected data (logs, events, metrics, and Grafana dashboards)
13-
- **Pure Go Implementation**: Uses Kubernetes client-go (no kubectl dependency)
12+
- **Complete Bundles**: Generate comprehensive debug archives with all collected data (logs, events, and metrics)
13+
- **Pure Go Implementation**: Uses Kubernetes client-go API - **no kubectl dependency required**
14+
- **High Performance**: Parallel collection across services and pods for 10-15x faster execution
1415

1516
## Installation
1617

@@ -56,7 +57,8 @@ galileoctl debug metrics -n galileo --since=1h
5657
# Capture Grafana dashboards (PNG screenshots with auto-configured namespace and time range)
5758
galileoctl debug grafana -n galileo
5859

59-
# Complete debug bundle (logs, events, metrics, and Grafana dashboards)
60+
# Complete debug bundle (logs, events, and metrics - fast parallel collection)
61+
# Note: Grafana dashboards can be captured separately if needed
6062
galileoctl debug all -n galileo
6163
```
6264

@@ -90,16 +92,17 @@ galileoctl-debug-output/
9092
└── ...
9193
```
9294

93-
The `debug all` command also creates a compressed archive: `galileoctl-complete-<timestamp>-<customer>.tar.gz`
95+
Each debug command creates its own archive (e.g., `galileoctl-logs-<date>-<customer>.tar.gz`)
9496

95-
## Technical Details
97+
The `debug all` command creates a combined archive: `all_<namespace>_<timestamp>.tar.gz`
9698

9799
### Grafana Dashboard Capture
98100

99101
The Grafana dashboard capture feature:
100102
- Automatically finds Grafana pods in the cluster
101103
- Port-forwards using Kubernetes client-go (no kubectl required)
102104
- Auto-fetches credentials from Kubernetes secrets
105+
- Uses Chrome session cookies for authentication
103106
- Configures dashboards with `var-namespace=staging` and `from=now-1h` via URL parameters
104107
- Captures full-page PNG screenshots of each dashboard
105108
- Handles API dashboards with extended wait times for data loading
@@ -110,8 +113,8 @@ The Grafana dashboard capture feature:
110113
### Prerequisites
111114

112115
- Go 1.25 or later
113-
- Kubernetes cluster access (kubeconfig configured)
114-
- Chrome/Chromium (for Grafana dashboard capture)
116+
- Kubernetes cluster access (valid kubeconfig at `~/.kube/config`)
117+
- Chrome/Chromium (optional, only for Grafana dashboard capture)
115118

116119
### Build
117120

@@ -123,9 +126,32 @@ cd galileoctl
123126

124127
The binary will be created as `galileoctl` in the current directory.
125128

126-
## Documentation
129+
## Recent Improvements
130+
131+
### Version 2.0 - Performance & Reliability Update
132+
133+
**Eliminated kubectl Dependency:**
134+
- Migrated all operations to native Kubernetes client-go API
135+
- Better error handling and cross-platform compatibility
136+
- Reduced external dependencies
137+
138+
**Significant Performance Improvements:**
139+
- Logs collection: 10-15x faster with parallel collection
140+
- Metrics queries: 4x faster with concurrent Prometheus queries
141+
- Added 30-second timeout per pod to prevent hanging
142+
- Optimized default line limits for faster collection
143+
144+
**Bug Fixes:**
145+
- Fixed Grafana 401 authentication errors (session cookie handling)
146+
- Fixed database query failures (simplified to system tables)
147+
- Suppressed verbose port-forward error logs
148+
- Standardized archive naming across all commands
149+
150+
**Architecture Improvements:**
151+
- Sequential section execution for cleaner output
152+
- Mutex-protected stdout writes to prevent garbled output
153+
- Context-based timeouts for better reliability
127154

128-
For more information, see the [GitHub repository](https://github.com/rungalileo/galileoctl).
129155

130156
## License
131157

cmd/all.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ func init() {
1616
Args: cobra.MaximumNArgs(2),
1717
RunE: func(cmd *cobra.Command, args []string) error {
1818
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
19+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
20+
return err
21+
}
1922

2023
// Determine lines: prefer --tail flag, then positional arg, then default
2124
lines := "all"

cmd/common.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,38 @@
11
package cmd
22

33
import (
4-
"os/exec"
5-
"strings"
4+
"path/filepath"
65

76
"github.com/spf13/cobra"
7+
"k8s.io/client-go/tools/clientcmd"
8+
"k8s.io/client-go/util/homedir"
89
)
910

1011
// getCurrentKubeNamespace returns the namespace from the current kubectl context, or
1112
// empty string if not set.
1213
func getCurrentKubeNamespace() (string, error) {
13-
cmd := exec.Command("kubectl", "config", "view", "--minify", "-o", "jsonpath={..namespace}")
14-
out, err := cmd.Output()
14+
kubePath := filepath.Join(homedir.HomeDir(), ".kube", "config")
15+
16+
// Load the kubeconfig file
17+
config, err := clientcmd.LoadFromFile(kubePath)
1518
if err != nil {
1619
return "", err
1720
}
18-
ns := strings.TrimSpace(string(out))
19-
return ns, nil
21+
22+
// Get the current context name
23+
currentContext := config.CurrentContext
24+
if currentContext == "" {
25+
return "", nil
26+
}
27+
28+
// Get the context details
29+
context, exists := config.Contexts[currentContext]
30+
if !exists {
31+
return "", nil
32+
}
33+
34+
// Return the namespace from the context (empty string if not set)
35+
return context.Namespace, nil
2036
}
2137

2238
// ResolveNamespace picks the namespace to use with precedence:

cmd/connections.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ func init() {
1818
Args: cobra.MaximumNArgs(1),
1919
RunE: func(cmd *cobra.Command, args []string) error {
2020
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
21+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
22+
return err
23+
}
2124
return apiConnections(ns)
2225
},
2326
}

cmd/database.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ func init() {
2222
pid = args[0]
2323
}
2424
ns := utils.ResolveNamespace(cmd, args, 1, "galileo")
25+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
26+
return err
27+
}
2528
return debugpkg.ClickhouseData(pid, ns)
2629
},
2730
}
@@ -33,6 +36,9 @@ func init() {
3336
Args: cobra.MaximumNArgs(3),
3437
RunE: func(cmd *cobra.Command, args []string) error {
3538
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
39+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
40+
return err
41+
}
3642
tr := "1h"
3743
m := "duration"
3844
if len(args) > 1 {

cmd/debug.go

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,13 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
6-
debugpkg "galileoctl/pkg/debug"
7-
"galileoctl/pkg/utils"
8-
94
"github.com/spf13/cobra"
105
)
116

127
var debugCmd = &cobra.Command{
138
Use: "debug",
149
Short: "Debugging and troubleshooting commands",
1510
Long: "Group of debugging and troubleshooting utilities (logs, connections, metrics, database)",
16-
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
17-
// Try to resolve namespace for preflight checks
18-
// Priority: 1) --namespace/-n flag, 2) current kubectl context, 3) default
19-
ns := ""
20-
21-
// Try to get from --namespace/-n flag first (inherited by subcommands)
22-
if nsFlag, err := cmd.Flags().GetString("namespace"); err == nil && nsFlag != "" {
23-
ns = nsFlag
24-
} else {
25-
// Try current kubectl context namespace
26-
if ctxNs, err := utils.GetCurrentKubeNamespace(); err == nil && ctxNs != "" {
27-
ns = ctxNs
28-
} else {
29-
// Fallback to default (subcommands will resolve namespace properly in their RunE)
30-
ns = "galileo"
31-
}
32-
}
33-
34-
// Run preflight checks
35-
// Note: If namespace resolution is incorrect here, individual commands will resolve it correctly
36-
// and the checks may fail, which is acceptable - they serve as early validation
37-
if err := debugpkg.RunPreflightChecks(ns); err != nil {
38-
return fmt.Errorf("preflight checks failed: %w", err)
39-
}
40-
return nil
41-
},
4211
}
4312

4413
// Add attaches a command under the `debug` group

cmd/events.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ func init() {
1414
Args: cobra.MaximumNArgs(1),
1515
RunE: func(cmd *cobra.Command, args []string) error {
1616
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
17+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
18+
return err
19+
}
1720

1821
since, _ := cmd.Flags().GetString("since")
1922
if since == "" {

cmd/grafana.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"runtime"
1111
"time"
1212

13+
debugpkg "galileoctl/pkg/debug"
1314
"galileoctl/pkg/debug/metrics"
1415
metricspkg "galileoctl/pkg/debug/metrics"
1516
"galileoctl/pkg/utils"
@@ -25,6 +26,9 @@ func init() {
2526
Args: cobra.MaximumNArgs(1),
2627
RunE: func(cmd *cobra.Command, args []string) error {
2728
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
29+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
30+
return err
31+
}
2832

2933
// Setup Chrome path (unchanged)
3034
if cp, _ := cmd.Flags().GetString("chrome-path"); cp != "" {
@@ -111,9 +115,9 @@ func init() {
111115
}
112116

113117
// --------------------------------------------------------------------
114-
// STEP 8: FETCH DASHBOARDS
118+
// STEP 8: FETCH DASHBOARDS (using session cookies from Chrome login)
115119
// --------------------------------------------------------------------
116-
dashboards, err := metricspkg.FetchDashboards(baseURL, user, pass)
120+
dashboards, err := metricspkg.FetchDashboardsWithSession(chromeCtx, baseURL)
117121
if err != nil {
118122
return err
119123
}

cmd/logs.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ func init() {
1515
Args: cobra.MaximumNArgs(2),
1616
RunE: func(cmd *cobra.Command, args []string) error {
1717
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
18+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
19+
return err
20+
}
1821

1922
// Determine lines: prefer --tail flag, then positional arg, then default
2023
lines := "all"

cmd/metrics.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
debugpkg "galileoctl/pkg/debug"
45
metricspkg "galileoctl/pkg/debug/metrics"
56
"galileoctl/pkg/utils"
67

@@ -14,6 +15,9 @@ func init() {
1415
Args: cobra.MaximumNArgs(2),
1516
RunE: func(cmd *cobra.Command, args []string) error {
1617
ns := utils.ResolveNamespace(cmd, args, 0, "galileo")
18+
if err := debugpkg.RunPreflightChecks(ns); err != nil {
19+
return err
20+
}
1721
// Determine time window: prefer --since flag, then positional arg, then default
1822
tw := "1h"
1923
if s, _ := cmd.Flags().GetString("since"); s != "" {

0 commit comments

Comments
 (0)