Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit b61be07

Browse files
committed
Add pods list for all namespace. Close #10. Open #20.
1 parent 3431587 commit b61be07

File tree

6 files changed

+138
-62
lines changed

6 files changed

+138
-62
lines changed

config.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
type config struct {
10+
homeDir string
11+
kubeConfig *string
12+
frequency int
13+
setup bool
14+
}
15+
16+
// Check if configuration is initialized
17+
func (c *config) Initialized() bool {
18+
return c != nil && c.setup
19+
}
20+
21+
var CONFIG config
22+
23+
// Get configuration
24+
func getConfig() config {
25+
if CONFIG.Initialized() {
26+
return CONFIG
27+
}
28+
29+
c := config{}
30+
31+
// Home directory
32+
c.homeDir = os.Getenv("USERPROFILE")
33+
if h := os.Getenv("HOME"); h != "" {
34+
c.homeDir = h
35+
}
36+
37+
// Kubernetes configuration
38+
if h := c.homeDir; h != "" {
39+
c.kubeConfig = flag.String("kubeconfig", filepath.Join(h, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
40+
} else {
41+
c.kubeConfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
42+
}
43+
44+
// Refreshing frequency
45+
flag.IntVar(&c.frequency, "frequency", 3, "refreshing frequency in seconds (default: 5)")
46+
47+
flag.Parse()
48+
49+
c.setup = true
50+
CONFIG = c
51+
52+
return c
53+
}

keys.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,9 @@ type Key struct {
88
handler func(*gocui.Gui, *gocui.View) error
99
}
1010

11-
// Configure globale keys
12-
var globalKeys []Key = []Key{
13-
Key{"", gocui.KeyCtrlC, actionGlobalQuit},
14-
Key{"", gocui.KeyCtrlD, actionGlobalToggleDebug},
15-
}
16-
1711
// Define UI key bindings
1812
func uiKey(g *gocui.Gui) error {
19-
// Glboal keys
20-
for _, key := range globalKeys {
13+
for _, key := range keys {
2114
if err := g.SetKeybinding(key.viewname, key.key, gocui.ModNone, key.handler); err != nil {
2215
return err
2316
}

kubernetes.go

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package main
22

33
import (
4-
"flag"
54
"fmt"
6-
"os"
7-
"path/filepath"
85
"strconv"
96
"time"
107

@@ -16,46 +13,33 @@ import (
1613
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1714
)
1815

16+
// Get Kubernetes client set
1917
func getClientSet() *kubernetes.Clientset {
18+
c := getConfig()
19+
2020
// Use the current context in kubeconfig
21-
c, err := clientcmd.BuildConfigFromFlags("", *getKubeConfig())
21+
cc, err := clientcmd.BuildConfigFromFlags("", *c.kubeConfig)
2222
if err != nil {
2323
panic(err.Error())
2424
}
2525

2626
// Create the client set
27-
cs, err := kubernetes.NewForConfig(c)
27+
cs, err := kubernetes.NewForConfig(cc)
2828
if err != nil {
2929
panic(err.Error())
3030
}
3131

3232
return cs
3333
}
3434

35-
func getKubeConfig() *string {
36-
var kc *string
37-
if h := getHomeDir(); h != "" {
38-
kc = flag.String("kubeconfig", filepath.Join(h, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
39-
} else {
40-
kc = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
41-
}
42-
flag.Parse()
43-
44-
return kc
45-
}
46-
47-
func getHomeDir() string {
48-
if h := os.Getenv("HOME"); h != "" {
49-
return h
50-
}
51-
return os.Getenv("USERPROFILE") // windows
52-
}
53-
35+
// Get pods (use namespace)
5436
func getPods() (*v1.PodList, error) {
5537
cs := getClientSet()
38+
5639
return cs.CoreV1().Pods(NAMESPACE).List(metav1.ListOptions{})
5740
}
5841

42+
// Column helper: Restarts
5943
func columnHelperRestarts(cs []v1.ContainerStatus) string {
6044
r := 0
6145
for _, c := range cs {
@@ -64,29 +48,32 @@ func columnHelperRestarts(cs []v1.ContainerStatus) string {
6448
return strconv.Itoa(r)
6549
}
6650

51+
// Column helper: Age
6752
func columnHelperAge(t metav1.Time) string {
68-
delta := time.Now().Sub(t.Time)
53+
d := time.Now().Sub(t.Time)
6954

70-
if delta.Hours() > 1 {
71-
if delta.Hours() > 24 {
72-
d := float64(delta.Hours() / 24)
73-
return fmt.Sprintf("%.0fd", d)
55+
if d.Hours() > 1 {
56+
if d.Hours() > 24 {
57+
ds := float64(d.Hours() / 24)
58+
return fmt.Sprintf("%.0fd", ds)
7459
} else {
75-
return fmt.Sprintf("%.0fh", delta.Hours())
60+
return fmt.Sprintf("%.0fh", d.Hours())
7661
}
77-
} else if delta.Minutes() > 1 {
78-
return fmt.Sprintf("%.0fm", delta.Minutes())
79-
} else if delta.Seconds() > 1 {
80-
return fmt.Sprintf("%.0fs", delta.Seconds())
62+
} else if d.Minutes() > 1 {
63+
return fmt.Sprintf("%.0fm", d.Minutes())
64+
} else if d.Seconds() > 1 {
65+
return fmt.Sprintf("%.0fs", d.Seconds())
8166
}
8267

8368
return "?"
8469
}
8570

86-
func columnHelperStatus(status v1.PodStatus) string {
87-
return fmt.Sprintf("%s", status.Phase)
71+
// Column helper: Status
72+
func columnHelperStatus(s v1.PodStatus) string {
73+
return fmt.Sprintf("%s", s.Phase)
8874
}
8975

76+
// Column helper: Ready
9077
func columnHelperReady(cs []v1.ContainerStatus) string {
9178
cr := 0
9279
for _, c := range cs {

main.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ import (
88
"github.com/jroimartin/gocui"
99
)
1010

11-
var NAMESPACE string = "default"
11+
var NAMESPACE string = ""
12+
13+
// Configure globale keys
14+
var keys []Key = []Key{
15+
Key{"", gocui.KeyCtrlC, actionGlobalQuit},
16+
Key{"", gocui.KeyCtrlD, actionGlobalToggleDebug},
17+
}
1218

1319
func main() {
1420
g, err := gocui.NewGui(gocui.OutputNormal)
@@ -42,6 +48,7 @@ func uiLayout(g *gocui.Gui) error {
4248
return nil
4349
}
4450

51+
// Useful to debug application (display with CTRL+D)
4552
func debug(g *gocui.Gui, output interface{}) {
4653
v, err := g.View("debug")
4754
if err == nil {

version.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,22 @@ const APP = "Pody"
1010
const AUTHOR = "@JulienBreux"
1111
const VERSION = "0.1.0"
1212

13+
// Get full banner of version
1314
func versionFull() string {
1415
return fmt.Sprintf("%s %s - By %s", APP, VERSION, AUTHOR)
1516
}
1617

18+
// Get only banner (used in title bar view)
1719
func versionBanner() string {
1820
return fmt.Sprintf(" %s %s", APP, VERSION)
1921
}
2022

23+
// Get only author (used in title bar view)
2124
func versionAuthor() string {
2225
return fmt.Sprintf("By %s ", AUTHOR)
2326
}
2427

28+
// Prepare version title (used in title bar view)
2529
func versionTitle(width int) string {
2630
return versionBanner() + pad.Left(versionAuthor(), width-len(versionBanner()), " ")
2731
}

views.go

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"fmt"
55
"strings"
6+
"time"
67

78
"github.com/jroimartin/gocui"
89
"github.com/willf/pad"
@@ -72,48 +73,79 @@ func viewPods(g *gocui.Gui, lMaxX int, lMaxY int) error {
7273
// Set as current view
7374
g.SetCurrentView(v.Name())
7475

75-
// Content: Add column
76-
//viewPodsAddLine(v, lMaxX, "NAME", "CPU", "MEMORY", "READY", "STATUS", "RESTARTS", "AGE") // TODO CPU + Memory
77-
viewPodsAddLine(v, lMaxX, "NAME", "READY", "STATUS", "RESTARTS", "AGE")
78-
fmt.Fprintln(v, strings.Repeat("─", lMaxX))
76+
// Content
77+
go viewPodsActualize(g, lMaxX)
78+
go viewPodsAutoRefresh(g, lMaxX)
79+
}
80+
81+
return nil
82+
}
83+
84+
// Auto refresh view pods
85+
func viewPodsAutoRefresh(g *gocui.Gui, lMaxX int) {
86+
c := getConfig()
87+
t := time.NewTicker(time.Duration(c.frequency) * time.Second)
88+
for {
89+
select {
90+
case <-t.C:
91+
debug(g, fmt.Sprintf("View pods: Refreshing (%ds)", c.frequency))
92+
go viewPodsActualize(g, lMaxX)
93+
}
94+
}
95+
}
96+
97+
// Actualize pods view
98+
func viewPodsActualize(g *gocui.Gui, lMaxX int) {
99+
g.Execute(func(g *gocui.Gui) error {
100+
debug(g, "View pods: Actualize")
101+
v, err := g.View("pods")
102+
if err != nil {
103+
return err
104+
}
79105

80-
// Content: Add lines
81-
// TODO Use goroutine
82106
pods, err := getPods()
83107
if err != nil {
84108
panic(err.Error())
85109
}
110+
111+
v.Clear()
112+
113+
// Content: Add column
114+
//viewPodsAddLine(v, lMaxX, "NAME", "CPU", "MEMORY", "READY", "STATUS", "RESTARTS", "AGE") // TODO CPU + Memory #20
115+
viewPodsAddLine(v, lMaxX, "NAME", "READY", "STATUS", "RESTARTS", "AGE")
116+
fmt.Fprintln(v, strings.Repeat("─", lMaxX))
117+
86118
if len(pods.Items) > 0 {
87-
debug(g, fmt.Sprintf("There are %d pods in the cluster", len(pods.Items)))
119+
debug(g, fmt.Sprintf("View pods: %d pods found", len(pods.Items)))
88120
for _, pod := range pods.Items {
89121
n := pod.GetName()
90-
//c := "?" // TODO CPU + Memory
91-
//m := "?" // TODO CPU + Memory
122+
//c := "?" // TODO CPU + Memory #20
123+
//m := "?" // TODO CPU + Memory #20
92124
s := columnHelperStatus(pod.Status)
93125
r := columnHelperRestarts(pod.Status.ContainerStatuses)
94126
a := columnHelperAge(pod.CreationTimestamp)
95127
cr := columnHelperReady(pod.Status.ContainerStatuses)
96128
viewPodsAddLine(v, lMaxX, n, cr, s, r, a)
97-
//viewPodsAddLine(v, lMaxX, n, c, m, cr, s, r, a) // TODO CPU + Memory
129+
//viewPodsAddLine(v, lMaxX, n, c, m, cr, s, r, a) // TODO CPU + Memory #20
98130
}
99131
} else {
100-
debug(g, "Pods not found.")
132+
debug(g, "View pods: Pods not found")
101133
}
102-
}
103134

104-
return nil
135+
return nil
136+
})
105137
}
106138

107139
// Add line to view pods
108-
//func viewPodsAddLine(v *gocui.View, maxX int, name, cpu, memory, ready, status, restarts, age string) { // TODO CPU + Memory
140+
//func viewPodsAddLine(v *gocui.View, maxX int, name, cpu, memory, ready, status, restarts, age string) { // TODO CPU + Memory #20
109141
func viewPodsAddLine(v *gocui.View, maxX int, name, ready, status, restarts, age string) {
110-
wN := maxX - 34 // 54 // TODO CPU + Memory
142+
wN := maxX - 34 // 54 // TODO CPU + Memory #20
111143
if wN < 45 {
112144
wN = 45
113145
}
114146
line := pad.Right(name, wN, " ") +
115-
//pad.Right(cpu, 10, " ") + // TODO CPU + Memory
116-
//pad.Right(memory, 10, " ") + // TODO CPU + Memory
147+
//pad.Right(cpu, 10, " ") + // TODO CPU + Memory #20
148+
//pad.Right(memory, 10, " ") + // TODO CPU + Memory #20
117149
pad.Right(ready, 10, " ") +
118150
pad.Right(status, 10, " ") +
119151
pad.Right(restarts, 10, " ") +

0 commit comments

Comments
 (0)