mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00

But omitting +listType=set because it introduces errors. Signed-off-by: Maya Rashish <mrashish@redhat.com>
171 lines
5.2 KiB
Go
171 lines
5.2 KiB
Go
package tests
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"reflect"
|
|
"regexp"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/onsi/ginkgo"
|
|
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
cdiv1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1beta1"
|
|
"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) cdiv1.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 cdiv1.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
|
|
}
|