Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: tests(integration): Move integration tests to tests/ #340

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,55 +70,64 @@ all: build
# http://linuxcommand.org/lc3_adv_awk.php

.PHONY: help
help: ## Display this help.
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Development

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."

##@ Test

.PHONY: fmt
fmt: ## Run go fmt against code.
fmt: ## Run go fmt against code.
go fmt ./...

.PHONY: vet
vet: ## Run go vet against code.
vet: ## Run go vet against code.
go vet ./...

.PHONY: test
test: fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test -v -coverprofile=coverage.out -coverpkg ./... ./...
.PHONY: test-unit
test-unit: ## Run unit tests.
go test -v -coverprofile=coverage.out `go list ./controllers/... ./pkg/... | grep -v ./pkg/mocks`

.PHONY: unit-test-coverage
unit-test-coverage: test
.PHONY: test-coverage
test-coverage: test-unit ## Run unit tests and print code coverage.
go tool cover -func coverage.out

.PHONY: test-integration
test-integration: ## Run integration tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test -v -tags=integration ./...

.PHONY: test
test: fmt vet envtest test-unit test-integration ## Run all tests (fmt, vet, envtest, unit & integration).

.PHONY: test-docker
test-docker:
test-docker: ## Run all tests (fmt, vet, envtest, unit & integration) inside a Docker container.
docker build -t test -f test.Dockerfile . && docker run test

##@ Build

.PHONY: build
build: generate fmt vet ## Build manager binary.
build: generate fmt vet ## Build manager binary.
go build -o bin/manager main.go

.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
run: manifests generate fmt vet ## Run a controller from your host.
go run ./main.go

.PHONY: docker-build
docker-build: ## Build docker image with the manager.
docker-build: ## Build docker image with the manager.
docker build -t ${IMG} .

.PHONY: docker-push
docker-push: ## Push docker image with the manager.
docker-push: ## Push docker image with the manager.
docker push ${IMG}

##@ Deployment
Expand All @@ -140,36 +149,36 @@ ifndef ignore-not-found
endif

.PHONY: install
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | kubectl apply -f -

.PHONY: uninstall
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -

.PHONY: undeploy
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
.PHONY: controller-gen
controller-gen: ## Download controller-gen locally if necessary.
controller-gen: ## Download controller-gen locally if necessary.
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@latest)

KUSTOMIZE = $(shell pwd)/bin/kustomize
.PHONY: kustomize
kustomize: manifests ## Download kustomize locally if necessary.
kustomize: manifests ## Download kustomize locally if necessary.
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/[email protected])
kustomize build config/default > deploy/kubeslice-operator.yaml

ENVTEST = $(shell pwd)/bin/setup-envtest
.PHONY: envtest
envtest: ## Download envtest-setup locally if necessary.
envtest: ## Download envtest-setup locally if necessary.
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)

# go-get-tool will 'go get' any package $2 and install it to $1.
Expand All @@ -187,23 +196,23 @@ rm -rf $$TMP_DIR ;\
endef

.PHONY: bundle
bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files.
bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files.
operator-sdk generate kustomize manifests -q
cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
operator-sdk bundle validate ./bundle

.PHONY: bundle-build
bundle-build: ## Build the bundle image.
bundle-build: ## Build the bundle image.
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .

.PHONY: bundle-push
bundle-push: ## Push the bundle image.
bundle-push: ## Push the bundle image.
$(MAKE) docker-push IMG=$(BUNDLE_IMG)

.PHONY: opm
OPM = ./bin/opm
opm: ## Download opm locally if necessary.
opm: ## Download opm locally if necessary.
ifeq (,$(wildcard $(OPM)))
ifeq (,$(shell which opm 2>/dev/null))
@{ \
Expand Down Expand Up @@ -234,12 +243,12 @@ endif
# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:
# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator
.PHONY: catalog-build
catalog-build: opm ## Build a catalog image.
catalog-build: opm ## Build a catalog image.
$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)

# Push the catalog image.
.PHONY: catalog-push
catalog-push: ## Push a catalog image.
catalog-push: ## Push a catalog image.
$(MAKE) docker-push IMG=$(CATALOG_IMG)

# Generate events schema map
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ package cluster
import (
"context"
"errors"
"reflect"
"runtime/debug"
"testing"

hubv1alpha1 "github.com/kubeslice/apis/pkg/controller/v1alpha1"
"github.com/kubeslice/kubeslice-monitoring/pkg/metrics"
kubeslicev1beta1 "github.com/kubeslice/worker-operator/api/v1beta1"
utilmock "github.com/kubeslice/worker-operator/pkg/mocks"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -87,9 +86,7 @@ func TestGetOperatorClusterRole(t *testing.T) {
mock.IsType(&rbacv1.ClusterRole{}),
).Return(nil)
_, err := reconciler.getOperatorClusterRole(ctx)
if expected.err != err {
t.Error("Expected error:", expected.err, " but got ", err)
}
assert.ErrorIs(t, expected.err, err)
}

func TestCreateDeregisterJobPositiveScenarios(t *testing.T) {
Expand Down Expand Up @@ -194,9 +191,7 @@ func TestCreateDeregisterJobPositiveScenarios(t *testing.T) {
mock.IsType([]k8sclient.CreateOption(nil)),
).Return(nil)
err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.err != err {
t.Error("Expected error:", expected.err, " but got ", err)
}
assert.ErrorIs(t, expected.err, err)
}

func TestReconcilerFailToUpdateClusterRegistrationStatus(t *testing.T) {
Expand Down Expand Up @@ -237,9 +232,7 @@ func TestReconcilerFailToUpdateClusterRegistrationStatus(t *testing.T) {
).Return(errors.New("error updating status of deregistration on the controller"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToCreateServiceAccount(t *testing.T) {
Expand Down Expand Up @@ -295,9 +288,7 @@ func TestReconcilerFailToCreateServiceAccount(t *testing.T) {
).Return(errors.New("unable to create service account"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToFetchOperatorClusterRole(t *testing.T) {
Expand Down Expand Up @@ -363,9 +354,7 @@ func TestReconcilerFailToFetchOperatorClusterRole(t *testing.T) {
).Return(errors.New("unable to fetch operator clusterrole"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToCreateClusterRole(t *testing.T) {
Expand Down Expand Up @@ -441,9 +430,7 @@ func TestReconcilerFailToCreateClusterRole(t *testing.T) {
).Return(errors.New("unable to create cluster role"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToCreateClusterRoleBinding(t *testing.T) {
Expand Down Expand Up @@ -524,9 +511,7 @@ func TestReconcilerFailToCreateClusterRoleBinding(t *testing.T) {
).Return(errors.New("unable to create cluster rolebinding"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToCreateConfigmap(t *testing.T) {
Expand Down Expand Up @@ -621,9 +606,7 @@ func TestReconcilerFailToCreateConfigmap(t *testing.T) {
mock.IsType([]k8sclient.CreateOption(nil)),
).Return(errors.New("Unable to create configmap"))
err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToDeleteJob(t *testing.T) {
Expand Down Expand Up @@ -729,9 +712,7 @@ func TestReconcilerFailToDeleteJob(t *testing.T) {
).Return(errors.New("Unable to delete deregister job"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestReconcilerFailToCreateDeregisterJob(t *testing.T) {
Expand Down Expand Up @@ -842,64 +823,42 @@ func TestReconcilerFailToCreateDeregisterJob(t *testing.T) {
).Return(errors.New("Unable to create deregister job"))

err := reconciler.createDeregisterJob(ctx, testClusterObj)
if expected.errMsg != err.Error() {
t.Error("Expected error:", expected.errMsg, " but got ", err)
}
assert.Equal(t, expected.errMsg, err.Error())
}

func TestGetConfigmapScriptData(t *testing.T) {
data, err := getCleanupScript()
AssertNoError(t, err)
if len(data) == 0 {
t.Fatalf("unable to get configmap data")
}
assert.NoError(t, err)
assert.NotZero(t, len(data), "unable to get configmap data")
}

func TestConstructJobForClusterDeregister(t *testing.T) {
job := constructJobForClusterDeregister()
AssertEqual(t, job.Name, deregisterJobName)
AssertEqual(t, job.Namespace, ControlPlaneNamespace)
assert.Equal(t, job.Name, deregisterJobName)
assert.Equal(t, job.Namespace, ControlPlaneNamespace)
}

func TestConstructServiceAccount(t *testing.T) {
sa := constructServiceAccount()
AssertEqual(t, sa.Name, serviceAccountName)
AssertEqual(t, sa.Namespace, ControlPlaneNamespace)
assert.Equal(t, sa.Name, serviceAccountName)
assert.Equal(t, sa.Namespace, ControlPlaneNamespace)
}

func TestConstructClusterRole(t *testing.T) {
cr := constructClusterRole(testOperatorClusterRole, "random-uid")
isEqual := reflect.DeepEqual(cr.Rules, testOperatorClusterRole.Rules)
if !isEqual {
t.Fatalf("got invalid data in clusterrole Rules: got -- %q want -- %q", &cr.Rules[0], &testOperatorClusterRole.Rules[0])
}
assert.Equal(t, cr.Rules, testOperatorClusterRole.Rules)
}

func TestConstructClusterRoleBinding(t *testing.T) {
crb := constructClusterRoleBinding("random-uid")
AssertEqual(t, crb.Name, clusterRoleBindingName)
AssertEqual(t, crb.RoleRef, testClusterRoleRef)
AssertEqual(t, len(crb.Subjects), 1)
AssertEqual(t, crb.Subjects[0], testClusterRoleBindingSubject[0])
assert.Equal(t, crb.Name, clusterRoleBindingName)
assert.Equal(t, crb.RoleRef, testClusterRoleRef)
assert.Len(t, crb.Subjects, 1)
assert.Equal(t, crb.Subjects[0], testClusterRoleBindingSubject[0])
}

func TestConstructConfigMap(t *testing.T) {
data := "this is the data."
cm := constructConfigMap(data)
AssertEqual(t, cm.Data["kubeslice-cleanup.sh"], data)
}

func AssertEqual(t *testing.T, actual interface{}, expected interface{}) {
t.Helper()
if actual != expected {
t.Log("expected --", expected, "actual --", actual)
t.Fail()
}
}

func AssertNoError(t *testing.T, err error) {
t.Helper()
if err != nil {
t.Errorf("Expected No Error but got %s, Stack:\n%s", err, string(debug.Stack()))
}
assert.Equal(t, cm.Data["kubeslice-cleanup.sh"], data)
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func TestReconcilerHandleExternalDependency(t *testing.T) {
client.StatusMock.On("Update",
mock.IsType(ctx),
mock.IsType(&hubv1alpha1.Cluster{}),
mock.IsType([]k8sclient.UpdateOption(nil)),
mock.IsType([]k8sclient.SubResourceUpdateOption(nil)),
).Return(nil)
client.On("List",
mock.IsType(ctx),
Expand Down Expand Up @@ -295,7 +295,7 @@ func TestReconcilerToFailWhileCallingCreateDeregisterJob(t *testing.T) {
client.StatusMock.On("Update",
mock.IsType(ctx),
mock.IsType(&hubv1alpha1.Cluster{}),
mock.IsType([]k8sclient.UpdateOption(nil)),
mock.IsType([]k8sclient.SubResourceUpdateOption(nil)),
).Return(errors.New("error updating status of deregistration on the controller"))
client.On("Create",
mock.IsType(ctx),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ var (
testWorkerNamespace = "kubeslice-system"
)

var k8sClient k8sclient.Client

var testVPNKeyRotationObject = &hubv1alpha1.VpnKeyRotation{
ObjectMeta: metav1.ObjectMeta{
Name: testVPNKeyRotationName,
Expand Down
Loading
Loading