Skip to content

Commit

Permalink
[wip] add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
stuggi committed Oct 5, 2023
1 parent bb5f504 commit 437dd74
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 3 deletions.
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ golangci-lint:
$(LOCALBIN)/golangci-lint run --fix

.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out
test: manifests generate gowork fmt vet envtest ginkgo ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) -v debug --bin-dir $(LOCALBIN) use $(ENVTEST_K8S_VERSION) -p path)" \
OPERATOR_TEMPLATES="$(PWD)/templates" \
$(GINKGO) --trace --cover --coverpkg=../../pkg/openstack,../../pkg/openstackclient,../../pkg/util,../../controllers,../../apis/client/v1beta1,../../apis/core/v1beta1 --coverprofile cover.out --covermode=atomic ${PROC_CMD} $(GINKGO_ARGS) ./tests/... ./apis/client/...

##@ Build

Expand Down Expand Up @@ -202,6 +204,7 @@ $(LOCALBIN):
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
GINKGO ?= $(LOCALBIN)/ginkgo

## Tool Versions
KUSTOMIZE_VERSION ?= v3.8.7
Expand All @@ -223,6 +226,11 @@ envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest

.PHONY: ginkgo
ginkgo: $(GINKGO) ## Download ginkgo locally if necessary.
$(GINKGO): $(LOCALBIN)
test -s $(LOCALBIN)/ginkgo || GOBIN=$(LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo

.PHONY: bundle
bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files.
operator-sdk generate kustomize manifests -q
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/openstack-k8s-operators/keystone-operator/api v0.1.1-0.20231003172225-508b207a4ce1
github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.0.0-20231005100414-e942c6825d0a
github.com/openstack-k8s-operators/lib-common/modules/common v0.1.1-0.20231004075925-7a2ccbf0ea0e
github.com/openstack-k8s-operators/lib-common/modules/test v0.1.2-0.20231001084618-12369665b166
github.com/openstack-k8s-operators/manila-operator/api v0.1.1-0.20231002132501-83fc02d0bb5c
github.com/openstack-k8s-operators/mariadb-operator/api v0.1.1-0.20230928152002-65395552e015
github.com/openstack-k8s-operators/neutron-operator/api v0.1.1-0.20231003055522-7458d6e1df2e
Expand All @@ -44,9 +45,11 @@ require (
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 // indirect
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 // indirect
github.com/metal3-io/baremetal-operator/apis v0.3.1 // indirect
github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.2.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/tools v0.13.0 // indirect
sigs.k8s.io/gateway-api v0.6.0 // indirect
)
Expand All @@ -68,7 +71,7 @@ require (
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/google/uuid v1.3.1
github.com/gophercloud/gophercloud v1.7.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 h1:VzM3TYHDgqPkettiP6I6q2jOeQFL4nrJM+UcAc4f6Fs=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down Expand Up @@ -161,6 +162,7 @@ github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.2023100
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20231002090319-8c85a5806ffb/go.mod h1:LOXXvTQCwhOBNd+0FTlgllpa3wqlkI6Vf3Q5QVRVPlw=
github.com/openstack-k8s-operators/lib-common/modules/storage v0.1.1-0.20231002090319-8c85a5806ffb h1:Wpq8CssgUVhmQrreNXpxOfi1Em36344jaEaTV8aVk6I=
github.com/openstack-k8s-operators/lib-common/modules/storage v0.1.1-0.20231002090319-8c85a5806ffb/go.mod h1:qkK/2JzIGOzoctfe0sbL+mSelrEmErAND4vuj1qTU/A=
github.com/openstack-k8s-operators/lib-common/modules/test v0.1.2-0.20231001084618-12369665b166 h1:lh3WHM+3DcPlXK4I3QWHmvV+cPCy+dmiMdfImHF/Nqc=
github.com/openstack-k8s-operators/manila-operator/api v0.1.1-0.20231002132501-83fc02d0bb5c h1:/gI3W8XZCzXCMb8fAT6Q8eCILHCxtrc8TqJW24N7LAo=
github.com/openstack-k8s-operators/manila-operator/api v0.1.1-0.20231002132501-83fc02d0bb5c/go.mod h1:rJkTThV08Be6hnxw7IbDSrIPQ/FqQ2Uzhe9NdppoP4E=
github.com/openstack-k8s-operators/mariadb-operator/api v0.1.1-0.20230928152002-65395552e015 h1:1G37nuB9C8QPp7tScEpwbR7eQj+2e6l089MNzj5cChk=
Expand Down
52 changes: 52 additions & 0 deletions tests/functional/base_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package functional_test

import (
. "github.com/onsi/gomega"

"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

openstackclientv1 "github.com/openstack-k8s-operators/openstack-operator/apis/client/v1beta1"
)

func GetDefaultOpenStackClientSpec() map[string]interface{} {
return map[string]interface{}{}
}

func CreateOpenStackClient(name types.NamespacedName, spec map[string]interface{}) client.Object {

raw := map[string]interface{}{
"apiVersion": "client.openstack.org/v1beta1",
"kind": "OpenStackClient",
"metadata": map[string]interface{}{
"name": name.Name,
"namespace": name.Namespace,
},
"spec": spec,
}
return th.CreateUnstructured(raw)
}

func GetOpenStackClient(name types.NamespacedName) *openstackclientv1.OpenStackClient {
instance := &openstackclientv1.OpenStackClient{}
Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(ctx, name, instance)).Should(Succeed())
}, timeout, interval).Should(Succeed())
return instance
}
71 changes: 71 additions & 0 deletions tests/functional/openstackclient_webhook_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package functional_test

import (
"os"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/types"

openstackclientv1 "github.com/openstack-k8s-operators/openstack-operator/apis/client/v1beta1"
)

var _ = Describe("OpenStackClient Webhook", func() {

var openstackclientName types.NamespacedName

BeforeEach(func() {

openstackclientName = types.NamespacedName{
Name: "foo",
Namespace: namespace,
}

err := os.Setenv("OPERATOR_TEMPLATES", "../../templates")
Expect(err).NotTo(HaveOccurred())
})

When("A OpenStackClient instance is created without container images", func() {
BeforeEach(func() {
DeferCleanup(th.DeleteInstance, CreateOpenStackClient(openstackclientName, GetDefaultOpenStackClientSpec()))
})

It("should have the defaults initialized by webhook", func() {
OpenStackClient := GetOpenStackClient(openstackclientName)
Expect(OpenStackClient.Spec.ContainerImage).Should(Equal(
openstackclientv1.OpenStackClientContainerImage,
))
})
})

When("A OpenStackClient instance is created with container images", func() {
BeforeEach(func() {
openstackclientSpec := GetDefaultOpenStackClientSpec()
openstackclientSpec["containerImage"] = "api-container-image"
DeferCleanup(th.DeleteInstance, CreateOpenStackClient(openstackclientName, openstackclientSpec))
})

It("should use the given values", func() {
OpenStackClient := GetOpenStackClient(openstackclientName)
Expect(OpenStackClient.Spec.ContainerImage).Should(Equal(
"api-container-image",
))
})
})
})
177 changes: 177 additions & 0 deletions tests/functional/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package functional_test

import (
"context"
"crypto/tls"
"fmt"
"net"
"path/filepath"
"testing"
"time"

"github.com/go-logr/logr"
"github.com/google/uuid"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"go.uber.org/zap/zapcore"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"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"

routev1 "github.com/openshift/api/route/v1"
test "github.com/openstack-k8s-operators/lib-common/modules/test"
openstackclientv1 "github.com/openstack-k8s-operators/openstack-operator/apis/client/v1beta1"

client_ctrl "github.com/openstack-k8s-operators/openstack-operator/controllers/client"

common_test "github.com/openstack-k8s-operators/lib-common/modules/test/helpers"
//+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
k8sClient client.Client
testEnv *envtest.Environment
ctx context.Context
cancel context.CancelFunc
logger logr.Logger
th *common_test.TestHelper
namespace string
)

const (
timeout = time.Second * 2

SecretName = "test-osp-secret"

interval = time.Millisecond * 200
)

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

RunSpecs(t, "Controller Suite")
}

var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true), func(o *zap.Options) {
o.Development = true
o.TimeEncoder = zapcore.ISO8601TimeEncoder
}))

ctx, cancel = context.WithCancel(context.TODO())

routev1CRDs, err := test.GetOpenShiftCRDDir("route/v1", "../../go.mod")
Expect(err).ShouldNot(HaveOccurred())

By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{
filepath.Join("..", "..", "config", "crd", "bases"),
routev1CRDs,
},
ErrorIfCRDPathMissing: true,
WebhookInstallOptions: envtest.WebhookInstallOptions{
Paths: []string{filepath.Join("..", "..", "config", "webhook")},
// NOTE(gibi): if localhost is resolved to ::1 (ipv6) then starting
// the webhook fails as it try to parse the address as ipv4 and
// failing on the colons in ::1
LocalServingHost: "127.0.0.1",
},
}

// cfg is defined in this file globally.
cfg, err = testEnv.Start()
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())

err = openstackclientv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
err = routev1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

//+kubebuilder:scaffold:scheme

logger = ctrl.Log.WithName("---Test---")

k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())
th = common_test.NewTestHelper(ctx, k8sClient, timeout, interval, logger)
Expect(th).NotTo(BeNil())

// Start the controller-manager if goroutine
webhookInstallOptions := &testEnv.WebhookInstallOptions
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme.Scheme,
// NOTE(gibi): disable metrics reporting in test to allow
// parallel test execution. Otherwise each instance would like to
// bind to the same port
MetricsBindAddress: "0",
Host: webhookInstallOptions.LocalServingHost,
Port: webhookInstallOptions.LocalServingPort,
CertDir: webhookInstallOptions.LocalServingCertDir,
LeaderElection: false,
})
Expect(err).ToNot(HaveOccurred())

kclient, err := kubernetes.NewForConfig(cfg)
Expect(err).ToNot(HaveOccurred(), "failed to create kclient")

err = (&openstackclientv1.OpenStackClient{}).SetupWebhookWithManager(k8sManager)
Expect(err).NotTo(HaveOccurred())

openstackclientv1.SetupDefaults()

err = (&client_ctrl.OpenStackClientReconciler{
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
Kclient: kclient,
}).SetupWithManager(k8sManager)
Expect(err).ToNot(HaveOccurred())

go func() {
defer GinkgoRecover()
err = k8sManager.Start(ctx)
Expect(err).ToNot(HaveOccurred(), "failed to run manager")
}()

// wait for the webhook server to get ready
dialer := &net.Dialer{Timeout: 10 * time.Second}
addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort)
Eventually(func() error {
conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true})
if err != nil {
return err
}
conn.Close()
return nil
}).Should(Succeed())
})

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

var _ = BeforeEach(func() {
// NOTE(gibi): We need to create a unique namespace for each test run
// as namespaces cannot be deleted in a locally running envtest. See
// https://book.kubebuilder.io/reference/envtest.html#namespace-usage-limitation
namespace = uuid.New().String()
th.CreateNamespace(namespace)
// We still request the delete of the Namespace to properly cleanup if
// we run the test in an existing cluster.
DeferCleanup(th.DeleteNamespace, namespace)
})

0 comments on commit 437dd74

Please sign in to comment.