Add tests and run them in CI
This commit is contained in:
parent
0d70c9b96a
commit
00b7f12d65
7 changed files with 207 additions and 3 deletions
9
.github/workflows/go.yml
vendored
9
.github/workflows/go.yml
vendored
|
@ -27,6 +27,15 @@ jobs:
|
|||
with:
|
||||
lfs: true
|
||||
|
||||
- name: Install gotestsum
|
||||
run: go install gotest.tools/gotestsum@latest
|
||||
|
||||
- name: Create out directory
|
||||
run: mkdir -p ./out
|
||||
|
||||
- name: Run tests
|
||||
run: gotestsum -- -coverprofile=out/cover.txt -shuffle=on -race -covermode=atomic ./...
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,3 +16,4 @@
|
|||
|
||||
.idea/
|
||||
dist/
|
||||
out/
|
20
.pre-commit-config.yaml
Normal file
20
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/tekwizely/pre-commit-golang
|
||||
rev: v1.0.0-beta.5
|
||||
hooks:
|
||||
- id: go-mod-tidy-repo
|
||||
args:
|
||||
- -go=1.18
|
||||
- id: go-fumpt
|
||||
args:
|
||||
- -w
|
||||
- id: go-imports
|
||||
args:
|
||||
- -local=gitlab.com/inetmock/inetmock
|
||||
- -w
|
||||
- id: golangci-lint-repo-mod
|
||||
args:
|
||||
- --fast
|
||||
- --fix
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module github.com/baez90/kreaper
|
|||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/maxatome/go-testdeep v1.11.0
|
||||
go.uber.org/zap v1.21.0
|
||||
k8s.io/api v0.23.5
|
||||
k8s.io/apimachinery v0.23.5
|
||||
|
|
2
go.sum
2
go.sum
|
@ -194,6 +194,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
|
||||
github.com/maxatome/go-testdeep v1.11.0 h1:Tgh5efyCYyJFGUYiT0qxBSIDeXw0F5zSoatlou685kk=
|
||||
github.com/maxatome/go-testdeep v1.11.0/go.mod h1:011SgQ6efzZYAen6fDn4BqQ+lUR72ysdyKe7Dyogw70=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
12
main.go
12
main.go
|
@ -96,12 +96,18 @@ func prepareFlags() {
|
|||
"Set target namespace in which kreaper will look for pods - env variable: KREAPER_TARGET_NAMESPACE",
|
||||
)
|
||||
|
||||
var kubeconfigFallback string
|
||||
if home := homedir.HomeDir(); home != "" {
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", lookupEnvOr("KUBECONFIG", filepath.Join(home, ".kube", "config"), identity[string]), "(optional) absolute path to the kubeconfig file")
|
||||
} else {
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", lookupEnvOr("KUBECONFIG", "", identity[string]), "absolute path to the kubeconfig file")
|
||||
kubeconfigFallback = filepath.Join(home, ".kube", "config")
|
||||
}
|
||||
|
||||
flag.StringVar(
|
||||
&kubeconfig,
|
||||
"kubeconfig",
|
||||
lookupEnvOr("KUBECONFIG", kubeconfigFallback, identity[string]),
|
||||
"absolute path to the kubeconfig file",
|
||||
)
|
||||
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
|
|
165
reaper/reaper_test.go
Normal file
165
reaper/reaper_test.go
Normal file
|
@ -0,0 +1,165 @@
|
|||
package reaper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/maxatome/go-testdeep/td"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/baez90/kreaper/reaper"
|
||||
)
|
||||
|
||||
func TestKreaper_Kill(t *testing.T) {
|
||||
const defaultNamespace = "default"
|
||||
t.Parallel()
|
||||
type fields struct {
|
||||
initialState corev1.PodList
|
||||
lifetime time.Duration
|
||||
target reaper.Target
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
modifier func(tb testing.TB, k8sClient client.Client)
|
||||
wantErr error
|
||||
wantRemaining td.TestDeep
|
||||
}{
|
||||
{
|
||||
name: "Empty initial state",
|
||||
fields: fields{
|
||||
lifetime: 10 * time.Second,
|
||||
target: reaper.Target("app.kubernetes.io/name=ee8dcc4d"),
|
||||
},
|
||||
wantRemaining: td.Empty(),
|
||||
},
|
||||
{
|
||||
name: "Single pod to delete",
|
||||
fields: fields{
|
||||
target: reaper.Target("app.kubernetes.io/name=ee8dcc4d"),
|
||||
lifetime: 100 * time.Millisecond,
|
||||
initialState: corev1.PodList{
|
||||
Items: []corev1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "demo-asdf234",
|
||||
Namespace: defaultNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/name": "ee8dcc4d",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantRemaining: td.Empty(),
|
||||
},
|
||||
{
|
||||
name: "Single pod to delete - delete preemptively",
|
||||
fields: fields{
|
||||
target: reaper.Target("app.kubernetes.io/name=ee8dcc4d"),
|
||||
lifetime: 100 * time.Millisecond,
|
||||
initialState: corev1.PodList{
|
||||
Items: []corev1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "demo-asdf234",
|
||||
Namespace: defaultNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/name": "ee8dcc4d",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
modifier: func(tb testing.TB, k8sClient client.Client) {
|
||||
tb.Helper()
|
||||
td.CmpNoError(tb, k8sClient.DeleteAllOf(context.Background(), new(corev1.Pod)))
|
||||
},
|
||||
wantRemaining: td.Empty(),
|
||||
},
|
||||
{
|
||||
name: "Single pod to delete - one should remain",
|
||||
fields: fields{
|
||||
target: reaper.Target("app.kubernetes.io/name=ee8dcc4d"),
|
||||
lifetime: 100 * time.Millisecond,
|
||||
initialState: corev1.PodList{
|
||||
Items: []corev1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "demo-asdf234",
|
||||
Namespace: defaultNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/name": "ee8dcc4d",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "demo-lkjklsdf9234",
|
||||
Namespace: defaultNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/name": "ef903e61",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantRemaining: td.Len(1),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
k8sClient := fake.NewClientBuilder().
|
||||
WithLists(&tt.fields.initialState).
|
||||
Build()
|
||||
|
||||
k := reaper.Kreaper{
|
||||
Client: k8sClient,
|
||||
Lifetime: tt.fields.lifetime,
|
||||
Target: tt.fields.target,
|
||||
TargetNamespace: defaultNamespace,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancel)
|
||||
|
||||
errs := make(chan error, 1)
|
||||
|
||||
go func(ctx context.Context, errs chan<- error) {
|
||||
defer close(errs)
|
||||
errs <- k.Kill(ctx)
|
||||
if err := k.Kill(ctx); !errors.Is(err, tt.wantErr) {
|
||||
t.Errorf("Kill() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
}(ctx, errs)
|
||||
|
||||
if tt.modifier != nil {
|
||||
tt.modifier(t, k8sClient)
|
||||
}
|
||||
|
||||
for err := range errs {
|
||||
if !errors.Is(err, tt.wantErr) {
|
||||
t.Errorf("Kill() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var remainingPods corev1.PodList
|
||||
if err := k8sClient.List(ctx, &remainingPods); err != nil {
|
||||
t.Fatalf("Failed to list remaining pods err = %v", err)
|
||||
}
|
||||
|
||||
td.Cmp(t, remainingPods.Items, tt.wantRemaining)
|
||||
})
|
||||
}
|
||||
}
|
Reference in a new issue