Skip to content

Commit e4a96d7

Browse files
authored
Initial API integration test (#54)
* on pull request we are going to run tests * added `api/v1/integration_test.go` for integration tests against embedded API server * added test verifying that `.spec.servicePerNode` does not flip on object update
1 parent feead4e commit e4a96d7

File tree

6 files changed

+278
-1
lines changed

6 files changed

+278
-1
lines changed

.github/workflows/pr-workflow.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ jobs:
4040
uses: CatChen/check-git-status-action@v1
4141
with:
4242
fail-if-not-clean: true
43+
44+
- name: Tests
45+
run: |
46+
make test

Makefile

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
LOCALBIN ?= $(shell pwd)/bin
33
$(LOCALBIN):
44
mkdir -p $(LOCALBIN)
5+
ENVTEST ?= $(LOCALBIN)/setup-envtest
6+
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
7+
ENVTEST_K8S_VERSION = 1.30.0
8+
ENVTEST_VERSION ?= release-0.19
59

610
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
711
CRD_REF_DOCS ?= $(LOCALBIN)/crd-ref-docs
@@ -72,4 +76,30 @@ vet: ## Run go vet against code.
7276
go vet ./...
7377

7478
$(GCI): $(LOCALBIN)
75-
GOBIN=$(LOCALBIN) go install github.com/daixiang0/gci@latest
79+
GOBIN=$(LOCALBIN) go install github.com/daixiang0/gci@latest
80+
81+
82+
.PHONY: envtest
83+
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
84+
$(ENVTEST): $(LOCALBIN)
85+
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
86+
87+
test: manifests generate fmt vet envtest ## Run tests.
88+
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out
89+
90+
91+
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
92+
# $1 - target path with name of binary
93+
# $2 - package url which can be installed
94+
# $3 - specific version of package
95+
define go-install-tool
96+
@[ -f "$(1)-$(3)" ] || { \
97+
set -e; \
98+
package=$(2)@$(3) ;\
99+
echo "Downloading $${package}" ;\
100+
rm -f $(1) || true ;\
101+
GOBIN=$(LOCALBIN) go install $${package} ;\
102+
mv $(1) $(1)-$(3) ;\
103+
} ;\
104+
ln -sf $(1)-$(3) $(1)
105+
endef

api/v1/integration_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package v1
2+
3+
import (
4+
"context"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
corev1 "k8s.io/api/core/v1"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
)
11+
12+
var _ = Describe("QdrantCluster", func() {
13+
Context("API integration tests", func() {
14+
const namespaceName = "test-namespace"
15+
ctx := context.Background()
16+
namespace := &corev1.Namespace{
17+
ObjectMeta: metav1.ObjectMeta{
18+
Name: namespaceName,
19+
},
20+
}
21+
BeforeEach(func() {
22+
By("Creating the Namespace to perform the tests")
23+
err := k8sClient.Create(ctx, namespace)
24+
Expect(err).To(Not(HaveOccurred()))
25+
})
26+
It("should not flip ServicePerNode value on update", func() {
27+
qc := QdrantCluster{
28+
ObjectMeta: metav1.ObjectMeta{
29+
Namespace: namespaceName,
30+
Name: "test-cluster",
31+
},
32+
Spec: QdrantClusterSpec{
33+
Id: "test-cluster",
34+
Size: 1,
35+
ServicePerNode: NewPointer(false),
36+
},
37+
}
38+
err := k8sClient.Create(ctx, &qc)
39+
Expect(err).To(Not(HaveOccurred()))
40+
Expect(DerefPointer(qc.Spec.ServicePerNode)).To(BeFalse())
41+
42+
qc.Spec.Size = 2
43+
err = k8sClient.Update(ctx, &qc)
44+
Expect(err).To(Not(HaveOccurred()))
45+
Expect(DerefPointer(qc.Spec.ServicePerNode)).To(BeFalse())
46+
})
47+
})
48+
49+
})
50+
51+
// NewPointer is a generic function to create a pointer to any type.
52+
func NewPointer[T any](value T) *T {
53+
return &value
54+
}
55+
56+
// DerefPointer is a generic function to dereference a pointer with a default-value fallback.
57+
func DerefPointer[T any](ptr *T, defaults ...T) T {
58+
if ptr != nil {
59+
return *ptr
60+
}
61+
if len(defaults) > 0 {
62+
return defaults[0]
63+
}
64+
var empty T
65+
return empty
66+
}

api/v1/suite_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package v1
2+
3+
import (
4+
"fmt"
5+
"path/filepath"
6+
"runtime"
7+
"testing"
8+
9+
. "github.com/onsi/ginkgo/v2"
10+
. "github.com/onsi/gomega"
11+
"k8s.io/client-go/kubernetes/scheme"
12+
"k8s.io/client-go/rest"
13+
"sigs.k8s.io/controller-runtime/pkg/client"
14+
"sigs.k8s.io/controller-runtime/pkg/envtest"
15+
logf "sigs.k8s.io/controller-runtime/pkg/log"
16+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
17+
)
18+
19+
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
20+
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
21+
22+
var cfg *rest.Config
23+
var k8sClient client.Client
24+
var testEnv *envtest.Environment
25+
26+
func TestControllers(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
29+
RunSpecs(t, "Controller Suite")
30+
}
31+
32+
var _ = BeforeSuite(func() {
33+
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
34+
35+
By("bootstrapping test environment")
36+
testEnv = &envtest.Environment{
37+
CRDDirectoryPaths: []string{filepath.Join("..", "..", "crds")},
38+
ErrorIfCRDPathMissing: true,
39+
40+
// The BinaryAssetsDirectory is only required if you want to run the tests directly
41+
// without call the makefile target test. If not informed it will look for the
42+
// default path defined in controller-runtime which is /usr/local/kubebuilder/.
43+
// Note that you must have the required binaries setup under the bin directory to perform
44+
// the tests directly. When we run make test it will be setup and used automatically.
45+
BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s",
46+
fmt.Sprintf("1.30.0-%s-%s", runtime.GOOS, runtime.GOARCH)),
47+
}
48+
49+
var err error
50+
// cfg is defined in this file globally.
51+
cfg, err = testEnv.Start()
52+
Expect(err).NotTo(HaveOccurred())
53+
Expect(cfg).NotTo(BeNil())
54+
55+
err = AddToScheme(scheme.Scheme)
56+
Expect(err).NotTo(HaveOccurred())
57+
58+
// +kubebuilder:scaffold:scheme
59+
60+
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
61+
Expect(err).NotTo(HaveOccurred())
62+
Expect(k8sClient).NotTo(BeNil())
63+
64+
})
65+
66+
var _ = AfterSuite(func() {
67+
By("tearing down the test environment")
68+
err := testEnv.Stop()
69+
Expect(err).NotTo(HaveOccurred())
70+
})

go.mod

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,63 @@ go 1.23
55
require (
66
github.com/fluxcd/helm-controller/api v1.1.0
77
github.com/fluxcd/source-controller/api v1.4.1
8+
github.com/onsi/ginkgo/v2 v2.19.0
9+
github.com/onsi/gomega v1.33.1
810
github.com/stretchr/testify v1.10.0
911
k8s.io/api v0.31.3
1012
k8s.io/apimachinery v0.31.3
13+
k8s.io/client-go v0.31.1
1114
sigs.k8s.io/controller-runtime v0.19.3
1215
)
1316

1417
require (
1518
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
19+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
20+
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
1621
github.com/fluxcd/pkg/apis/acl v0.3.0 // indirect
1722
github.com/fluxcd/pkg/apis/kustomize v1.6.1 // indirect
1823
github.com/fluxcd/pkg/apis/meta v1.6.1 // indirect
1924
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
2025
github.com/go-logr/logr v1.4.2 // indirect
26+
github.com/go-logr/zapr v1.3.0 // indirect
27+
github.com/go-openapi/jsonpointer v0.19.6 // indirect
28+
github.com/go-openapi/jsonreference v0.20.2 // indirect
29+
github.com/go-openapi/swag v0.22.4 // indirect
30+
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
2131
github.com/gogo/protobuf v1.3.2 // indirect
32+
github.com/golang/protobuf v1.5.4 // indirect
33+
github.com/google/gnostic-models v0.6.8 // indirect
34+
github.com/google/go-cmp v0.6.0 // indirect
2235
github.com/google/gofuzz v1.2.0 // indirect
36+
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect
37+
github.com/google/uuid v1.6.0 // indirect
38+
github.com/imdario/mergo v0.3.6 // indirect
39+
github.com/josharian/intern v1.0.0 // indirect
2340
github.com/json-iterator/go v1.1.12 // indirect
41+
github.com/mailru/easyjson v0.7.7 // indirect
2442
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
2543
github.com/modern-go/reflect2 v1.0.2 // indirect
44+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
45+
github.com/pkg/errors v0.9.1 // indirect
2646
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
47+
github.com/spf13/pflag v1.0.5 // indirect
2748
github.com/x448/float16 v0.8.4 // indirect
49+
go.uber.org/multierr v1.11.0 // indirect
50+
go.uber.org/zap v1.26.0 // indirect
2851
golang.org/x/net v0.30.0 // indirect
52+
golang.org/x/oauth2 v0.21.0 // indirect
53+
golang.org/x/sys v0.26.0 // indirect
54+
golang.org/x/term v0.25.0 // indirect
2955
golang.org/x/text v0.19.0 // indirect
56+
golang.org/x/time v0.3.0 // indirect
57+
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
58+
google.golang.org/protobuf v1.34.2 // indirect
3059
gopkg.in/inf.v0 v0.9.1 // indirect
3160
gopkg.in/yaml.v2 v2.4.0 // indirect
3261
gopkg.in/yaml.v3 v3.0.1 // indirect
3362
k8s.io/apiextensions-apiserver v0.31.1 // indirect
3463
k8s.io/klog/v2 v2.130.1 // indirect
64+
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
3565
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 // indirect
3666
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
3767
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect

0 commit comments

Comments
 (0)