Repository: kubernetes-sigs/security-profiles-operator
Pull request #875 (2022-03-31 12:30:21)

test: add e2e tests for Flatcar Linux
Signed-off-by: Cosmin Cojocar <gcojocar@adobe.com>

<!--  Thanks for sending a pull request!  Here are some tips for you:

- If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
- Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
- If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
- If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

#### What type of PR is this?

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind design

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

#### What this PR does / why we need it:

#### Which issue(s) this PR fixes:

<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.

Fixes #

or

None
-->

#### Does this PR have test?

<!--
If tests aren't applicable just write N/A.
-->

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?

<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

For more information on release notes see: https://git.k8s.io/community/contributors/guide/release-notes.md
-->

```release-note
Add E2E tests for cluster running on Flatcar Linux
```


k8s-ci-robot: @ccojocar: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
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/875#" title="Author self-approved">ccojocar</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **jhrozek** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @jhrozek` 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/main/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":["jhrozek"]} -->
saschagrunert: /ok-to-test
k8s-ci-robot: @ccojocar: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-security-profiles-operator-verify | de57b9f230fc5882fb67cd96ab727c174eeb36b1 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/875/pull-security-profiles-operator-verify/1509904826178211840) | true | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=875). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Accojocar). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/security-profiles-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
ccojocar: @saschagrunert @janetkuo @JAORMX The base e2e tests passed, please could you have a look over my changes?

I am trying to enable the eBPF profile recording in a different pull request. Thanks  
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/875#" title="Author self-approved">ccojocar</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please ask for approval from **jaormx** after the PR has been reviewed.

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/main/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":["jaormx"]} -->
ccojocar: @saschagrunert @JAORMX The e2e tests passed now with containerd. 
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/875#" title="Author self-approved">ccojocar</a>*, *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/875#pullrequestreview-931287535" title="Approved">JAORMX</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/main/OWNERS)~~ [JAORMX]

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":[]} -->

Patch:
diff --git a/Makefile b/Makefile
index 4ace74a9e..0ba8eb641 100644
--- a/Makefile
+++ b/Makefile
@@ -257,6 +257,10 @@ vagrant-up-fedora: ## Boot the Vagrant Fedora based test VM
 vagrant-up-ubuntu: ## Boot the Vagrant Ubuntu based test VM
 	$(call vagrant-up,ubuntu)
 
+.PHONY: vagrant-up-flatcar
+vagrant-up-flatcar: ## Boot the Vagrant Flatcar based test VM
+	$(call vagrant-up,flatcar)
+
 $(BUILD_DIR)/mdtoc: $(BUILD_DIR)
 	$(call go-build,./vendor/sigs.k8s.io/mdtoc)
 
diff --git a/api/seccompprofile/v1beta1/seccompprofile_types.go b/api/seccompprofile/v1beta1/seccompprofile_types.go
index 87697c5cc..89177688d 100644
--- a/api/seccompprofile/v1beta1/seccompprofile_types.go
+++ b/api/seccompprofile/v1beta1/seccompprofile_types.go
@@ -144,11 +144,16 @@ func (sp *SeccompProfile) SetImplementationStatus() {
 	sp.Status.LocalhostProfile = strings.TrimPrefix(profilePath, config.KubeletSeccompRootPath+"/")
 }
 
-func (sp *SeccompProfile) GetProfilePath() string {
+func (sp *SeccompProfile) GetProfileFile() string {
 	pfile := sp.GetName()
 	if !strings.HasSuffix(pfile, extJSON) {
 		pfile = sp.GetName() + extJSON
 	}
+	return pfile
+}
+
+func (sp *SeccompProfile) GetProfilePath() string {
+	pfile := sp.GetProfileFile()
 	return path.Join(
 		config.ProfilesRootPath,
 		filepath.Base(sp.GetNamespace()),
@@ -156,6 +161,15 @@ func (sp *SeccompProfile) GetProfilePath() string {
 	)
 }
 
+func (sp *SeccompProfile) GetProfileOperatorPath() string {
+	pfile := sp.GetProfileFile()
+	return path.Join(
+		config.OperatorRoot,
+		filepath.Base(sp.GetNamespace()),
+		filepath.Base(pfile),
+	)
+}
+
 // +kubebuilder:object:root=true
 
 // SeccompProfileList contains a list of SeccompProfile.
diff --git a/hack/ci/Vagrantfile-flatcar b/hack/ci/Vagrantfile-flatcar
new file mode 100644
index 000000000..f228af4bf
--- /dev/null
+++ b/hack/ci/Vagrantfile-flatcar
@@ -0,0 +1,127 @@
+#-*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure("2") do |config|
+  config.vm.box = "flatcar-stable"
+  config.vm.box_url = "https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vagrant.json"
+  memory = 8192
+  cpus = 4 
+
+  config.vm.provider :virtualbox do |v|
+     v.customize [
+      "modifyvm", :id,
+      "--memory", memory,
+      "--paravirtprovider", "default",
+      "--cpus", cpus 
+    ]
+    v.check_guest_additions = false
+    v.functional_vboxsf = false
+  end
+
+  config.vm.provider :libvirt do |v|
+    v.memory = memory
+    v.cpus = cpus
+  end
+
+  config.ssh.username = 'core'
+  config.ssh.insert_key = true
+  config.ssh.forward_agent = true
+
+  config.vm.synced_folder ".", "/vagrant", type: "rsync"
+
+  config.vm.provision "install-dependencies", type: "shell", run: "once" do |sh|
+    sh.inline = <<~SHELL
+      set -euxo pipefail
+
+      # Disable docker
+      systemctl disable --now docker.service
+
+      # Configure the kernel dependencies
+      modprobe overlay
+      modprobe br_netfilter
+
+      # Enable containerd
+      cat <<EOF | tee /etc/modules-load.d/containerd.conf
+      overlay
+      br_netfilter
+      EOF
+      systemctl enable --now containerd
+      systemctl restart containerd.service
+
+      # Import the test image of security profiles operator 
+      ctr -n=k8s.io image import /vagrant/image.tar
+      crictl --runtime-endpoint="unix:///run/containerd/containerd.sock" images
+
+      # Install Go
+      GO_VERSION=1.18
+      mkdir /opt/go
+      curl -sSfL -o- https://golang.org/dl/go$GO_VERSION.linux-amd64.tar.gz | tar xfz - -C /opt
+
+      # Configure the kernel modules
+      cat <<EOF | tee /etc/modules-load.d/k8s.conf
+      overlay
+      br_netfilter
+      EOF
+
+      # Setup Networking 
+      cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
+      net.bridge.bridge-nf-call-iptables  = 1
+      net.ipv4.ip_forward                 = 1
+      net.bridge.bridge-nf-call-ip6tables = 1
+      EOF
+
+      sysctl --system
+
+      # Install k8s components
+      CNI_VERSION="v1.0.1"
+      RELEASE_VERSION="v0.4.0"
+      DOWNLOAD_DIR=/opt/bin
+      RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
+
+      mkdir -p $DOWNLOAD_DIR
+      mkdir -p /opt/cni/bin
+      mkdir -p /etc/systemd/system/kubelet.service.d
+
+      # Install tools
+      curl -sSL -o $DOWNLOAD_DIR/jq "https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64"
+      chmod +x $DOWNLOAD_DIR/jq
+      curl -sSL -o $DOWNLOAD_DIR/flatcar_developer_container.bin.bz2 "https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_developer_container.bin.bz2"
+      bzcat $DOWNLOAD_DIR/flatcar_developer_container.bin.bz2 > $DOWNLOAD_DIR/flatcar_developer_container.bin
+
+      curl -sSL "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-amd64-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz
+      curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubelet/lib/systemd/system/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | tee /etc/systemd/system/kubelet.service
+      curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
+      curl -sSL --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/amd64/{kubeadm,kubelet,kubectl}
+
+      chmod +x {kubeadm,kubelet,kubectl}
+      mv {kubeadm,kubelet,kubectl} $DOWNLOAD_DIR/
+
+      # Disable kernel print rate limiting for syslog messaging
+      sysctl -w kernel.printk_ratelimit=0
+      sysctl -w kernel.printk_ratelimit_burst=0
+
+      systemctl enable --now kubelet
+      systemctl status kubelet
+
+      # Setup cluster
+      IP=`ip route get 1.2.3.4 | cut -d ' ' -f7 | tr -d '[:space:]'`
+      NODENAME=$(hostname -s)
+      swapoff -a
+      sysctl -w net.ipv4.ip_forward=1
+      kubeadm init --config /vagrant/hack/ci/kubeadm-config-flatcar.yaml --node-name $NODENAME
+
+      # Setup kubectl
+      mkdir -p $HOME/.kube
+      cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
+      chown -R core:core $HOME/.kube
+      export KUBECONFIG=/etc/kubernetes/admin.conf
+
+      # Configure cluster
+      kubectl taint nodes --all node-role.kubernetes.io/master-
+
+      # Install CNI
+      kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml
+      kubectl apply -f /vagrant/hack/ci/flatcar-cni-plugin.yaml
+    SHELL
+  end
+end
diff --git a/hack/ci/env-flatcar.sh b/hack/ci/env-flatcar.sh
new file mode 100755
index 000000000..85c4a6124
--- /dev/null
+++ b/hack/ci/env-flatcar.sh
@@ -0,0 +1,24 @@
+# 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.
+
+# Setup the Go environment variables
+export PATH="/opt/go/bin:$PATH"
+export GOPATH="/opt/go"
+export GOBIN="$GOPATH/bin"
+
+# Add the binaries to the path
+export PATH="/opt/bin:$PATH"
+
+# Added for faster debugging with lower verbosity
+alias k=kubectl
diff --git a/hack/ci/flatcar-cni-plugin.yaml b/hack/ci/flatcar-cni-plugin.yaml
new file mode 100644
index 000000000..cbc1ff47d
--- /dev/null
+++ b/hack/ci/flatcar-cni-plugin.yaml
@@ -0,0 +1,16 @@
+# Source: https://docs.projectcalico.org/manifests/custom-resources.yaml
+apiVersion: operator.tigera.io/v1
+kind: Installation
+metadata:
+  name: default
+spec:
+  # Configures Calico networking.
+  calicoNetwork:
+    # Note: The ipPools section cannot be modified post-install.
+    ipPools:
+    - blockSize: 26
+      cidr: 192.168.0.0/16
+      encapsulation: VXLANCrossSubnet
+      natOutgoing: Enabled
+      nodeSelector: all()
+  flexVolumePath: /opt/libexec/kubernetes/kubelet-plugins/volume/exec/
diff --git a/hack/ci/kubeadm-config-flatcar.yaml b/hack/ci/kubeadm-config-flatcar.yaml
new file mode 100644
index 000000000..3fa401267
--- /dev/null
+++ b/hack/ci/kubeadm-config-flatcar.yaml
@@ -0,0 +1,14 @@
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: InitConfiguration
+nodeRegistration:
+  kubeletExtraArgs:
+    volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
+  criSocket: "unix:///run/containerd/containerd.sock"
+---
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: ClusterConfiguration
+networking:
+  podSubnet: 192.168.0.0/16
+controllerManager:
+  extraArgs:
+    flex-volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
diff --git a/hack/ci/run-flatcar.sh b/hack/ci/run-flatcar.sh
new file mode 100755
index 000000000..ba6fa1863
--- /dev/null
+++ b/hack/ci/run-flatcar.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# 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.
+
+set -euo pipefail
+
+exec vagrant ssh -- sudo "bash -c 'cd /vagrant && . hack/ci/env-flatcar.sh && $*'"


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 003e7d223..e4d7f046a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -124,3 +124,33 @@ jobs:
           $RUN kubectl get nodes -o wide
       - name: Run E2E tests
         run: $RUN hack/ci/e2e-ubuntu.sh
+
+  e2e-flatcar:
+    needs: image
+
+    # runs-on not set to macos-11 as vagrant currently not available and stable on macos BigSur
+    # https://github.com/actions/virtual-environments/issues/2999
+    runs-on: macos-10.15
+    timeout-minutes: 90
+    env:
+      RUN: ./hack/ci/run-flatcar.sh
+    steps:
+      - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
+      - uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed # v2.1.7
+        with:
+          path: |
+            ~/.vagrant.d/boxes
+          key: e2e-flatcar-${{ hashFiles('hack/ci/Vagrantfile-flatcar') }}
+          restore-keys: e2e-flatcar-
+      - uses: actions/download-artifact@3be87be14a055c47b01d3bd88f8fe02320a9bb60 # v2.0.10
+        with:
+          name: image
+          path: .
+      - name: Boot Virtual Machine
+        run: make vagrant-up-flatcar
+      - name: Show environment information
+        run: |
+          $RUN kubectl wait --for=condition=ready --timeout=600s node localhost
+          $RUN kubectl get nodes -o wide
+      - name: Run E2E tests
+        run: $RUN hack/ci/e2e-flatcar-dev-container.sh
diff --git a/hack/ci/e2e-flatcar-dev-container.sh b/hack/ci/e2e-flatcar-dev-container.sh
new file mode 100755
index 000000000..22842c27e
--- /dev/null
+++ b/hack/ci/e2e-flatcar-dev-container.sh
@@ -0,0 +1,21 @@
+# 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.
+
+set -ue
+
+dev() {
+  systemd-nspawn -q -i /opt/bin/flatcar_developer_container.bin --bind=/:/hostfs ${@}
+}
+
+dev --chdir=/hostfs/vagrant -- /hostfs/vagrant/hack/ci/e2e-flatcar.sh
diff --git a/hack/ci/e2e-flatcar.sh b/hack/ci/e2e-flatcar.sh
new file mode 100755
index 000000000..98b627206
--- /dev/null
+++ b/hack/ci/e2e-flatcar.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# 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.
+
+set -euo pipefail
+
+export E2E_CLUSTER_TYPE="vanilla"
+export E2E_SPOD_CONFIG="test/flatcar-spod-config.yaml"
+export E2E_TEST_SECCOMP=true
+export E2E_TEST_SELINUX=false
+export E2E_TEST_LOG_ENRICHER=false
+export E2E_TEST_BPF_RECORDER=false
+export E2E_TEST_PROFILE_RECORDING=false
+
+export HOSTFS_DEV_MOUNT_PATH="/hostfs"
+export NODE_ROOTFS_PREFIX=$HOSTFS_DEV_MOUNT_PATH
+
+# Setup the Go environment variables
+export PATH="$HOSTFS_DEV_MOUNT_PATH/opt/go/bin:$PATH"
+export GOPATH="$HOSTFS_DEV_MOUNT_PATH/opt/go"
+export GOBIN="$GOPATH/bin"
+
+# Add the binaries to the path
+export PATH="$HOSTFS_DEV_MOUNT_PATH/opt/bin:$PATH"
+
+# Added for faster debugging with lower verbosity
+export KUBECONFIG=$HOSTFS_DEV_MOUNT_PATH/etc/kubernetes/admin.conf
+alias k=kubectl
+
+make test-e2e
diff --git a/test/e2e_test.go b/test/e2e_test.go
index 4fd02fe47..079a16aae 100644
--- a/test/e2e_test.go
+++ b/test/e2e_test.go
@@ -270,6 +270,13 @@ func (e *e2e) deployOperator(manifest string) {
 	e.logf("Deploying operator")
 	e.kubectl("create", "-f", manifest)
 
+	// Update the default SPOD configuration
+	if e.spodConfig != "" {
+		e.logf("Updating SPOD config")
+		// Apply this server-side to avoid conflicts with the default configuration
+		e.kubectl("apply", "--server-side", "-f", e.spodConfig)
+	}
+
 	// Wait for the operator to be ready
 	e.logf("Waiting for operator to be ready")
 	// Wait for deployment
diff --git a/test/flatcar-spod-config.yaml b/test/flatcar-spod-config.yaml
new file mode 100644
index 000000000..99b4756be
--- /dev/null
+++ b/test/flatcar-spod-config.yaml
@@ -0,0 +1,23 @@
+apiVersion: security-profiles-operator.x-k8s.io/v1alpha1
+kind: SecurityProfilesOperatorDaemon
+metadata:
+  labels:
+    app: security-profiles-operator
+  name: spod
+  namespace: security-profiles-operator
+spec:
+  hostProcVolumePath: /proc
+  selinuxOptions:
+    allowedSystemProfiles:
+    - container
+  selinuxTypeTag: unconfined_t
+  tolerations:
+  - effect: NoSchedule
+    key: node-role.kubernetes.io/master
+    operator: Exists
+  - effect: NoSchedule
+    key: node-role.kubernetes.io/control-plane
+    operator: Exists
+  - effect: NoExecute
+    key: node.kubernetes.io/not-ready
+    operator: Exists
diff --git a/test/suite_test.go b/test/suite_test.go
index 4c06eedce..e7a165b7d 100644
--- a/test/suite_test.go
+++ b/test/suite_test.go
@@ -48,12 +48,14 @@ var (
 	clusterType                     = os.Getenv("E2E_CLUSTER_TYPE")
 	envSkipBuildImages              = os.Getenv("E2E_SKIP_BUILD_IMAGES")
 	envTestImage                    = os.Getenv("E2E_SPO_IMAGE")
+	spodConfig                      = os.Getenv("E2E_SPOD_CONFIG")
 	envSelinuxTestsEnabled          = os.Getenv("E2E_TEST_SELINUX")
 	envLogEnricherTestsEnabled      = os.Getenv("E2E_TEST_LOG_ENRICHER")
 	envSeccompTestsEnabled          = os.Getenv("E2E_TEST_SECCOMP")
 	envProfileRecordingTestsEnabled = os.Getenv("E2E_TEST_PROFILE_RECORDING")
 	envBpfRecorderTestsEnabled      = os.Getenv("E2E_TEST_BPF_RECORDER")
 	containerRuntime                = os.Getenv("CONTAINER_RUNTIME")
+	nodeRootfsPrefix                = os.Getenv("NODE_ROOTFS_PREFIX")
 )
 
 const (
@@ -62,12 +64,19 @@ const (
 	clusterTypeOpenShift = "openshift"
 )
 
+const (
+	containerRuntimeDocker = "docker"
+)
+
 type e2e struct {
 	suite.Suite
+	containerRuntime     string
 	kubectlPath          string
 	testImage            string
 	selinuxdImage        string
 	pullPolicy           string
+	spodConfig           string
+	nodeRootfsPrefix     string
 	selinuxEnabled       bool
 	logEnricherEnabled   bool
 	testSeccomp          bool
@@ -140,6 +149,9 @@ func TestSuite(t *testing.T) {
 				logger:               klogr.New(),
 				pullPolicy:           "Never",
 				testImage:            testImage,
+				spodConfig:           spodConfig,
+				containerRuntime:     containerRuntime,
+				nodeRootfsPrefix:     nodeRootfsPrefix,
 				selinuxEnabled:       selinuxEnabled,
 				logEnricherEnabled:   logEnricherEnabled,
 				testSeccomp:          testSeccomp,
@@ -165,6 +177,9 @@ func TestSuite(t *testing.T) {
 				// image registry and not on the nodes.
 				pullPolicy:           "Always",
 				testImage:            testImage,
+				spodConfig:           spodConfig,
+				containerRuntime:     containerRuntime,
+				nodeRootfsPrefix:     nodeRootfsPrefix,
 				selinuxEnabled:       selinuxEnabled,
 				logEnricherEnabled:   logEnricherEnabled,
 				testSeccomp:          testSeccomp,
@@ -185,6 +200,9 @@ func TestSuite(t *testing.T) {
 				logger:               klogr.New(),
 				pullPolicy:           "Never",
 				testImage:            testImage,
+				spodConfig:           spodConfig,
+				containerRuntime:     containerRuntime,
+				nodeRootfsPrefix:     nodeRootfsPrefix,
 				selinuxEnabled:       selinuxEnabled,
 				logEnricherEnabled:   logEnricherEnabled,
 				testSeccomp:          testSeccomp,
@@ -397,7 +415,10 @@ func (e *vanilla) SetupSuite() {
 }
 
 func (e *vanilla) SetupTest() {
-	e.run(containerRuntime, "pull", e.selinuxdImage)
+	e.logf("Setting up test")
+	if e.selinuxEnabled {
+		e.run(containerRuntime, "pull", e.selinuxdImage)
+	}
 }
 
 func (e *vanilla) TearDownTest() {
diff --git a/test/tc_base_profiles_test.go b/test/tc_base_profiles_test.go
index 2721c181a..158973f3e 100644
--- a/test/tc_base_profiles_test.go
+++ b/test/tc_base_profiles_test.go
@@ -29,7 +29,7 @@ func (e *e2e) testCaseBaseProfile([]string) {
 	baseProfilePath := "examples/baseprofile-runc.yaml"
 	baseProfileName := "runc-v1.0.0"
 
-	if clusterType == clusterTypeVanilla {
+	if clusterType == clusterTypeVanilla && e.containerRuntime != containerRuntimeDocker {
 		baseProfilePath = "examples/baseprofile-crun.yaml"
 		baseProfileName = "crun-v0.20.1"
 	}
diff --git a/test/tc_delete_profiles_test.go b/test/tc_delete_profiles_test.go
index ee0936bae..11a9dc2b2 100644
--- a/test/tc_delete_profiles_test.go
+++ b/test/tc_delete_profiles_test.go
@@ -18,6 +18,7 @@ package e2e_test
 
 import (
 	"fmt"
+	"path"
 	"time"
 
 	v1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
@@ -102,7 +103,7 @@ spec:
 
 	namespace := e.getCurrentContextNamespace(defaultNamespace)
 	sp := e.getSeccompProfile(deleteProfileName, namespace)
-	path := sp.GetProfilePath()
+	profileOperatorPath := path.Join(e.nodeRootfsPrefix, sp.GetProfileOperatorPath())
 
 	e.logf("Waiting for profile to be reconciled")
 	e.waitFor("condition=ready", "seccompprofile", deleteProfileName)
@@ -110,13 +111,13 @@ spec:
 	e.logf("Verifying profile exists")
 	time.Sleep(time.Second)
 	for _, node := range nodes {
-		e.execNode(node, "test", "-f", path)
+		e.execNode(node, "test", "-f", profileOperatorPath)
 	}
 	e.logf("Verifying profile deleted")
 	e.kubectl("delete", "seccompprofile", deleteProfileName)
 	time.Sleep(time.Second)
 	for _, node := range nodes {
-		e.execNode(node, "test", "!", "-f", path)
+		e.execNode(node, "test", "!", "-f", profileOperatorPath)
 	}
 
 	// Check linking pods prevent deletion
@@ -172,8 +173,8 @@ spec:
 			e.Equal(nodeStatuses.Items[i].Status, secprofnodestatusv1alpha1.ProfileStateTerminating)
 			// On each node, there should still be the profile on the disk
 			nodeWithPodName := nodeStatuses.Items[i].NodeName
-			path := sp.GetProfilePath()
-			e.execNode(nodeWithPodName, "test", "-f", path)
+			profileOperatorPath := path.Join(e.nodeRootfsPrefix, sp.GetProfileOperatorPath())
+			e.execNode(nodeWithPodName, "test", "-f", profileOperatorPath)
 		}
 
 		isDeleted := make(chan bool)