Skip to content

Commit 7beac30

Browse files
refactor!: rewrite and cleanup kubenurse server code (#29)
* refactor!: rewrite and cleanup kubenurse server code By using a package and multiple separate files the code is easier to understand and test. A new /ready handler was added so we can configure a readiness probe to allow seamless updates of kubenurse. * build: update golangci-lint version * build: update golangci-lint timeout, default is too short * build: extract lint step and use go version 1.17 * feat: configure new readinessprobe in kustomize and helm templates * fix: linter errors * chore: cleanup, remove not needed WaitGroup * refactor!: move pkg/kubediscovery to internal/kubediscovery * refactor!: move pkg/checker to internal/servicecheck * refactor!: incorporate pkg/metrics in internal/servicecheck * refactor!: more refactorings to allow easier unit testing * feat: more unit tests and coverage calculation in workflows * docs: include ci and coverage badges in readme * docs: fix coverage status URL Co-authored-by: Clément Nussbaumer <[email protected]> * chore: embed servicecheck.Result in /alive output for simplicity Co-authored-by: Clément Nussbaumer <[email protected]>
1 parent 50fb9eb commit 7beac30

26 files changed

+788
-327
lines changed

.github/workflows/ci-helm-deploy.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
name: ci-helm-deploy
2+
name: deploy with helm
33
on:
44
push:
55
pull_request:
@@ -11,10 +11,8 @@ jobs:
1111
uses: actions/checkout@v2
1212
- name: Setup Go
1313
uses: actions/setup-go@v2
14-
- name: golangci-lint
15-
uses: golangci/golangci-lint-action@v2
1614
with:
17-
version: v1.32
15+
go-version: 1.17
1816
- name: GoReleaser
1917
uses: goreleaser/goreleaser-action@v2
2018
with:

.github/workflows/ci-kustomize-deploy.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
name: ci-kustomize-deploy
2+
name: deploy with kustomize
33
on:
44
push:
55
pull_request:
@@ -11,10 +11,8 @@ jobs:
1111
uses: actions/checkout@v2
1212
- name: Setup Go
1313
uses: actions/setup-go@v2
14-
- name: golangci-lint
15-
uses: golangci/golangci-lint-action@v2
1614
with:
17-
version: v1.32
15+
go-version: 1.17
1816
- name: GoReleaser
1917
uses: goreleaser/goreleaser-action@v2
2018
with:

.github/workflows/helm-lint.yml

Lines changed: 0 additions & 12 deletions
This file was deleted.

.github/workflows/lint.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
name: lint and test
3+
on:
4+
push:
5+
pull_request:
6+
jobs:
7+
lint-go:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- uses: golangci/golangci-lint-action@v2
12+
with:
13+
version: v1.43
14+
args: --timeout 5m
15+
lint-helm:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v2
19+
- name: Helm lint
20+
shell: bash
21+
run: |
22+
helm lint ./helm/kubenurse/
23+
test-go:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v2
27+
- uses: actions/setup-go@v2
28+
with:
29+
go-version: 1.17
30+
- name: Run unit tests
31+
run: go test -race -covermode atomic -coverprofile=profile.cov ./...
32+
- name: Send coverage report
33+
env:
34+
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
run: |
36+
go install github.com/mattn/[email protected]
37+
goveralls -coverprofile=profile.cov -service=github

.github/workflows/release.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ jobs:
1212
uses: actions/checkout@v2
1313
- name: Setup Go
1414
uses: actions/setup-go@v2
15-
- name: golangci-lint
16-
uses: golangci/golangci-lint-action@v2
1715
with:
18-
version: v1.32
16+
go-version: 1.17
1917
- name: Login to DockerHub
2018
uses: docker/login-action@v1
2119
with:

.golangci.yml

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
# options for analysis running
1+
---
22
run:
3-
tests: true
4-
timeout: 3m
5-
6-
7-
# all available settings of specific linters
3+
tests: false
4+
skip-dirs:
5+
- .github
6+
- build
7+
- web
8+
- .go
89
linters-settings:
910
dupl:
10-
threshold: 150
11+
threshold: 100
1112
funlen:
1213
lines: 100
1314
statements: 50
1415
goconst:
1516
min-len: 2
16-
min-occurrences: 3
17+
min-occurrences: 2
1718
gocritic:
1819
enabled-tags:
1920
- diagnostic
@@ -23,21 +24,27 @@ linters-settings:
2324
- style
2425
disabled-checks:
2526
- whyNoLint
27+
- hugeParam
2628
gocyclo:
2729
min-complexity: 15
28-
golint:
30+
revive:
2931
min-confidence: 0.8
3032
govet:
3133
check-shadowing: true
32-
maligned:
33-
suggest-new: true
34+
lll:
35+
line-length: 140
3436
misspell:
3537
locale: UK
38+
nolintlint:
39+
allow-leading-space: false
40+
require-explanation: true
41+
allow-no-explanation:
42+
- gocognit
43+
- funlen
44+
- gocyclo
3645

3746
linters:
38-
disable:
39-
- gomnd
40-
- lll
47+
disable-all: true
4148
enable:
4249
- bodyclose
4350
- deadcode
@@ -46,28 +53,26 @@ linters:
4653
- dupl
4754
- errcheck
4855
- funlen
56+
- nolintlint
4957
- gochecknoglobals
5058
- gochecknoinits
5159
- gocognit
5260
- goconst
5361
- gocritic
5462
- gocyclo
55-
- godox
5663
- gofmt
5764
- goimports
58-
- golint
65+
- revive
5966
- goprintffuncname
6067
- gosec
6168
- gosimple
6269
- govet
6370
- ineffassign
64-
- interfacer
65-
- maligned
6671
- misspell
6772
- nakedret
6873
- prealloc
6974
- rowserrcheck
70-
- scopelint # todo
75+
- exportloopref
7176
- staticcheck
7277
- structcheck
7378
- stylecheck
@@ -78,12 +83,11 @@ linters:
7883
- varcheck
7984
- whitespace
8085
- wsl
81-
82-
8386
issues:
8487
exclude:
8588
# Very commonly not checked.
86-
- 'Error return value of .(l.Sync|.*Close|.*Flush|os\.Remove(All)?|os\.(Un)?Setenv). is not checked'
89+
- 'Error return value of .(l.Sync|.*Close|.*.Write|.*Flush|os\.Remove(All)?|os\.(Un)?Setenv). is not checked'
90+
- 'G104:.*'
8791
- 'exported method (.*\.MarshalJSON|.*\.UnmarshalJSON) should have comment or be unexported'
8892
- 'shadow: declaration of "err" shadows declaration.*'
8993
max-same-issues: 0

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[![CI](https://github.com/postfinance/kubenurse/actions/workflows/release.yml/badge.svg)](https://github.com/postfinance/kubenurse/actions/workflows/release.yml)
2+
[![Coverage Status](https://coveralls.io/repos/github/postfinance/kubenurse/badge.svg?branch=master)](https://coveralls.io/github/postfinance/kubenurse?branch=master)
3+
14
# Kubenurse
25
kubenurse is a little service that monitors all network connections in a kubernetes
36
cluster and exports the taken metrics as prometheus endpoint.

examples/daemonset.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ spec:
3636
ports:
3737
- containerPort: 8080
3838
protocol: TCP
39+
readinessProbe:
40+
failureThreshold: 1
41+
httpGet:
42+
path: /ready
43+
port: 8080
44+
scheme: HTTP
45+
periodSeconds: 3
46+
successThreshold: 1
47+
timeoutSeconds: 1
3948
tolerations:
4049
- effect: NoSchedule
4150
key: node-role.kubernetes.io/master

go.mod

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/postfinance/kubenurse
22

3-
go 1.15
3+
go 1.17
44

55
require (
66
github.com/prometheus/client_golang v1.11.0
@@ -9,3 +9,41 @@ require (
99
k8s.io/apimachinery v0.22.2
1010
k8s.io/client-go v0.22.2
1111
)
12+
13+
require (
14+
github.com/beorn7/perks v1.0.1 // indirect
15+
github.com/cespare/xxhash/v2 v2.1.1 // indirect
16+
github.com/davecgh/go-spew v1.1.1 // indirect
17+
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
18+
github.com/go-logr/logr v0.4.0 // indirect
19+
github.com/gogo/protobuf v1.3.2 // indirect
20+
github.com/golang/protobuf v1.5.2 // indirect
21+
github.com/google/go-cmp v0.5.5 // indirect
22+
github.com/google/gofuzz v1.1.0 // indirect
23+
github.com/googleapis/gnostic v0.5.5 // indirect
24+
github.com/json-iterator/go v1.1.11 // indirect
25+
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
26+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
27+
github.com/modern-go/reflect2 v1.0.1 // indirect
28+
github.com/pkg/errors v0.9.1 // indirect
29+
github.com/pmezard/go-difflib v1.0.0 // indirect
30+
github.com/prometheus/client_model v0.2.0 // indirect
31+
github.com/prometheus/common v0.26.0 // indirect
32+
github.com/prometheus/procfs v0.6.0 // indirect
33+
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 // indirect
34+
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
35+
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
36+
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
37+
golang.org/x/text v0.3.6 // indirect
38+
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
39+
google.golang.org/appengine v1.6.5 // indirect
40+
google.golang.org/protobuf v1.26.0 // indirect
41+
gopkg.in/inf.v0 v0.9.1 // indirect
42+
gopkg.in/yaml.v2 v2.4.0 // indirect
43+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
44+
k8s.io/klog/v2 v2.9.0 // indirect
45+
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
46+
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect
47+
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
48+
sigs.k8s.io/yaml v1.2.0 // indirect
49+
)

helm/kubenurse/templates/daemonset.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ spec:
4545
ports:
4646
- containerPort: 8080
4747
protocol: TCP
48+
readinessProbe:
49+
failureThreshold: 1
50+
httpGet:
51+
path: /ready
52+
port: 8080
53+
scheme: HTTP
54+
periodSeconds: 3
55+
successThreshold: 1
56+
timeoutSeconds: 1
4857
tolerations:
4958
- effect: NoSchedule
5059
key: node-role.kubernetes.io/master

pkg/kubediscovery/kubediscovery.go renamed to internal/kubediscovery/kubediscovery.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99

1010
"k8s.io/client-go/kubernetes"
11-
"k8s.io/client-go/rest"
1211
)
1312

1413
// Client provides the kubediscovery client methods.
@@ -42,19 +41,11 @@ type Neighbour struct {
4241
// New creates a new kubediscovery client. The context is used to stop the k8s watchers/informers.
4342
// When allowUnschedulable is true, no node watcher is created and kubenurses
4443
// on unschedulable nodes are considered as neighbours.
45-
func New(ctx context.Context, allowUnschedulable bool) (*Client, error) {
46-
// create in-cluster config
47-
config, err := rest.InClusterConfig()
48-
if err != nil {
49-
return nil, fmt.Errorf("creating in-cluster configuration: %w", err)
50-
}
51-
52-
cliset, err := kubernetes.NewForConfig(config)
53-
if err != nil {
54-
return nil, fmt.Errorf("creating clientset: %w", err)
55-
}
56-
57-
var nc *nodeCache
44+
func New(ctx context.Context, cliset kubernetes.Interface, allowUnschedulable bool) (*Client, error) {
45+
var (
46+
nc *nodeCache
47+
err error
48+
)
5849

5950
// Watch nodes only if we do not consider kubenurses on unschedulable nodes
6051
if !allowUnschedulable {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package kubediscovery
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
v1 "k8s.io/api/core/v1"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/client-go/kubernetes"
11+
"k8s.io/client-go/kubernetes/fake"
12+
)
13+
14+
var (
15+
kubenursePod = v1.Pod{
16+
ObjectMeta: metav1.ObjectMeta{
17+
Name: "kubenurse-dummy",
18+
Labels: map[string]string{
19+
"app": "kubenurse",
20+
},
21+
},
22+
}
23+
differentPod = v1.Pod{
24+
ObjectMeta: metav1.ObjectMeta{
25+
Name: "different",
26+
Labels: map[string]string{
27+
"app": "different",
28+
},
29+
},
30+
}
31+
)
32+
33+
func TestGetNeighbours(t *testing.T) {
34+
r := require.New(t)
35+
fakeClient := fake.NewSimpleClientset()
36+
37+
createFakePods(fakeClient)
38+
39+
client, err := New(context.Background(), fakeClient, false)
40+
r.NoError(err)
41+
42+
neighbours, err := client.GetNeighbours(context.Background(), "kube-system", "app=kubenurse")
43+
r.NoError(err)
44+
r.Len(neighbours, 1)
45+
r.Equal(kubenursePod.ObjectMeta.Name, neighbours[0].PodName)
46+
}
47+
48+
func createFakePods(k8s kubernetes.Interface) {
49+
for _, pod := range []v1.Pod{kubenursePod, differentPod} {
50+
_, err := k8s.CoreV1().Pods("kube-system").Create(context.Background(), &pod, metav1.CreateOptions{})
51+
if err != nil {
52+
panic(err)
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)