Skip to content

Commit cf675d9

Browse files
committed
feat: Add Podman support as drop-in replacement for Docker
Signed-off-by: Pascal Zimmermann <pascal.zimmermann01@sap.com>
1 parent 0d2461f commit cf675d9

18 files changed

Lines changed: 942 additions & 141 deletions

.github/workflows/kind-cats.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
--privileged \
4040
--pid host \
4141
-v /lib/modules:/lib/modules:ro \
42-
alpine sh -c "sysctl -w fs.inotify.max_user_instances=512 && modprobe nfs && modprobe nfsd"
42+
alpine sh -c "sysctl -w fs.inotify.max_user_instances=512 && sysctl -w net.ipv4.ip_unprivileged_port_start=80 && modprobe nfs && modprobe nfsd"
4343
- name: Install dependencies
4444
if: steps.check_changes.outputs.skip != 'true'
4545
run: |

.github/workflows/kind-smoke.yaml

Lines changed: 17 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -23,114 +23,23 @@ on:
2323

2424
jobs:
2525
kind-smoke:
26-
runs-on: ubuntu-latest
26+
uses: ./.github/workflows/smoke-run.yaml
2727
permissions:
2828
id-token: write
2929
contents: read
30-
steps:
31-
- uses: actions/checkout@v6
32-
with:
33-
fetch-depth: 0
34-
- name: Check if only ignored paths changed
35-
id: check_changes
36-
run: |
37-
if [ "${{ github.event_name }}" == "pull_request" ]; then
38-
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }})
39-
RELEVANT_FILES=$(echo "$CHANGED_FILES" | grep -v -E '.*\.Dockerfile|^releases/.*/files/|^\.github/|^docs/|\.md$|^renovate\.json$' || true)
40-
if [ -z "$RELEVANT_FILES" ]; then
41-
echo "Only ignored paths were changed. Skipping workflow."
42-
echo "skip=true" >> $GITHUB_OUTPUT
43-
else
44-
echo "skip=false" >> $GITHUB_OUTPUT
45-
fi
46-
else
47-
echo "skip=false" >> $GITHUB_OUTPUT
48-
fi
49-
- name: Set kernel settings
50-
if: steps.check_changes.outputs.skip != 'true'
51-
run: |
52-
docker run --rm \
53-
--privileged \
54-
--pid host \
55-
alpine sh -c "sysctl -w fs.inotify.max_user_instances=512"
56-
- name: Install dependencies
57-
if: steps.check_changes.outputs.skip != 'true'
58-
run: |
59-
mkdir -p $HOME/.local/bin && echo "$HOME/.local/bin" >> "$GITHUB_PATH"
60-
curl -L https://kind.sigs.k8s.io/dl/v${KIND_VERSION}/kind-linux-amd64 -o $HOME/.local/bin/kind
61-
chmod +x $HOME/.local/bin/kind
62-
curl -L https://github.com/helmfile/helmfile/releases/download/v${HELMFILE_VERSION}/helmfile_${HELMFILE_VERSION}_linux_amd64.tar.gz | tar -zx
63-
mv helmfile $HOME/.local/bin/helmfile
64-
curl -L "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=${CF_CLI_VERSION}&source=github" | tar -zx
65-
mv cf8 $HOME/.local/bin/cf
66-
env:
67-
# renovate: dataSource=github-releases depName=cloudfoundry/cli
68-
CF_CLI_VERSION: "8.18.3"
69-
# renovate: dataSource=github-releases depName=kubernetes-sigs/kind
70-
KIND_VERSION: "0.32.0"
71-
# renovate: dataSource=github-releases depName=helmfile/helmfile
72-
HELMFILE_VERSION: "1.5.3"
73-
- name: Use develop versions of cf-deployment
74-
id: pre_validation
75-
if: steps.check_changes.outputs.skip != 'true' && github.event_name == 'workflow_dispatch' && github.event.inputs.fresh-validation == 'true'
76-
env:
77-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
78-
run: |
79-
pip3 install -r scripts/requirements.txt
80-
python3 scripts/sync-cf-deployment-versions.py --ref develop
81-
- name: Run make up (default)
82-
if: steps.check_changes.outputs.skip != 'true' && github.event_name == 'pull_request'
83-
run: make up
84-
- name: Run make up
85-
if: steps.check_changes.outputs.skip != 'true' && github.event_name != 'pull_request'
86-
run: make up
87-
env:
88-
INSTALL_OPTIONAL_COMPONENTS: ${{ inputs.minimal }}
89-
- name: Login
90-
if: steps.check_changes.outputs.skip != 'true'
91-
run: make login
92-
- name: Init
93-
if: steps.check_changes.outputs.skip != 'true'
94-
run: make bootstrap-complete
95-
- name: setup CF tests
96-
if: steps.check_changes.outputs.skip != 'true'
97-
uses: ./.github/actions/setup-cf-tests
98-
with:
99-
test-repo: cf-smoke-tests
100-
test-branch: main
101-
config-template: ./.github/smoke-config.tpl
102-
config-output: ./.github/smoke-config.json
103-
- name: run smoke test
104-
if: steps.check_changes.outputs.skip != 'true'
105-
env:
106-
CONFIG: "${{ github.workspace }}/.github/smoke-config.json"
107-
GINKGO_NO_COLOR: "true"
108-
run: |
109-
./cf-smoke-tests/bin/test --no-color --github-output --timeout=30m --procs=4 --json-report report.json
110-
- name: debug events
111-
if: failure()
112-
run: kubectl get events -A --sort-by='.lastTimestamp'
113-
- name: debug pods
114-
if: failure()
115-
run: |
116-
echo "===== CLOUD_CONTROLLER ====="
117-
kubectl get pod -n cf-system -l app.kubernetes.io/name=cloud-controller -o wide
118-
kubectl get pod -n cf-system -l app.kubernetes.io/name=cloud-controller -o jsonpath='{.status.containerStatuses[*].state}' | jq
119-
kubectl logs -n cf-system -l app.kubernetes.io/name=cloud-controller --all-containers=true
120-
echo "===== CC_WORKER ====="
121-
kubectl get pod -n cf-system -l app.kubernetes.io/name=cc-worker -o wide
122-
kubectl logs -n cf-system -l app.kubernetes.io/name=cc-worker
123-
echo "===== CC_UPLOADER ====="
124-
kubectl get pod -n cf-system -l app=cc-uploader -o wide
125-
kubectl logs -n cf-system -l app=cc-uploader
126-
echo "===== CC_DEPLOYMENT_UPDATER ====="
127-
kubectl get pod -n cf-system -l app.kubernetes.io/name=cc-deployment-updater -o wide
128-
kubectl logs -n cf-system -l app.kubernetes.io/name=cc-deployment-updater
129-
echo "===== CC_WORKER_CLOCK ====="
130-
kubectl get pod -n cf-system -l app.kubernetes.io/name=cc-worker-clock -o wide
131-
kubectl logs -n cf-system -l app.kubernetes.io/name=cc-worker-clock
132-
- uses: actions/upload-artifact@v7
133-
if: always()
134-
with:
135-
name: report.json
136-
path: ./cf-smoke-tests/report.json
30+
with:
31+
container-runtime: docker
32+
install-optional-components: ${{ github.event_name == 'pull_request' && 'false' || inputs.minimal != true && 'true' || 'false' }}
33+
fresh-validation: ${{ inputs.fresh-validation == true }}
34+
artifact-name: report.json
35+
36+
kind-smoke-podman:
37+
uses: ./.github/workflows/smoke-run.yaml
38+
permissions:
39+
id-token: write
40+
contents: read
41+
with:
42+
container-runtime: podman
43+
install-optional-components: ${{ github.event_name == 'pull_request' && 'false' || inputs.minimal != true && 'true' || 'false' }}
44+
fresh-validation: ${{ inputs.fresh-validation == true }}
45+
artifact-name: report-podman.json

.github/workflows/smoke-run.yaml

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
name: Smoke Run (reusable)
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
container-runtime:
7+
description: 'Container runtime to use (docker or podman)'
8+
type: string
9+
required: true
10+
install-optional-components:
11+
description: 'Whether to install optional CF components'
12+
type: string
13+
required: true
14+
artifact-name:
15+
description: 'Name of the uploaded test report artifact'
16+
type: string
17+
required: true
18+
fresh-validation:
19+
description: 'Use versions of cf-deployment from the develop branch'
20+
type: boolean
21+
required: false
22+
default: false
23+
24+
jobs:
25+
smoke-run:
26+
runs-on: ubuntu-latest
27+
permissions:
28+
id-token: write
29+
contents: read
30+
steps:
31+
- uses: actions/checkout@v6
32+
with:
33+
fetch-depth: 0
34+
- name: Check if only ignored paths changed
35+
id: check_changes
36+
run: |
37+
if [ "${{ github.event_name }}" == "pull_request" ]; then
38+
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }})
39+
RELEVANT_FILES=$(echo "$CHANGED_FILES" | grep -v -E '.*\.Dockerfile|^releases/.*/files/|^\.github/|^docs/|\.md$|^renovate\.json$' || true)
40+
if [ -z "$RELEVANT_FILES" ]; then
41+
echo "Only ignored paths were changed. Skipping workflow."
42+
echo "skip=true" >> $GITHUB_OUTPUT
43+
else
44+
echo "skip=false" >> $GITHUB_OUTPUT
45+
fi
46+
else
47+
echo "skip=false" >> $GITHUB_OUTPUT
48+
fi
49+
- name: Pin nip.io domains to localhost
50+
if: steps.check_changes.outputs.skip != 'true'
51+
run: |
52+
# nip.io is an external DNS service; CI runners sometimes can't resolve it.
53+
printf '127.0.0.1 api.127-0-0-1.nip.io\n127.0.0.1 uaa.127-0-0-1.nip.io\n127.0.0.1 login.127-0-0-1.nip.io\n127.0.0.1 apps.127-0-0-1.nip.io\n127.0.0.1 doppler.127-0-0-1.nip.io\n127.0.0.1 log-stream.127-0-0-1.nip.io\n' | sudo tee -a /etc/hosts
54+
- name: Set kernel settings
55+
if: steps.check_changes.outputs.skip != 'true'
56+
run: |
57+
sudo sysctl -w fs.inotify.max_user_instances=512
58+
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80
59+
- name: Set kernel settings (Podman extras)
60+
if: steps.check_changes.outputs.skip != 'true' && inputs.container-runtime == 'podman'
61+
run: |
62+
# Mount BPF filesystem on the host (needed by kindnet on some kernels)
63+
sudo mount bpffs /sys/fs/bpf -t bpf -o nosuid,nodev,noexec,relatime || true
64+
- name: Install podman-compose
65+
if: steps.check_changes.outputs.skip != 'true' && inputs.container-runtime == 'podman'
66+
run: |
67+
sudo apt-get update -qq
68+
sudo apt-get install -y podman-compose
69+
# Ensure podman-compose is used instead of the docker-compose plugin shim
70+
sudo ln -sf /usr/bin/podman-compose /usr/local/bin/podman-compose
71+
- name: Install dependencies
72+
if: steps.check_changes.outputs.skip != 'true'
73+
run: |
74+
mkdir -p $HOME/.local/bin && echo "$HOME/.local/bin" >> "$GITHUB_PATH"
75+
curl -L https://kind.sigs.k8s.io/dl/v${KIND_VERSION}/kind-linux-amd64 -o $HOME/.local/bin/kind
76+
chmod +x $HOME/.local/bin/kind
77+
curl -L https://github.com/helmfile/helmfile/releases/download/v${HELMFILE_VERSION}/helmfile_${HELMFILE_VERSION}_linux_amd64.tar.gz | tar -zx
78+
mv helmfile $HOME/.local/bin/helmfile
79+
curl -L "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=${CF_CLI_VERSION}&source=github" | tar -zx
80+
mv cf8 $HOME/.local/bin/cf
81+
env:
82+
# renovate: dataSource=github-releases depName=cloudfoundry/cli
83+
CF_CLI_VERSION: "8.18.3"
84+
# renovate: dataSource=github-releases depName=kubernetes-sigs/kind
85+
KIND_VERSION: "0.32.0"
86+
# renovate: dataSource=github-releases depName=helmfile/helmfile
87+
HELMFILE_VERSION: "1.5.3"
88+
- name: Use develop versions of cf-deployment
89+
id: pre_validation
90+
if: steps.check_changes.outputs.skip != 'true' && inputs.fresh-validation == true
91+
env:
92+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
93+
run: |
94+
pip3 install -r scripts/requirements.txt
95+
python3 scripts/sync-cf-deployment-versions.py --ref develop
96+
- name: Run make up
97+
if: steps.check_changes.outputs.skip != 'true'
98+
run: make up
99+
env:
100+
CONTAINER_RUNTIME: ${{ inputs.container-runtime }}
101+
INSTALL_OPTIONAL_COMPONENTS: ${{ inputs.install-optional-components }}
102+
- name: Login
103+
if: steps.check_changes.outputs.skip != 'true'
104+
run: make login
105+
- name: Init
106+
if: steps.check_changes.outputs.skip != 'true'
107+
run: make bootstrap-complete
108+
- name: setup CF tests
109+
if: steps.check_changes.outputs.skip != 'true'
110+
uses: ./.github/actions/setup-cf-tests
111+
with:
112+
test-repo: cf-smoke-tests
113+
test-branch: main
114+
config-template: ./.github/smoke-config.tpl
115+
config-output: ./.github/smoke-config.json
116+
- name: run smoke test
117+
if: steps.check_changes.outputs.skip != 'true'
118+
env:
119+
CONFIG: "${{ github.workspace }}/.github/smoke-config.json"
120+
GINKGO_NO_COLOR: "true"
121+
run: |
122+
./cf-smoke-tests/bin/test --no-color --github-output --timeout=30m --procs=4 --json-report report.json
123+
- name: debug events
124+
if: failure()
125+
run: kubectl get events -A --sort-by='.lastTimestamp'
126+
- name: debug cilium
127+
if: failure() && inputs.container-runtime == 'podman'
128+
run: |
129+
echo "===== CILIUM PODS ====="
130+
kubectl get pod -n kube-system -l k8s-app=cilium -o wide
131+
echo "===== CILIUM AGENT LOGS (all pods) ====="
132+
for pod in $(kubectl get pod -n kube-system -l k8s-app=cilium -o jsonpath='{.items[*].metadata.name}'); do
133+
echo "--- $pod ---"
134+
kubectl logs -n kube-system "$pod" --all-containers=true --previous 2>/dev/null || kubectl logs -n kube-system "$pod" --all-containers=true 2>/dev/null || true
135+
done
136+
echo "===== CILIUM OPERATOR LOGS ====="
137+
kubectl logs -n kube-system -l name=cilium-operator --all-containers=true 2>/dev/null || true
138+
echo "===== CILIUM STATUS ====="
139+
kubectl exec -n kube-system $(kubectl get pod -n kube-system -l k8s-app=cilium -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) -- cilium status 2>/dev/null || true
140+
- name: debug pods
141+
if: failure()
142+
run: |
143+
echo "===== CLOUD_CONTROLLER ====="
144+
kubectl get pod -n cf-system -l app.kubernetes.io/name=cloud-controller -o wide
145+
kubectl get pod -n cf-system -l app.kubernetes.io/name=cloud-controller -o jsonpath='{.status.containerStatuses[*].state}' | jq
146+
kubectl logs -n cf-system -l app.kubernetes.io/name=cloud-controller --all-containers=true
147+
echo "===== CC_WORKER ====="
148+
kubectl get pod -n cf-system -l app.kubernetes.io/name=cc-worker -o wide
149+
kubectl logs -n cf-system -l app.kubernetes.io/name=cc-worker
150+
echo "===== CC_UPLOADER ====="
151+
kubectl get pod -n cf-system -l app=cc-uploader -o wide
152+
kubectl logs -n cf-system -l app=cc-uploader
153+
echo "===== CC_DEPLOYMENT_UPDATER ====="
154+
kubectl get pod -n cf-system -l app.kubernetes.io/name=cc-deployment-updater -o wide
155+
kubectl logs -n cf-system -l app.kubernetes.io/name=cc-deployment-updater
156+
echo "===== CC_WORKER_CLOCK ====="
157+
kubectl get pod -n cf-system -l app.kubernetes.io/name=cc-worker-clock -o wide
158+
kubectl logs -n cf-system -l app.kubernetes.io/name=cc-worker-clock
159+
- name: debug pods (Podman extras)
160+
if: failure() && inputs.container-runtime == 'podman'
161+
run: |
162+
echo "===== CF_TCP_ROUTER ====="
163+
kubectl get pod -n cf-system -l app=cf-tcp-router -o wide
164+
kubectl get pod -n cf-system -l app=cf-tcp-router -o jsonpath='{.items[*].status.containerStatuses[*].state}' | jq 2>/dev/null || true
165+
kubectl logs -n cf-system -l app=cf-tcp-router --all-containers=true 2>/dev/null || true
166+
echo "===== ROUTING_API ====="
167+
kubectl get pod -n cf-system -l app=routing-api -o wide
168+
kubectl logs -n cf-system -l app=routing-api --all-containers=true 2>/dev/null || true
169+
- uses: actions/upload-artifact@v7
170+
if: always()
171+
with:
172+
name: ${{ inputs.artifact-name }}
173+
path: ./cf-smoke-tests/report.json

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
temp/
2-
2+
.idea

Makefile

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@ temp/certs/ca.key temp/certs/ca.crt temp/certs/ssh_key temp/certs/ssh_key.pub te
99
@ ./scripts/init.sh
1010

1111
install:
12-
kind get kubeconfig --name cfk8s > temp/kubeconfig
13-
14-
@if ! command -v helmfile &> /dev/null; then \
15-
echo "helmfile not found, using docker to run helmfile"; \
16-
docker run --rm --net=host --env-file temp/secrets.env \
12+
@ . ./scripts/detect-runtime.sh; \
13+
if [ "$$IS_PODMAN" = "true" ]; then export SKIP_CILIUM="true"; fi; \
14+
kind get kubeconfig --name cfk8s > temp/kubeconfig; \
15+
if ! command -v helmfile &> /dev/null; then \
16+
echo "helmfile not found, using $$CONTAINER_RUNTIME to run helmfile"; \
17+
$$CONTAINER_RUNTIME run --rm --net=host --env-file temp/secrets.env \
1718
--env INSTALL_OPTIONAL_COMPONENTS \
19+
--env CILIUM_EXTRA_VALUES \
20+
--env SKIP_CILIUM \
1821
-v "$$PWD/temp/certs:/certs" -v "$$PWD/temp/kubeconfig:/helm/.kube/config:ro" -v "$$PWD:/wd" --workdir /wd ghcr.io/helmfile/helmfile:v$(HELMFILE_VERSION) helmfile sync; \
1922
else \
2023
echo "helmfile found, using local helmfile"; \
21-
source temp/secrets.sh; \
22-
helmfile sync --kubeconfig temp/kubeconfig; \
24+
source temp/secrets.sh; \
25+
CILIUM_EXTRA_VALUES="$$CILIUM_EXTRA_VALUES" SKIP_CILIUM="$$SKIP_CILIUM" helmfile sync --kubeconfig temp/kubeconfig; \
2326
fi
2427

2528
login:
@@ -43,12 +46,12 @@ create-org:
4346
bootstrap: create-org
4447
@ ./scripts/upload_buildpacks.sh
4548

46-
bootstrap-complete: create-org
49+
bootstrap-complete: create-org
4750
@ ALL_BUILDPACKS=true ./scripts/upload_buildpacks.sh
4851

4952
up: create-kind init install
5053

5154
down: delete-kind
5255
@ rm -rf temp
5356

54-
PHONY: install login create-kind delete-kind up down create-org bootstrap bootstrap-complete
57+
.PHONY: install login create-kind delete-kind up down create-org bootstrap bootstrap-complete

0 commit comments

Comments
 (0)