containerized-data-importer/tests/utils.go
Maya Rashish 9a8fc07302
Skip test 2555 if running on openshift (#1572)
* Move "isOpenshift" to utils and make public.

No functional change.

Signed-off-by: Maya Rashish <mrashish@redhat.com>

* Skip malformed too large qcow2 on openshift.

Whether this test fails depends on the qemu-img version. The way we
build and test it in this repo is fine, but external builds may fail.

Skipping only on OpenShift means we will continue testing it and
finding regressions.

Signed-off-by: Maya Rashish <mrashish@redhat.com>
2021-01-18 14:20:28 +01:00

203 lines
6.0 KiB
Go

package tests
import (
"bytes"
"context"
"fmt"
"net/http"
"os"
"os/exec"
"reflect"
"regexp"
"runtime"
"time"
sdkapi "kubevirt.io/controller-lifecycle-operator-sdk/pkg/sdk/api"
"github.com/onsi/ginkgo"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"kubevirt.io/containerized-data-importer/tests/framework"
)
const (
defaultTimeout = 270 * time.Second
testNamespacePrefix = "cdi-test-"
)
var (
versionRegex = regexp.MustCompile(`ubernetes .*v(\d+\.\d+\.\d+)`)
versionRegexServer = regexp.MustCompile(`Server Version: .*({.*})`)
versionRegexGitVersion = regexp.MustCompile(`GitVersion:"v(\d+\.\d+\.\d+)\+?\S*"`)
nodeSelectorTestValue = map[string]string{"kubernetes.io/arch": runtime.GOARCH}
tolerationsTestValue = []v1.Toleration{{Key: "test", Value: "123"}}
affinityTestValue = &v1.Affinity{}
)
// CDIFailHandler call ginkgo.Fail with printing the additional information
func CDIFailHandler(message string, callerSkip ...int) {
if len(callerSkip) > 0 {
callerSkip[0]++
}
ginkgo.Fail(message, callerSkip...)
}
//RunKubectlCommand ...
func RunKubectlCommand(f *framework.Framework, args ...string) (string, error) {
var errb bytes.Buffer
cmd := CreateKubectlCommand(f, args...)
cmd.Stderr = &errb
stdOutBytes, err := cmd.Output()
if err != nil {
if len(errb.String()) > 0 {
return errb.String(), err
}
// err will not always be nil calling kubectl, this is expected on no results for instance.
// still return the value and let the called decide what to do.
return string(stdOutBytes), err
}
return string(stdOutBytes), nil
}
// CreateKubectlCommand returns the Cmd to execute kubectl
func CreateKubectlCommand(f *framework.Framework, args ...string) *exec.Cmd {
kubeconfig := f.KubeConfig
path := f.KubectlPath
cmd := exec.Command(path, args...)
kubeconfEnv := fmt.Sprintf("KUBECONFIG=%s", kubeconfig)
cmd.Env = append(os.Environ(), kubeconfEnv)
return cmd
}
//PrintControllerLog ...
func PrintControllerLog(f *framework.Framework) {
PrintPodLog(f, f.ControllerPod.Name, f.CdiInstallNs)
}
//PrintPodLog ...
func PrintPodLog(f *framework.Framework, podName, namespace string) {
log, err := RunKubectlCommand(f, "logs", podName, "-n", namespace)
if err == nil {
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: Pod log\n%s\n", log)
} else {
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: Unable to get pod log, %s\n", err.Error())
}
}
//PanicOnError ...
func PanicOnError(err error) {
if err != nil {
panic(err)
}
}
// GetKubeVersion returns the version returned by the kubectl version command as a semver compatible string
func GetKubeVersion(f *framework.Framework) string {
// Check non json version output.
out, err := RunKubectlCommand(f, "version")
if err != nil {
return ""
}
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: Output from kubectl: %s\n", out)
matches := versionRegex.FindStringSubmatch(out)
if len(matches) > 1 {
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: kubectl version: %s\n", matches[1])
return matches[1]
}
// Didn't match, maybe its the newer version
matches = versionRegexServer.FindStringSubmatch(out)
if len(matches) > 1 {
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: kubectl version output: %s\n", matches[1])
// Would love to use json.Unmarshal, but keys aren't quoted
gitVersion := versionRegexGitVersion.FindStringSubmatch(matches[1])
if len(gitVersion) > 1 {
return gitVersion[1]
}
return ""
}
return ""
}
// TestNodePlacementValues returns a pre-defined set of node placement values for testing purposes.
// The values chosen are valid, but the pod will likely not be schedulable.
func TestNodePlacementValues(f *framework.Framework) sdkapi.NodePlacement {
nodes, _ := f.K8sClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
affinityTestValue = &v1.Affinity{
NodeAffinity: &v1.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
NodeSelectorTerms: []v1.NodeSelectorTerm{
{
MatchExpressions: []v1.NodeSelectorRequirement{
{Key: "kubernetes.io/hostname", Operator: v1.NodeSelectorOpIn, Values: []string{nodes.Items[0].Name}},
},
},
},
},
},
}
return sdkapi.NodePlacement{
NodeSelector: nodeSelectorTestValue,
Affinity: affinityTestValue,
Tolerations: tolerationsTestValue,
}
}
// PodSpecHasTestNodePlacementValues compares if the pod spec has the set of node placement values defined for testing purposes
func PodSpecHasTestNodePlacementValues(f *framework.Framework, podSpec v1.PodSpec) bool {
if !reflect.DeepEqual(podSpec.NodeSelector, nodeSelectorTestValue) {
fmt.Printf("mismatched nodeSelectors, podSpec:\n%v\nExpected:\n%v\n", podSpec.NodeSelector, nodeSelectorTestValue)
return false
}
if !reflect.DeepEqual(podSpec.Affinity, affinityTestValue) {
fmt.Printf("mismatched affinity, podSpec:\n%v\nExpected:\n%v\n", *podSpec.Affinity, affinityTestValue)
return false
}
foundMatchingTolerations := false
for _, toleration := range podSpec.Tolerations {
if toleration == tolerationsTestValue[0] {
foundMatchingTolerations = true
}
}
if foundMatchingTolerations != true {
fmt.Printf("no matching tolerations found. podSpec:\n%v\nExpected:\n%v\n", podSpec.Tolerations, tolerationsTestValue)
return false
}
return true
}
//IsOpenshift checks if we are on OpenShift platform
func IsOpenshift(client kubernetes.Interface) bool {
//OpenShift 3.X check
result := client.Discovery().RESTClient().Get().AbsPath("/oapi/v1").Do(context.TODO())
var statusCode int
result.StatusCode(&statusCode)
if result.Error() == nil {
// It is OpenShift
if statusCode == http.StatusOK {
return true
}
} else {
// Got 404 so this is not Openshift 3.X, let's check OpenShift 4
result = client.Discovery().RESTClient().Get().AbsPath("/apis/route.openshift.io").Do(context.TODO())
var statusCode int
result.StatusCode(&statusCode)
if result.Error() == nil {
// It is OpenShift
if statusCode == http.StatusOK {
return true
}
}
}
return false
}