Skip to content

Commit 8da85b5

Browse files
committed
feat: implement persistence
fixes #2 fixes #4 fixes #7
1 parent c476df8 commit 8da85b5

File tree

14 files changed

+523
-37
lines changed

14 files changed

+523
-37
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
.DS_Store
22
.idea/
33

4-
build/
5-
dist/
4+
/build/
5+
/dist/
6+
/data/
67

78
.cr-release-packages/

charts/lighthouse-webui-plugin/templates/deployment.yaml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ metadata:
1111
annotations: {{- tpl (toYaml .) $ | trim | nindent 4 }}
1212
{{- end }}
1313
spec:
14-
replicas: {{ .Values.deployment.replicas }}
14+
replicas: 1
1515
revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }}
16+
{{- with .Values.deployment.strategy }}
17+
strategy: {{- tpl (toYaml .) $ | trim | nindent 4 }}
18+
{{- end }}
1619
selector:
1720
matchLabels: {{- include "webui.labels.selector" . | nindent 6 }}
1821
template:
@@ -57,6 +60,12 @@ spec:
5760
- -log-level
5861
- {{ . }}
5962
{{- end }}
63+
- -store-data-path
64+
- "/data"
65+
- -store-max-events
66+
- {{ .Values.config.store.gc.maxEventsToKeep }}
67+
- -store-events-max-age
68+
- {{ .Values.config.store.gc.eventsMaxAge }}
6069
env:
6170
- name: XDG_CONFIG_HOME
6271
value: /home/jenkins
@@ -71,6 +80,9 @@ spec:
7180
envFrom:
7281
{{- toYaml . | trim | nindent 10 }}
7382
{{- end }}
83+
volumeMounts:
84+
- name: data
85+
mountPath: "/data"
7486
ports:
7587
- name: http
7688
containerPort: 8080
@@ -84,6 +96,14 @@ spec:
8496
{{- with .Values.pod.resources }}
8597
resources: {{- toYaml . | trim | nindent 10 }}
8698
{{- end }}
99+
volumes:
100+
- name: data
101+
{{- if .Values.persistence.enabled }}
102+
persistentVolumeClaim:
103+
claimName: {{ include "webui.fullname" . }}
104+
{{- else }}
105+
emptyDir: {}
106+
{{- end }}
87107
{{- with .Values.pod.securityContext }}
88108
securityContext: {{- toYaml . | trim | nindent 8 }}
89109
{{- end }}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{{- if .Values.persistence.enabled }}
2+
apiVersion: v1
3+
kind: PersistentVolumeClaim
4+
metadata:
5+
name: {{ template "webui.fullname" . }}
6+
labels:
7+
{{- include "webui.labels" . | nindent 4 }}
8+
{{- with .Values.persistence.labels }}
9+
{{- tpl (toYaml .) $ | trim | nindent 4 }}
10+
{{- end }}
11+
{{- with .Values.persistence.annotations }}
12+
annotations: {{- tpl (toYaml .) $ | trim | nindent 4 }}
13+
{{- end }}
14+
spec:
15+
{{- with .Values.persistence.storageClassName }}
16+
storageClassName: {{ . | quote }}
17+
{{- end }}
18+
accessModes:
19+
{{- range .Values.persistence.accessModes }}
20+
- {{ . | quote }}
21+
{{- end }}
22+
resources:
23+
requests:
24+
storage: {{ .Values.persistence.size | quote }}
25+
{{- end -}}

charts/lighthouse-webui-plugin/values.yaml

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ config:
1111
namespace: jx
1212
resyncInterval: 60s
1313
logLevel: INFO
14+
store:
15+
gc:
16+
# max number of events to keep in the store - if non-zero
17+
maxEventsToKeep: 0
18+
# max age of the events to keep in the store - if non-zero
19+
# this is a golang duration. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
20+
eventsMaxAge: 0
1421

1522
secrets:
1623
lighthouse:
@@ -26,10 +33,12 @@ image:
2633
pullPolicy:
2734

2835
deployment:
29-
replicas: 1
3036
revisionHistoryLimit: 2
3137
labels: {}
3238
annotations: {}
39+
strategy:
40+
# if you enable persistence, you should switch to `Recreate`
41+
type: RollingUpdate
3342

3443
pod:
3544
resources:
@@ -53,6 +62,7 @@ pod:
5362
fsGroup: 1000
5463
env: {}
5564
envFrom: []
65+
5666
service:
5767
port: 80
5868
type:
@@ -96,10 +106,16 @@ istio:
96106
apiVersion: networking.istio.io/v1beta1
97107
gateway: jx-gateway
98108

99-
jx:
100-
# whether to create a Release CRD when installing charts with Release CRDs included
101-
releaseCRD: true
102-
109+
# persistence for the events
110+
persistence:
111+
enabled: false
112+
size: 1Gi
113+
accessModes:
114+
- ReadWriteOnce
115+
storageClassName:
116+
labels: {}
117+
annotations: {}
118+
103119
serviceAccount:
104120
# allow additional annotations to be added to the ServiceAccount
105121
# such as for workload identity on clouds
@@ -110,3 +126,7 @@ role:
110126
- apiGroups: ["lighthouse.jenkins.io"]
111127
resources: ["lighthousejobs"]
112128
verbs: ["list", "watch", "get"]
129+
130+
jx:
131+
# whether to create a Release CRD when installing charts with Release CRDs included
132+
releaseCRD: true

cmd/server/main.go

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import (
77
"fmt"
88
"net/http"
99
"os"
10+
"os/signal"
11+
"sync"
12+
"syscall"
1013
"time"
1114

1215
webui "github.com/jenkins-x-plugins/lighthouse-webui-plugin"
@@ -27,6 +30,7 @@ var (
2730
keeperEndpoint string
2831
keeperSyncInterval time.Duration
2932
eventTraceURLTemplate string
33+
storeConfig webui.StoreConfig
3034
kubeConfigPath string
3135
listenAddr string
3236
logLevel string
@@ -42,6 +46,9 @@ func init() {
4246
flag.DurationVar(&options.keeperSyncInterval, "keeper-sync-interval", 1*time.Minute, "Interval to poll the Lighthouse Keeper service for its state")
4347
flag.StringVar(&options.eventTraceURLTemplate, "event-trace-url-template", "", "Go template string used to build the event trace URL")
4448
flag.StringVar(&options.logLevel, "log-level", "INFO", "Log level - one of: trace, debug, info, warn(ing), error, fatal or panic")
49+
flag.StringVar(&options.storeConfig.DataPath, "store-data-path", "", "If non-empty, the events store will be persisted on disk in the directory")
50+
flag.IntVar(&options.storeConfig.MaxEvents, "store-max-events", 0, "If non-zero, the internal GC will ensure that no more than that many number of events will be stored/persisted")
51+
flag.DurationVar(&options.storeConfig.EventsMaxAge, "store-events-max-age", 0, "If non-zero, the internal GC will ensure to events older than this age (duration) will be removed from the store")
4552
flag.StringVar(&options.kubeConfigPath, "kubeconfig", kube.DefaultKubeConfigPath(), "Kubernetes Config Path. Default: KUBECONFIG env var value")
4653
flag.StringVar(&options.listenAddr, "listen-addr", ":8080", "Address on which the server will listen for incoming connections")
4754
flag.BoolVar(&options.printVersion, "version", false, "Print the version")
@@ -55,8 +62,8 @@ func main() {
5562
return
5663
}
5764

58-
ctx, cancelFunc := context.WithCancel(context.Background())
59-
defer cancelFunc()
65+
ctx, cancelCtx := context.WithCancel(context.Background())
66+
defer cancelCtx()
6067

6168
logger := logrus.New()
6269
logLevel, err := logrus.ParseLevel(options.logLevel)
@@ -65,7 +72,7 @@ func main() {
6572
} else {
6673
logger.SetLevel(logLevel)
6774
}
68-
logger.WithField("logLevel", logLevel).Info("Starting")
75+
logger.WithField("logLevel", logLevel).WithField("version", version.Version).Info("Starting")
6976

7077
kConfig, err := kube.NewConfig(options.kubeConfigPath)
7178
if err != nil {
@@ -76,11 +83,12 @@ func main() {
7683
logger.WithError(err).Fatal("failed to create a Lighthouse client")
7784
}
7885

79-
store, err := webui.NewStore()
86+
store, err := webui.NewStore(options.storeConfig, logger)
8087
if err != nil {
8188
logger.WithError(err).Fatal("failed to create a new store")
8289
}
8390

91+
logger.WithField("endpoint", options.keeperEndpoint).WithField("syncInterval", options.keeperSyncInterval).Info("Starting Keeper Syncer")
8492
(&webui.KeeperSyncer{
8593
KeeperEndpoint: options.keeperEndpoint,
8694
SyncInterval: options.keeperSyncInterval,
@@ -116,11 +124,45 @@ func main() {
116124
if err != nil {
117125
logger.WithError(err).Fatal("failed to initialize the HTTP handler")
118126
}
119-
http.Handle("/", handler)
120-
121-
logger.WithField("listenAddr", options.listenAddr).Info("Starting HTTP Server")
122-
err = http.ListenAndServe(options.listenAddr, nil)
123-
if !errors.Is(err, http.ErrServerClosed) {
124-
logger.WithError(err).Fatal("failed to start HTTP server")
127+
httpServer := http.Server{
128+
Handler: handler,
129+
Addr: options.listenAddr,
125130
}
131+
132+
var wg sync.WaitGroup
133+
wg.Add(1)
134+
go func() {
135+
<-ctx.Done()
136+
shutdownCtx, cancelShutdownFunc := context.WithTimeout(context.Background(), 10*time.Second)
137+
defer cancelShutdownFunc()
138+
139+
logger.Info("Shutting down the HTTP server...")
140+
if err := httpServer.Shutdown(shutdownCtx); err != nil {
141+
logger.Warn("Timed-out while waiting for the HTTP server to shutdown!")
142+
}
143+
144+
logger.Info("Closing the store...")
145+
if err := store.Close(); err != nil {
146+
logger.WithError(err).Warn("failed to close the store")
147+
}
148+
149+
wg.Done()
150+
}()
151+
go func() {
152+
logger.WithField("listenAddr", options.listenAddr).Info("Starting HTTP Server")
153+
err = httpServer.ListenAndServe()
154+
if !errors.Is(err, http.ErrServerClosed) {
155+
logger.WithError(err).Fatal("failed to start HTTP server")
156+
}
157+
}()
158+
159+
c := make(chan os.Signal, 1)
160+
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
161+
sig := <-c
162+
163+
logger.WithField("signal", sig).Info("Interrupted by user (or killed) !")
164+
cancelCtx()
165+
wg.Wait()
166+
167+
logger.Info("This is the end, my friend")
126168
}

event.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ import (
55
"time"
66
)
77

8-
type Events []Event
8+
type Events struct {
9+
Events []Event
10+
Counts struct {
11+
Kinds map[string]int
12+
Repositories map[string]int
13+
Senders map[string]int
14+
}
15+
}
916

1017
type Event struct {
1118
GUID string

job.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ import (
88
lhv1alpha1 "github.com/jenkins-x/lighthouse/pkg/apis/lighthouse/v1alpha1"
99
)
1010

11-
type Jobs []Job
11+
type Jobs struct {
12+
Jobs []Job
13+
Counts struct {
14+
States map[string]int
15+
Types map[string]int
16+
Repositories map[string]int
17+
Authors map[string]int
18+
}
19+
}
1220

1321
type Job struct {
1422
Name string
@@ -19,6 +27,7 @@ type Job struct {
1927
Branch string
2028
Build string
2129
Context string
30+
Author string
2231
State string
2332
Description string
2433
ReportURL string
@@ -55,6 +64,13 @@ func JobFromLighthouseJob(lhjob *lhv1alpha1.LighthouseJob) Job {
5564
j.End = lhjob.Status.CompletionTime.Time
5665
j.Duration = j.End.Sub(j.Start)
5766
}
67+
if lhjob.Spec.Refs != nil {
68+
for _, pr := range lhjob.Spec.Refs.Pulls {
69+
if pr.Author != "" && j.Author == "" {
70+
j.Author = pr.Author
71+
}
72+
}
73+
}
5874
return j
5975
}
6076

0 commit comments

Comments
 (0)