Repository: kubernetes-sigs/security-profiles-operator
Pull request #313 (2021-02-17 12:29:46)

Move images used for e2e testing away from dockerhub
#### What type of PR is this?

/kind bug

#### What this PR does / why we need it:

This moves our test images away from using dockerhub to using less restrictive
registries.

The hello-world image was replaced with one that we host in the
security-profile-operator's quay.io org called test-hello-world (note the
"test-" prefix which indicates that the image is used for testing).

The busybox image was replaced with a fedora-minimal image (coming from
Fedora's registry).


#### Does this PR have test?

N/A.

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?

```release-note
NONE
```

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/313#" title="Author self-approved">JAORMX</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **pjbgf** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @pjbgf` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/security-profiles-operator/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["pjbgf"]} -->
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/313#" title="Author self-approved">JAORMX</a>*, *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/313#pullrequestreview-592144429" title="LGTM">saschagrunert</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubernetes-sigs/security-profiles-operator/blob/master/OWNERS)~~ [saschagrunert]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
JAORMX: /hold

let's replace the nginx image too
k8s-ci-robot: New changes are detected. LGTM label has been removed.
JAORMX: /hold cancel

Patch:
diff --git a/Makefile b/Makefile
index 687eb6eb6..982dea8e7 100644
--- a/Makefile
+++ b/Makefile
@@ -226,7 +226,7 @@ test-unit: $(BUILD_DIR) ## Run the unit tests
 
 .PHONY: test-e2e
 test-e2e: ## Run the end-to-end tests
-	$(GO) test -parallel 1 -timeout 40m -count=1 ./test/... -v
+	$(GO) test -parallel 1 -timeout 80m -count=1 ./test/... -v
 
 # Generate CRD manifests
 manifests: $(CONTROLLER_GEN)


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 8877eff6c..2667d5894 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -47,7 +47,7 @@ jobs:
   e2e:
     needs: image
     runs-on: macos-10.15
-    timeout-minutes: 40
+    timeout-minutes: 80
     env:
       RUN: ./hack/ci/run.sh
     steps:
diff --git a/hack/ci/e2e.sh b/hack/ci/e2e.sh
index 1a705c039..929469cbe 100755
--- a/hack/ci/e2e.sh
+++ b/hack/ci/e2e.sh
@@ -22,5 +22,6 @@ export E2E_TEST_SELINUX=true
 # No need to test them here.
 export E2E_TEST_SECCOMP=false
 export E2E_TEST_PROFILE_BINDING=false
+export E2E_TEST_PROFILE_RECORDING=true
 
 make test-e2e
diff --git a/test/e2e_test.go b/test/e2e_test.go
index 89f20fdb8..2c80e8fce 100644
--- a/test/e2e_test.go
+++ b/test/e2e_test.go
@@ -31,6 +31,7 @@ const (
 	certmanager       = "https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml"
 	manifest          = "deploy/operator.yaml"
 	namespaceManifest = "deploy/namespace-operator.yaml"
+	webhookManifest   = "deploy/webhook.yaml"
 	testNamespace     = "test-ns"
 	defaultNamespace  = "default"
 	// NOTE(jaosorior): We should be able to decrease this once we
@@ -92,12 +93,23 @@ func (e *e2e) TestSecurityProfilesOperator() {
 		})
 	}
 
+	if e.testProfileBinding || e.testProfileRecording {
+		e.deployWebhook(webhookManifest)
+		defer e.run("git", "checkout", webhookManifest)
+	}
+
 	// TODO(jaosorior): Re-introduce this to the namespaced tests once we
 	// fix the issue with the certs.
 	e.Run("cluster-wide: Seccomp: Verify profile binding", func() {
 		e.testCaseProfileBinding(nodes)
 	})
 
+	e.Run("cluster-wide: Seccomp: Verify profile recording", func() {
+		e.testCaseProfileRecording(nodes)
+	})
+
+	e.cleanupWebhook(webhookManifest)
+
 	// Clean up cluster-wide deployment to prepare for namespace deployment
 	e.cleanupOperator(manifest)
 
@@ -178,6 +190,36 @@ func (e *e2e) cleanupOperator(manifest string) {
 	e.kubectl("delete", "-f", manifest)
 }
 
+func (e *e2e) deployWebhook(manifest string) {
+	// Deploy prerequisites
+	e.logf("Deploying cert-manager")
+	e.kubectl("apply", "-f", certmanager)
+	e.waitFor(
+		"condition=ready",
+		"--namespace", "cert-manager",
+		"pod", "-l", "app.kubernetes.io/instance=cert-manager",
+	)
+	e.run(
+		"sed", "-i", fmt.Sprintf("s;image: .*gcr.io/.*;image: %s;g", e.testImage),
+		manifest,
+	)
+	e.run(
+		"sed", "-i",
+		fmt.Sprintf("s;imagePullPolicy: Always;imagePullPolicy: %s;g", e.pullPolicy),
+		manifest,
+	)
+	e.logf("Deploying webhook")
+	e.kubectl("create", "-f", manifest)
+	e.waitInOperatorNSFor("condition=ready", "pod", "-l", "name=security-profiles-operator-webhook")
+	e.waitInOperatorNSFor("condition=ready", "certificate", "webhook-cert")
+}
+
+func (e *e2e) cleanupWebhook(manifest string) {
+	e.logf("Cleaning up webhook")
+	e.kubectl("delete", "-f", manifest)
+	e.kubectl("delete", "-f", certmanager)
+}
+
 func (e *e2e) getWorkerNodes() []string {
 	e.logf("Getting worker nodes")
 	nodesOutput := e.kubectl(
diff --git a/test/suite_test.go b/test/suite_test.go
index 991f78692..ae3303a3a 100644
--- a/test/suite_test.go
+++ b/test/suite_test.go
@@ -44,13 +44,14 @@ const (
 )
 
 var (
-	clusterType                   = os.Getenv("E2E_CLUSTER_TYPE")
-	envSkipBuildImages            = os.Getenv("E2E_SKIP_BUILD_IMAGES")
-	envTestImage                  = os.Getenv("E2E_SPO_IMAGE")
-	envSelinuxTestsEnabled        = os.Getenv("E2E_TEST_SELINUX")
-	envSeccompTestsEnabled        = os.Getenv("E2E_TEST_SECCOMP")
-	envProfileBindingTestsEnabled = os.Getenv("E2E_TEST_PROFILE_BINDING")
-	containerRuntime              = os.Getenv("CONTAINER_RUNTIME")
+	clusterType                     = os.Getenv("E2E_CLUSTER_TYPE")
+	envSkipBuildImages              = os.Getenv("E2E_SKIP_BUILD_IMAGES")
+	envTestImage                    = os.Getenv("E2E_SPO_IMAGE")
+	envSelinuxTestsEnabled          = os.Getenv("E2E_TEST_SELINUX")
+	envSeccompTestsEnabled          = os.Getenv("E2E_TEST_SECCOMP")
+	envProfileBindingTestsEnabled   = os.Getenv("E2E_TEST_PROFILE_BINDING")
+	envProfileRecordingTestsEnabled = os.Getenv("E2E_TEST_PROFILE_RECORDING")
+	containerRuntime                = os.Getenv("CONTAINER_RUNTIME")
 )
 
 const (
@@ -61,15 +62,16 @@ const (
 
 type e2e struct {
 	suite.Suite
-	kubectlPath        string
-	testImage          string
-	selinuxdImage      string
-	pullPolicy         string
-	selinuxEnabled     bool
-	testSeccomp        bool
-	testProfileBinding bool
-	logger             logr.Logger
-	execNode           func(node string, args ...string) string
+	kubectlPath          string
+	testImage            string
+	selinuxdImage        string
+	pullPolicy           string
+	selinuxEnabled       bool
+	testSeccomp          bool
+	testProfileBinding   bool
+	testProfileRecording bool
+	logger               logr.Logger
+	execNode             func(node string, args ...string) string
 }
 
 type kinde2e struct {
@@ -109,6 +111,10 @@ func TestSuite(t *testing.T) {
 	if err != nil {
 		testProfileBinding = true
 	}
+	testProfileRecording, err := strconv.ParseBool(envProfileRecordingTestsEnabled)
+	if err != nil {
+		testProfileRecording = false
+	}
 	selinuxdImage := "quay.io/jaosorior/selinuxd"
 	switch {
 	case clusterType == "" || strings.EqualFold(clusterType, clusterTypeKind):
@@ -117,13 +123,14 @@ func TestSuite(t *testing.T) {
 		}
 		suite.Run(t, &kinde2e{
 			e2e{
-				logger:             klogr.New(),
-				pullPolicy:         "Never",
-				testImage:          testImage,
-				selinuxEnabled:     selinuxEnabled,
-				testSeccomp:        testSeccomp,
-				testProfileBinding: testProfileBinding,
-				selinuxdImage:      selinuxdImage,
+				logger:               klogr.New(),
+				pullPolicy:           "Never",
+				testImage:            testImage,
+				selinuxEnabled:       selinuxEnabled,
+				testSeccomp:          testSeccomp,
+				testProfileBinding:   testProfileBinding,
+				testProfileRecording: testProfileRecording,
+				selinuxdImage:        selinuxdImage,
 			},
 			"", "",
 		})
@@ -141,12 +148,13 @@ func TestSuite(t *testing.T) {
 				logger: klogr.New(),
 				// Need to pull the image as it'll be uploaded to the cluster OCP
 				// image registry and not on the nodes.
-				pullPolicy:         "Always",
-				testImage:          testImage,
-				selinuxEnabled:     selinuxEnabled,
-				testSeccomp:        testSeccomp,
-				testProfileBinding: testProfileBinding,
-				selinuxdImage:      selinuxdImage,
+				pullPolicy:           "Always",
+				testImage:            testImage,
+				selinuxEnabled:       selinuxEnabled,
+				testSeccomp:          testSeccomp,
+				testProfileBinding:   testProfileBinding,
+				testProfileRecording: testProfileRecording,
+				selinuxdImage:        selinuxdImage,
 			},
 			skipBuildImages,
 			skipPushImages,
@@ -158,13 +166,14 @@ func TestSuite(t *testing.T) {
 		selinuxdImage = "quay.io/jaosorior/selinuxd-fedora"
 		suite.Run(t, &vanilla{
 			e2e{
-				logger:             klogr.New(),
-				pullPolicy:         "Never",
-				testImage:          testImage,
-				selinuxEnabled:     selinuxEnabled,
-				testSeccomp:        testSeccomp,
-				testProfileBinding: testProfileBinding,
-				selinuxdImage:      selinuxdImage,
+				logger:               klogr.New(),
+				pullPolicy:           "Never",
+				testImage:            testImage,
+				selinuxEnabled:       selinuxEnabled,
+				testSeccomp:          testSeccomp,
+				testProfileBinding:   testProfileBinding,
+				testProfileRecording: testProfileRecording,
+				selinuxdImage:        selinuxdImage,
 			},
 		})
 	default:
@@ -453,3 +462,9 @@ func (e *e2e) profileBindingTestCase() {
 		e.T().Skip("Skipping Profile-Binding-related test")
 	}
 }
+
+func (e *e2e) profileRecordingTestCase() {
+	if !e.testProfileRecording {
+		e.T().Skip("Skipping Profile-Recording-related test")
+	}
+}
diff --git a/test/tc_base_profiles_test.go b/test/tc_base_profiles_test.go
index cdec2840a..7ef8dfebd 100644
--- a/test/tc_base_profiles_test.go
+++ b/test/tc_base_profiles_test.go
@@ -56,7 +56,7 @@ metadata:
   name: hello
 spec:
   containers:
-  - image: hello-world:linux
+  - image: quay.io/security-profiles-operator/test-hello-world:latest
     name: hello
     resources: {}
   securityContext:
diff --git a/test/tc_delete_profiles_test.go b/test/tc_delete_profiles_test.go
index f8050e1af..5d2132273 100644
--- a/test/tc_delete_profiles_test.go
+++ b/test/tc_delete_profiles_test.go
@@ -44,7 +44,7 @@ metadata:
 spec:
   containers:
   - name: test-container
-    image: nginx:1.19.1
+    image: quay.io/security-profiles-operator/test-nginx:1.19.1
   securityContext:
     seccompProfile:
       type: Localhost
@@ -58,7 +58,7 @@ metadata:
 spec:
   containers:
   - name: test-container
-    image: nginx:1.19.1
+    image: quay.io/security-profiles-operator/test-nginx:1.19.1
     securityContext:
       seccompProfile:
         type: Localhost
@@ -72,14 +72,14 @@ metadata:
 spec:
   initContainers:
   - name: init-container
-    image: busybox:latest
+    image: registry.fedoraproject.org/fedora-minimal:latest
     securityContext:
       seccompProfile:
         type: Localhost
         localhostProfile: operator/%s/example-profiles/delete-me.json
   containers:
   - name: test-container
-    image: nginx:1.19.1
+    image: quay.io/security-profiles-operator/test-nginx:1.19.1
 `
 		deletePodSecurityContextInAnnotation = `
 apiVersion: v1
@@ -91,7 +91,7 @@ metadata:
 spec:
   containers:
   - name: test-container
-    image: nginx:1.19.1
+    image: quay.io/security-profiles-operator/test-nginx:1.19.1
 `
 		deletePodName = "test-pod"
 	)
diff --git a/test/tc_profilebindings_test.go b/test/tc_profilebindings_test.go
index 6de36e201..3d3b2d3e9 100644
--- a/test/tc_profilebindings_test.go
+++ b/test/tc_profilebindings_test.go
@@ -35,7 +35,7 @@ spec:
   profileRef:
     kind: SeccompProfile
     name: profile-allow-unsafe
-  image: hello-world:linux
+  image: quay.io/security-profiles-operator/test-hello-world:latest
 `
 	const testPod = `
 apiVersion: v1
@@ -44,16 +44,11 @@ metadata:
   name: hello
 spec:
   containers:
-  - image: hello-world:linux
+  - image: quay.io/security-profiles-operator/test-hello-world:latest
     name: hello
     resources: {}
   restartPolicy: Never
 `
-	const manifest = "deploy/webhook.yaml"
-
-	e.deployWebhook(manifest)
-	defer e.run("git", "checkout", manifest)
-	defer e.cleanupWebhook(manifest)
 
 	e.kubectl("create", "-f", exampleProfilePath)
 	defer e.kubectl("delete", "-f", exampleProfilePath)
@@ -122,33 +117,3 @@ spec:
 
 	e.Contains(output, "in-use-by-active-pods")
 }
-
-func (e *e2e) deployWebhook(manifest string) {
-	// Deploy prerequisites
-	e.logf("Deploying cert-manager")
-	e.kubectl("apply", "-f", certmanager)
-	e.waitFor(
-		"condition=ready",
-		"--namespace", "cert-manager",
-		"pod", "-l", "app.kubernetes.io/instance=cert-manager",
-	)
-	e.run(
-		"sed", "-i", fmt.Sprintf("s;image: .*gcr.io/.*;image: %s;g", e.testImage),
-		manifest,
-	)
-	e.run(
-		"sed", "-i",
-		fmt.Sprintf("s;imagePullPolicy: Always;imagePullPolicy: %s;g", e.pullPolicy),
-		manifest,
-	)
-	e.logf("Deploying webhook")
-	e.kubectl("create", "-f", manifest)
-	e.waitInOperatorNSFor("condition=ready", "pod", "-l", "name=security-profiles-operator-webhook")
-	e.waitInOperatorNSFor("condition=ready", "certificate", "webhook-cert")
-}
-
-func (e *e2e) cleanupWebhook(manifest string) {
-	e.logf("Cleaning up webhook")
-	e.kubectl("delete", "-f", manifest)
-	e.kubectl("delete", "-f", certmanager)
-}
diff --git a/test/tc_profilerecordings_test.go b/test/tc_profilerecordings_test.go
new file mode 100644
index 000000000..57cd0e57f
--- /dev/null
+++ b/test/tc_profilerecordings_test.go
@@ -0,0 +1,63 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+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 e2e_test
+
+import (
+	"io/ioutil"
+	"os"
+)
+
+func (e *e2e) testCaseProfileRecording([]string) {
+	e.profileRecordingTestCase()
+
+	const exampleRecordingPath = "examples/profilerecording.yaml"
+
+	e.logf("Creating recording")
+	e.kubectl("create", "-f", exampleRecordingPath)
+	defer e.kubectl("delete", "-f", exampleRecordingPath)
+
+	e.logf("Creating test pod")
+	const testPod = `
+apiVersion: v1
+kind: Pod
+metadata:
+  name: recording
+  labels:
+    app: alpine
+spec:
+  containers:
+  - image: quay.io/security-profiles-operator/test-nginx:1.19.1
+    name: recording
+    resources: {}
+  restartPolicy: Never
+`
+	testPodFile, err := ioutil.TempFile(os.TempDir(), "recording-pod*.yaml")
+	e.Nil(err)
+	defer os.Remove(testPodFile.Name())
+	_, err = testPodFile.Write([]byte(testPod))
+	e.Nil(err)
+	err = testPodFile.Close()
+	e.Nil(err)
+	e.kubectl("create", "-f", testPodFile.Name())
+
+	e.logf("Waiting for test pod to be initialized")
+	e.waitFor("condition=ready", "pod", "recording")
+	e.kubectl("delete", "pod", "recording")
+
+	profile := e.kubectl("get", "sp", "test-recording", "-o", "yaml")
+	e.Contains(profile, "mkdir")
+}