From f55cfdac38ed481d7d6d4690288ae6decb39fe00 Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 13:19:51 +0900 Subject: [PATCH 1/9] Create kubernetes pkg Handle kubernetes packages --- kubernetes/client.go | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 kubernetes/client.go diff --git a/kubernetes/client.go b/kubernetes/client.go new file mode 100644 index 0000000..8485e38 --- /dev/null +++ b/kubernetes/client.go @@ -0,0 +1,63 @@ +package kubernetes + +import ( + "os/user" + + "github.com/sukeesh/k8s-job-notify/env" + + batchv1 "k8s.io/api/batch/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +// Client represents the wrapper of kubernetes API client +type Client struct { + clientset kubernetes.Interface +} + +// NewClient returns Client struct +func NewClient() (*Client, error) { + config, err := getConfig() + if err != nil { + return nil, err + } + + clientSet, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } + + return &Client{ + clientset: clientSet, + }, nil +} + +func getConfig() (config *rest.Config, err error) { + var path string + + if !env.IsInCluster() { + usr, err := user.Current() + if err != nil { + return nil, err + } + + path = usr.HomeDir + "/.kube/config" + } + + config, err = clientcmd.BuildConfigFromFlags("", path) + if err != nil { + return nil, err + } + return config, nil +} + +// ListJobs returns the list of Jobs +func (c *Client) ListJobs(namespace string) (*batchv1.JobList, error) { + jobs, err := c.clientset.BatchV1().Jobs(namespace).List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + return jobs, err +} From 3ec42919f3ad860d42302de6bda76c9603ebc375 Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 13:20:28 +0900 Subject: [PATCH 2/9] Replace to local kubernetes pkg --- main.go | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/main.go b/main.go index 49bc1de..2a0541a 100644 --- a/main.go +++ b/main.go @@ -1,65 +1,38 @@ package main import ( - "flag" "log" "os" - "os/user" "time" "go.uber.org/zap" + k8s "./kubernetes" "github.com/sukeesh/k8s-job-notify/env" "github.com/sukeesh/k8s-job-notify/message" "github.com/sukeesh/k8s-job-notify/slack" - "k8s.io/client-go/rest" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" - "k8s.io/client-go/tools/clientcmd" ) func main() { - var kubeconfig *string - var config *rest.Config - var err error - pastJobs := make(map[string]bool) - if env.IsInCluster() { - config, err = rest.InClusterConfig() - if err != nil { - panic(err.Error()) - } - log.Printf("using inClusterConfig") - } else { - usr, err := user.Current() - if err != nil { - panic(err.Error()) - } - filePath := usr.HomeDir + "/.kube/config" - kubeconfig = flag.String("kubeconfig", filePath, "absolute path to file") - flag.Parse() - config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) - if err != nil { - panic(err.Error()) - } - } - clientSet, err := kubernetes.NewForConfig(config) + client, err := k8s.NewClient() if err != nil { - panic(err.Error()) + log.Fatalf("failed to create client %v", zap.Error(err)) + os.Exit(1) } namespace := env.GetNamespace() log.Printf("fetching jobs from %s namespace", namespace) for { - jobs, err := clientSet.BatchV1().Jobs(namespace).List(metav1.ListOptions{}) + jobs, err := client.ListJobs(namespace) if err != nil { log.Fatalf("failed to list all jobs in the namespace %v", zap.Error(err)) os.Exit(1) } + for _, job := range jobs.Items { // job.Name can be same for different jobs, so using job.Name+CreationTimeStamp for checking // uniqueness of the job. so that duplicated messages to slack can be avoided From 56824e0ef53dcc5804384646ae95ded0c905685a Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 13:21:04 +0900 Subject: [PATCH 3/9] Use k8s.io/api --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 14cb741..4086597 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( golang.org/x/net v0.0.0-20191125084936-ffdde1057850 // indirect golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect - k8s.io/api v0.0.0-20191121015604-11707872ac1c // indirect + k8s.io/api v0.0.0-20191121015604-11707872ac1c k8s.io/apimachinery v0.0.0-20191123233150-4c4803ed55e3 k8s.io/client-go v0.0.0-20190620085101-78d2af792bab k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6 // indirect From 062ff36e76fd8528db09d71e294283439c2c924c Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 13:21:30 +0900 Subject: [PATCH 4/9] Remove unreachable code --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index 2a0541a..a5cec9a 100644 --- a/main.go +++ b/main.go @@ -57,5 +57,4 @@ func main() { time.Sleep(time.Minute * 1) log.Printf("end of 1 minute wait.. fetching new jobs") } - os.Exit(0) } From 944eee610fb0b6b1db78c7dc7deb6ee9a604ecf8 Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 13:23:32 +0900 Subject: [PATCH 5/9] Fix error definition --- kubernetes/client.go | 2 +- main.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kubernetes/client.go b/kubernetes/client.go index 8485e38..f7bf3db 100644 --- a/kubernetes/client.go +++ b/kubernetes/client.go @@ -59,5 +59,5 @@ func (c *Client) ListJobs(namespace string) (*batchv1.JobList, error) { if err != nil { return nil, err } - return jobs, err + return jobs, nil } diff --git a/main.go b/main.go index a5cec9a..4880075 100644 --- a/main.go +++ b/main.go @@ -40,13 +40,13 @@ func main() { if pastJobs[jobUniqueHash] == false && job.Status.StartTime.Time.Add(time.Minute*20).After(time.Now()) { if job.Status.Succeeded > 0 { timeSinceCompletion := time.Now().Sub(job.Status.CompletionTime.Time).Minutes() - err = slack.SendSlackMessage(message.JobSuccess(job.Name, timeSinceCompletion)) + err := slack.SendSlackMessage(message.JobSuccess(job.Name, timeSinceCompletion)) if err != nil { log.Fatalf("sending a message to slack failed %v", zap.Error(err)) } pastJobs[jobUniqueHash] = true } else if job.Status.Failed > 0 { - err = slack.SendSlackMessage(message.JobFailure(job.Name)) + err := slack.SendSlackMessage(message.JobFailure(job.Name)) if err != nil { log.Fatalf("sending a message to slack failed %v", zap.Error(err)) } From ceeb9eede7e07d43f655f2128a899765994ade3d Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 13:39:55 +0900 Subject: [PATCH 6/9] Set kubeconfig flag --- kubernetes/client.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kubernetes/client.go b/kubernetes/client.go index f7bf3db..271e689 100644 --- a/kubernetes/client.go +++ b/kubernetes/client.go @@ -46,7 +46,10 @@ func getConfig() (config *rest.Config, err error) { path = usr.HomeDir + "/.kube/config" } - config, err = clientcmd.BuildConfigFromFlags("", path) + kubeconfig := flag.String("kubeconfig", path, "absolute path to file") + flag.Parse() + + config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { return nil, err } From e7dceeceed06c2ab2b06861392d34b3435a821ab Mon Sep 17 00:00:00 2001 From: asuforce Date: Wed, 20 May 2020 18:47:14 +0900 Subject: [PATCH 7/9] Use previous logic --- kubernetes/client.go | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/kubernetes/client.go b/kubernetes/client.go index 271e689..9a92e41 100644 --- a/kubernetes/client.go +++ b/kubernetes/client.go @@ -35,24 +35,27 @@ func NewClient() (*Client, error) { } func getConfig() (config *rest.Config, err error) { - var path string - - if !env.IsInCluster() { + if env.IsInCluster() { + config, err = rest.InClusterConfig() + if err != nil { + return nil, err + } + log.Printf("using inClusterConfig") + } else { usr, err := user.Current() if err != nil { return nil, err } - path = usr.HomeDir + "/.kube/config" + filePath := usr.HomeDir + "/.kube/config" + kubeconfig = flag.String("kubeconfig", filePath, "absolute path to file") + flag.Parse() + config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) + if err != nil { + return nil, err + } } - kubeconfig := flag.String("kubeconfig", path, "absolute path to file") - flag.Parse() - - config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) - if err != nil { - return nil, err - } return config, nil } From d9dff4579c97ed3a51a8eea5250f798f71e12be6 Mon Sep 17 00:00:00 2001 From: Sukeesh Date: Thu, 4 Jun 2020 20:28:20 +0530 Subject: [PATCH 8/9] refactor --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 4880075..06eac0d 100644 --- a/main.go +++ b/main.go @@ -7,8 +7,8 @@ import ( "go.uber.org/zap" - k8s "./kubernetes" "github.com/sukeesh/k8s-job-notify/env" + k8s "github.com/sukeesh/k8s-job-notify/kubernetes" "github.com/sukeesh/k8s-job-notify/message" "github.com/sukeesh/k8s-job-notify/slack" From 70dccd2fa0395c205240b5490a41d100d1f910b6 Mon Sep 17 00:00:00 2001 From: Sukeesh Date: Thu, 4 Jun 2020 20:40:50 +0530 Subject: [PATCH 9/9] fix message to slack --- kubernetes/client.go | 4 +++- message/message.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/kubernetes/client.go b/kubernetes/client.go index 9a92e41..8b752e4 100644 --- a/kubernetes/client.go +++ b/kubernetes/client.go @@ -1,6 +1,8 @@ package kubernetes import ( + "flag" + "log" "os/user" "github.com/sukeesh/k8s-job-notify/env" @@ -48,7 +50,7 @@ func getConfig() (config *rest.Config, err error) { } filePath := usr.HomeDir + "/.kube/config" - kubeconfig = flag.String("kubeconfig", filePath, "absolute path to file") + kubeconfig := flag.String("kubeconfig", filePath, "absolute path to file") flag.Parse() config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { diff --git a/message/message.go b/message/message.go index 83af5db..624c5f5 100644 --- a/message/message.go +++ b/message/message.go @@ -5,7 +5,7 @@ import ( ) func JobSuccess(jobName string, timeSinceCompletion float64) string { - return "*" + jobName + "* succeeded " + fmt.Sprintf("%f", timeSinceCompletion) + " minutes ago :tada:" + return "*" + jobName + "* succeeded " + fmt.Sprintf("%.1f", timeSinceCompletion) + " minutes ago :tada:" } func JobFailure(jobName string) string {