//go:build e2e // +build e2e package test import ( "fmt" "strings" "testing" "time" "github.com/kelseyhightower/envconfig" "github.com/stretchr/testify/suite" ) const ( hostPathVolumeType = "hostPath" localVolumeType = "local" ) type PodTestSuite struct { suite.Suite config testConfig kustomizeDir string } func (p *PodTestSuite) SetupSuite() { err := envconfig.Process("test", &p.config) if err != nil { panic(err) } p.T().Logf("using test config: %+v", p.config) p.TearDownSuite() //kind load docker-image "$image" cmds := []string{ fmt.Sprintf("kind create cluster --config=%s --wait=120s", testdataFile("kind-cluster.yaml")), fmt.Sprintf("kind load docker-image %s", p.config.IMAGE), } for _, cmd := range cmds { _, err = runCmd( p.T(), cmd, "", p.config.envs(), nil, ) if err != nil { p.FailNow("", "failed to create the cluster or load image", err) } } } func (p *PodTestSuite) TearDownSuite() { err := deleteCluster( p.T(), p.config.envs(), ) if err != nil { p.Failf("", "failed to delete the cluster: %v", err) } } func (p *PodTestSuite) TearDownTest() { err := deleteKustomizeDeployment( p.T(), p.kustomizeDir, p.config.envs(), ) if err != nil { p.Failf("", "failed to delete the deployment: %v", err) } } func TestPVCTestSuite(t *testing.T) { suite.Run(t, new(PodTestSuite)) } func (p *PodTestSuite) TestPodWithHostPathVolume() { p.kustomizeDir = "pod" runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } func (p *PodTestSuite) TestPodWithLocalVolume() { p.kustomizeDir = "pod-with-local-volume" runTest(p, []string{p.config.IMAGE}, "ready", localVolumeType) } func (p *PodTestSuite) TestPodWithLocalVolumeDefault() { p.kustomizeDir = "pod-with-default-local-volume" runTest(p, []string{p.config.IMAGE}, "ready", localVolumeType) } func (p *PodTestSuite) TestPodWithNodeAffinity() { p.kustomizeDir = "pod-with-node-affinity" runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } func (p *PodTestSuite) TestPodWithRWOPVolume() { p.kustomizeDir = "pod-with-rwop-volume" runTest(p, []string{p.config.IMAGE}, "ready", localVolumeType) } func (p *PodTestSuite) TestPodWithSecurityContext() { p.kustomizeDir = "pod-with-security-context" kustomizeDir := testdataFile(p.kustomizeDir) runTest(p, []string{p.config.IMAGE}, "podscheduled", hostPathVolumeType) cmd := fmt.Sprintf(`kubectl get pod -l %s=%s -o=jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].reason}'`, LabelKey, LabelValue) t := time.Tick(5 * time.Second) loop: for { select { case <-t: c := createCmd(p.T(), cmd, kustomizeDir, p.config.envs(), nil) output, err := c.CombinedOutput() if err != nil { p.T().Logf("%s: %v", c.String(), err) } if string(output) == "PodCompleted" { break loop } case <-time.After(60 * time.Second): p.FailNow("", "pod Ready condition reason should be PodCompleted") break } } } func (p *PodTestSuite) TestPodWithSubpath() { p.kustomizeDir = "pod-with-subpath" runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } func (p *PodTestSuite) TestPodWithMultipleStorageClasses() { p.kustomizeDir = "multiple-storage-classes" runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } func (p *PodTestSuite) TestPodWithCustomPathPatternStorageClasses() { p.kustomizeDir = "custom-path-pattern" runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } func runTest(p *PodTestSuite, images []string, waitCondition, volumeType string) { kustomizeDir := testdataFile(p.kustomizeDir) var cmds []string for _, image := range images { if len(image) > 0 { cmds = append(cmds, fmt.Sprintf("kustomize edit set image %s", image)) } } cmds = append( cmds, fmt.Sprintf("kustomize edit add label %s:%s -f", LabelKey, LabelValue), "kustomize build | kubectl apply -f -", fmt.Sprintf("kubectl wait pod -l %s=%s --for condition=%s --timeout=120s", LabelKey, LabelValue, waitCondition), ) for _, cmd := range cmds { _, err := runCmd( p.T(), cmd, kustomizeDir, p.config.envs(), nil, ) if err != nil { p.FailNow("", "failed to run command", cmd, err) break } } typeCheckCmd := fmt.Sprintf("kubectl get pv $(%s) -o jsonpath='{.spec.%s}'", "kubectl get pv -o jsonpath='{.items[0].metadata.name}'", volumeType) c := createCmd(p.T(), typeCheckCmd, kustomizeDir, p.config.envs(), nil) typeCheckOutput, err := c.CombinedOutput() if err != nil { p.FailNow("", "failed to check volume type: %v", err) } if len(typeCheckOutput) == 0 || !strings.Contains(string(typeCheckOutput), "path") { p.FailNow("volume Type not correct") } }