Skip to content

Commit 8e4e802

Browse files
authored
Merge pull request #271 from rojkov/e2e-ginkgo
e2e test: reimplement with K8s testing framework
2 parents 0900b31 + e1ccdf5 commit 8e4e802

13 files changed

+647
-256
lines changed

Makefile

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
GO := go
22
GOFMT := gofmt
33
GOCYCLO := gocyclo
4+
KUBECTL ?= kubectl
5+
KIND ?= kind
6+
PODMAN ?= podman
47

58
BUILDTAGS ?= ""
69
BUILDER ?= "docker"
710

11+
WEBHOOK_IMAGE_FILE = intel-fpga-admissionwebhook-devel.tgz
12+
813
pkgs = $(shell $(GO) list ./... | grep -v vendor | grep -v e2e)
914
cmds = $(shell ls cmd)
15+
e2e_tmp_dir := $(shell mktemp -u -t e2e-tests.XXXXXXXXXX)
1016

1117
all: build
1218

@@ -38,10 +44,17 @@ else
3844
exit $$rc
3945
endif
4046

41-
test-e2e:
47+
test-with-kind:
4248
@build/docker/build-image.sh intel/intel-fpga-admissionwebhook buildah
43-
@podman tag localhost/intel/intel-fpga-admissionwebhook:devel docker.io/intel/intel-fpga-admissionwebhook:devel
44-
@$(GO) test -v ./test/e2e/...
49+
@$(PODMAN) tag localhost/intel/intel-fpga-admissionwebhook:devel docker.io/intel/intel-fpga-admissionwebhook:devel
50+
@mkdir -p $(e2e_tmp_dir)
51+
@$(PODMAN) save "docker.io/intel/intel-fpga-admissionwebhook:devel" -o $(e2e_tmp_dir)/$(WEBHOOK_IMAGE_FILE)
52+
@$(KIND) create cluster --name "intel-device-plugins" --kubeconfig $(e2e_tmp_dir)/kubeconfig --image "kindest/node:v1.17.0"
53+
@$(KIND) load image-archive --name "intel-device-plugins" $(e2e_tmp_dir)/$(WEBHOOK_IMAGE_FILE)
54+
@$(GO) test -v ./test/e2e -args -kubeconfig $(e2e_tmp_dir)/kubeconfig -kubectl-path $(KUBECTL) -ginkgo.focus "Webhook" || rc=1; \
55+
$(KIND) delete cluster --name "intel-device-plugins"; \
56+
rm -rf $(e2e_tmp_dir); \
57+
exit $$rc
4558

4659
lint:
4760
@rc=0 ; for f in $$(find -name \*.go | grep -v \.\/vendor) ; do golint -set_exit_status $$f || rc=1 ; done ; exit $$rc

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,44 @@ For information on how to develop a new plugin using the framework, see the
126126
[Developers Guide](DEVEL.md) and the code in the
127127
[device plugins pkg directory](pkg/deviceplugin).
128128

129+
## Running E2E tests
130+
131+
Currently the E2E tests require having a Kubernetes cluster already configured
132+
on the nodes with the hardware required by the device plugins. Also all the
133+
container images with the executables under test must be available in the
134+
cluster. Given these two conditions are satisfied one can run the tests with
135+
136+
```bash
137+
$ go test -v ./test/e2e/...
138+
```
139+
140+
In case you want to run only certain tests, e.g. QAT ones, then run
141+
142+
```bash
143+
$ go test -v ./test/e2e/... -args -ginkgo.focus "QAT"
144+
```
145+
146+
If you need to specify paths to your custom `kubeconfig` containing
147+
embedded authentication info then add the `-kubeconfig` argument:
148+
149+
```bash
150+
$ go test -v ./test/e2e/... -args -kubeconfig /path/to/kubeconfig
151+
```
152+
153+
The full list of available options can be obtained with
154+
155+
```bash
156+
$ go test ./test/e2e/... -args -help
157+
```
158+
159+
Also it is possible to run the tests which don't depend on hardware
160+
without a pre-configured Kubernetes cluster. Just make sure you have
161+
[Kind](https://kind.sigs.k8s.io/) installed on your host and run
162+
163+
```
164+
$ make test-with-kind
165+
```
166+
129167
## Supported Kubernetes versions
130168

131169
Releases are made under the github [releases area](releases). Supported releases and

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ require (
77
github.com/go-ini/ini v1.46.0
88
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
99
github.com/google/gousb v0.0.0-20190812193832-18f4c1d8a750
10+
github.com/onsi/ginkgo v1.10.1
11+
github.com/onsi/gomega v1.7.0
1012
github.com/pkg/errors v0.8.1
1113
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
1214
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456
@@ -15,6 +17,8 @@ require (
1517
k8s.io/api v0.17.0
1618
k8s.io/apimachinery v0.17.0
1719
k8s.io/client-go v0.17.0
20+
k8s.io/component-base v0.17.0
21+
k8s.io/klog v1.0.0
1822
k8s.io/kubelet v0.0.0
1923
k8s.io/kubernetes v1.17.0
2024
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f

go.sum

Lines changed: 46 additions & 2 deletions
Large diffs are not rendered by default.

scripts/webhook-create-signed-cert.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

3-
which cfssl > /dev/null 2>&1 || (echo "Please install 'cfssl' (e.g. with 'go get -u github.com/cloudflare/cfssl/cmd/cfssl')"; exit 1)
4-
which jq > /dev/null 2>&1 || (echo "Please install 'jq'"; exit 1)
3+
which cfssl > /dev/null 2>&1 || { echo "Please install 'cfssl' (e.g. with 'go get -u github.com/cloudflare/cfssl/cmd/cfssl')"; exit 1; }
4+
which jq > /dev/null 2>&1 || { echo "Please install 'jq'"; exit 1; }
55

66
while [[ $# -gt 0 ]]; do
77
case ${1} in
@@ -30,6 +30,8 @@ done
3030
[ -z ${namespace} ] && namespace="default"
3131
[ -z ${kubectl} ] && kubectl="kubectl"
3232

33+
which ${kubectl} > /dev/null 2>&1 || { echo "ERROR: ${kubectl} not found"; exit 1; }
34+
3335
csrname="${service}.${namespace}"
3436
tmpdir=$(mktemp -d)
3537

scripts/webhook-deploy.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ done
5757
[ -z ${mode} ] && mode="preprogrammed"
5858
[ -z ${namespace} ] && namespace="default"
5959

60+
which ${kubectl} > /dev/null 2>&1 || { echo "ERROR: ${kubectl} not found"; exit 1; }
61+
6062
# clean up any previously created deployment
6163
${kubectl} delete MutatingWebhookConfiguration "fpga-mutator-webhook-cfg" 2>/dev/null || true
6264
${kubectl} --namespace ${namespace} delete service ${service} 2>/dev/null || true

test/e2e/deviceplugins_suite_test.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2020 Intel Corporation. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package e2e_test
16+
17+
import (
18+
"flag"
19+
"os"
20+
"testing"
21+
22+
"github.com/onsi/ginkgo"
23+
"github.com/onsi/gomega"
24+
25+
_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/fpgaadmissionwebhook"
26+
_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/gpu"
27+
_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/qat"
28+
v1 "k8s.io/api/core/v1"
29+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+
"k8s.io/component-base/logs"
31+
"k8s.io/component-base/version"
32+
"k8s.io/klog"
33+
"k8s.io/kubernetes/test/e2e/framework"
34+
"k8s.io/kubernetes/test/e2e/framework/config"
35+
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
36+
)
37+
38+
func init() {
39+
ginkgo.SynchronizedBeforeSuite(setupFirstNode, func(data []byte) {})
40+
}
41+
42+
func setupFirstNode() []byte {
43+
c, err := framework.LoadClientset()
44+
if err != nil {
45+
framework.Failf("Error loading client: %v", err)
46+
}
47+
48+
// Delete any namespaces except those created by the system. This ensures no
49+
// lingering resources are left over from a previous test run.
50+
deleted, err := framework.DeleteNamespaces(c, nil, /* deleteFilter */
51+
[]string{
52+
metav1.NamespaceSystem,
53+
metav1.NamespaceDefault,
54+
metav1.NamespacePublic,
55+
v1.NamespaceNodeLease,
56+
})
57+
if err != nil {
58+
framework.Failf("Error deleting orphaned namespaces: %v", err)
59+
}
60+
framework.Logf("Waiting for deletion of the following namespaces: %v", deleted)
61+
if err := framework.WaitForNamespacesDeleted(c, deleted, framework.NamespaceCleanupTimeout); err != nil {
62+
framework.Failf("Failed to delete orphaned namespaces %v: %v", deleted, err)
63+
}
64+
65+
framework.ExpectNoError(framework.WaitForAllNodesSchedulable(c, framework.TestContext.NodeSchedulableTimeout))
66+
67+
// Ensure all pods are running and ready before starting tests (otherwise,
68+
// cluster infrastructure pods that are being pulled or started can block
69+
// test pods from running, and tests that ensure all pods are running and
70+
// ready will fail).
71+
if err := e2epod.WaitForPodsRunningReady(c, metav1.NamespaceSystem, int32(framework.TestContext.MinStartupPods),
72+
int32(framework.TestContext.AllowedNotReadyNodes), framework.TestContext.SystemPodsStartupTimeout,
73+
map[string]string{}); err != nil {
74+
framework.DumpAllNamespaceInfo(c, metav1.NamespaceSystem)
75+
framework.LogFailedContainers(c, metav1.NamespaceSystem, framework.Logf)
76+
framework.Failf("Error waiting for all pods to be running and ready: %v", err)
77+
}
78+
79+
// Log the version of the server and this client.
80+
framework.Logf("e2e test version: %s", version.Get().GitVersion)
81+
serverVersion, err := c.DiscoveryClient.ServerVersion()
82+
if err != nil {
83+
framework.Logf("Unexpected server error retrieving version: %v", err)
84+
}
85+
if serverVersion != nil {
86+
framework.Logf("kube-apiserver version: %s", serverVersion.GitVersion)
87+
}
88+
89+
return []byte{}
90+
}
91+
92+
func TestDevicePlugins(t *testing.T) {
93+
gomega.RegisterFailHandler(ginkgo.Fail)
94+
ginkgo.RunSpecs(t, "E2E Device Plugins Suite")
95+
}
96+
97+
func TestMain(m *testing.M) {
98+
klog.SetOutput(ginkgo.GinkgoWriter)
99+
100+
logs.InitLogs()
101+
config.CopyFlags(config.Flags, flag.CommandLine)
102+
framework.RegisterCommonFlags(flag.CommandLine)
103+
framework.RegisterClusterFlags(flag.CommandLine)
104+
flag.Parse()
105+
106+
// Register framework flags, then handle flags.
107+
framework.AfterReadingAllFlags(&framework.TestContext)
108+
109+
// Now run the test suite.
110+
os.Exit(m.Run())
111+
}

0 commit comments

Comments
 (0)