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

test: add envtest for redis standalone #748

Merged
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
39 changes: 20 additions & 19 deletions .github/workflows/operator-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ env:
DockerImagName: docker.io/opstree/redis-operator
BuildDocs: true
AppVersion: "v0.15.2"
DOCKERFILE_PATH: '**/Dockerfile'
DOCKERFILE_PATH: "**/Dockerfile"

jobs:
gofmt:
Expand Down Expand Up @@ -54,6 +54,8 @@ jobs:
uses: actions/setup-go@v4
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install integration test dependencies
run: make integration-test-setup
- name: Run Go Tests with coverage
run: go test ./... -coverprofile=coverage.txt -covermode=atomic
- name: Upload coverage to Codecov
Expand All @@ -62,7 +64,7 @@ jobs:
file: ./coverage.txt
fail_ci_if_error: false
verbose: true

code_quality_golang_ci_lint:
needs: [gofmt, govet]
runs-on: ubuntu-latest
Expand All @@ -72,16 +74,16 @@ jobs:
uses: actions/setup-go@v4
with:
go-version: ${{ env.GOLANG_VERSION }}

- name: Download Go modules
run: go mod download

- name: Check disk space
run: df -h

- name: List Go module cache
run: ls -la $(go env GOPATH)/pkg/mod

- name: Run GolangCI-Lint
uses: golangci/golangci-lint-action@v3
with:
Expand All @@ -105,7 +107,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
arch: ['amd64', 'arm64']
arch: ["amd64", "arm64"]
steps:
- name: Checkout Code
uses: actions/checkout@v2
Expand All @@ -125,19 +127,19 @@ jobs:
needs: [container_quality_dockerfile_lint]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build multi-arch image
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/arm64,linux/amd64
push: false
tags: ${{ env.DockerImagName }}:latest
- name: Build multi-arch image
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/arm64,linux/amd64
push: false
tags: ${{ env.DockerImagName }}:latest

gosec_scan:
needs: [build_go_binary]
Expand All @@ -152,4 +154,3 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

GOSEC_OUTPUT: "junit-xml:/github/workspace/gosec-results.xml"

6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,8 @@ e2e-kind-setup:

.PHONY: e2e-test
e2e-test: e2e-kind-setup install-kuttl
$(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml
$(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml

.PHONY: integration-test-setup
integration-test-setup:
./hack/integrationSetup.sh
147 changes: 147 additions & 0 deletions controllers/redis_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package controllers

import (
"context"
"fmt"
"time"

appsv1 "k8s.io/api/apps/v1"

redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"

"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

const (
ns = "default"

timeout = time.Second * 5
interval = time.Millisecond * 250
)

var _ = Describe("Redis standalone test", func() {
var (
redisCR redisv1beta2.Redis
redisCRName string
// Used to create unique name for each test
testCount int
)

JustBeforeEach(func() {
redisCR = redisv1beta2.Redis{
TypeMeta: metav1.TypeMeta{
APIVersion: "redisv1beta2/apiVersion",
Kind: "Redis",
},
ObjectMeta: metav1.ObjectMeta{
Name: redisCRName,
Namespace: ns,
},
}
Expect(k8sClient.Create(context.TODO(), &redisCR)).Should(Succeed())
testCount++
})

BeforeEach(func() {
redisCRName = fmt.Sprintf("redis-%d", testCount)
})

Context("When creating a redis standalone CR", func() {
It("should create a statefulset", func() {
var sts *appsv1.StatefulSet
Eventually(func() error {
sts = &appsv1.StatefulSet{}
return k8sClient.Get(context.TODO(), types.NamespacedName{
Name: redisCRName,
Namespace: ns,
}, sts)
}, timeout, interval).Should(BeNil())

Expect(sts.Labels).To(Equal(map[string]string{
"app": redisCRName,
"redis_setup_type": "standalone",
"role": "standalone",
}))

Expect(*sts.Spec.Replicas).To(BeEquivalentTo(1))
Expect(sts.Spec.ServiceName).To(Equal(redisCRName + "-headless"))
})

It("should create a service", func() {
var svc *corev1.Service
Eventually(func() error {
svc = &corev1.Service{}
return k8sClient.Get(context.TODO(), types.NamespacedName{
Name: redisCR.Name,
Namespace: ns,
}, svc)
}, timeout, interval).Should(BeNil())

Expect(svc.Labels).To(Equal(map[string]string{
"app": redisCRName,
"redis_setup_type": "standalone",
"role": "standalone",
}))
})

It("should create a headless service", func() {
var svc *corev1.Service
Eventually(func() error {
svc = &corev1.Service{}
return k8sClient.Get(context.TODO(), types.NamespacedName{
Name: redisCR.Name + "-headless",
Namespace: ns,
}, svc)
}, timeout, interval).Should(BeNil())

Expect(svc.Labels).To(Equal(map[string]string{
"app": redisCRName,
"redis_setup_type": "standalone",
"role": "standalone",
}))
})

It("should create additional service", func() {
var svc *corev1.Service
Eventually(func() error {
svc = &corev1.Service{}
return k8sClient.Get(context.TODO(), types.NamespacedName{
Name: redisCR.Name + "-additional",
Namespace: ns,
}, svc)
}, timeout, interval).Should(BeNil())

Expect(svc.Labels).To(Equal(map[string]string{
"app": redisCRName,
"redis_setup_type": "standalone",
"role": "standalone",
}))
})

Context("then deleting the redis standalone CR", func() {
It("should delete the statefulset", func() {
redisCR := &redisv1beta2.Redis{
ObjectMeta: metav1.ObjectMeta{
Name: redisCRName,
Namespace: ns,
},
}
Expect(k8sClient.Delete(context.TODO(), redisCR)).To(BeNil())

Eventually(func() bool {
sts := &appsv1.StatefulSet{}
err := k8sClient.Get(context.TODO(), types.NamespacedName{
Name: redisCRName,
Namespace: ns,
}, sts)
return errors.IsNotFound(err)
}, timeout, interval).Should(BeTrue())
})
})
})
})
76 changes: 50 additions & 26 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,63 +18,87 @@ package controllers

import (
"path/filepath"
"testing"
"time"

// redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1"
redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2"
. "github.com/onsi/ginkgo"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"

// "k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
// +kubebuilder:scaffold:imports
)

// These tests use Ginkgo (BDD-style Go testing framework). Refer to
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.

// var cfg *rest.Config
var k8sClient client.Client
var testEnv *envtest.Environment

// func TestAPIs(t *testing.T) {
// RegisterFailHandler(Fail)
func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail)

// RunSpecsWithDefaultAndCustomReporters(t,
// "Controller Suite",
// []Reporter{printer.NewlineReporter{}})
// }
RunSpecs(t, "Controller suite")
}

var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))

By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
ErrorIfCRDPathMissing: true,
CRDInstallOptions: envtest.CRDInstallOptions{
MaxTime: 60 * time.Second,
},
}

cfg, err := testEnv.Start()
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
Expect(err).ToNot(HaveOccurred())
Expect(cfg).ToNot(BeNil())

err = redisv1beta2.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
// err = redisv1beta1.AddToScheme(scheme.Scheme)
// Expect(err).ToNot(HaveOccurred())

err = redisv1beta2.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
Expect(err).ToNot(HaveOccurred())

// +kubebuilder:scaffold:scheme

k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())

}, 60)
Expect(err).ToNot(HaveOccurred())
Expect(k8sClient).ToNot(BeNil())

k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme.Scheme,
})
Expect(err).ToNot(HaveOccurred())

k8sClient, err := kubernetes.NewForConfig(cfg)
Expect(err).ToNot(HaveOccurred())

err = (&RedisReconciler{
Client: k8sManager.GetClient(),
K8sClient: k8sClient,
Scheme: k8sManager.GetScheme(),
}).SetupWithManager(k8sManager)
Expect(err).ToNot(HaveOccurred())

go func() {
defer GinkgoRecover()
err = k8sManager.Start(ctrl.SetupSignalHandler())
Expect(err).ToNot(HaveOccurred(), "failed to run manager")
gexec.KillAndWait(4 * time.Second)

// Teardown the test environment once controller is fnished.
err := testEnv.Stop()
Expect(err).ToNot(HaveOccurred())
}()

var _ = AfterSuite(func() {
By("tearing down the test environment")
err := testEnv.Stop()
Expect(err).NotTo(HaveOccurred())
})
Loading
Loading