Skip to content

Add namespace creation Job to prevent deletion on ClusterPackage removal#501

Open
nephomaniac wants to merge 1 commit intoopenshift:masterfrom
nephomaniac:add-namespace-pko-resource
Open

Add namespace creation Job to prevent deletion on ClusterPackage removal#501
nephomaniac wants to merge 1 commit intoopenshift:masterfrom
nephomaniac:add-namespace-pko-resource

Conversation

@nephomaniac
Copy link
Copy Markdown
Contributor

@nephomaniac nephomaniac commented Mar 27, 2026

Summary

(POC) Adds a Job to create the operator namespace during PKO deployment, ensuring the namespace persists when the ClusterPackage is deleted.

Problem

When PKO manages a Namespace resource directly in deploy_pko/, it creates an owner reference from the namespace to the ClusterPackage. This means when the ClusterPackage is deleted, Kubernetes garbage collection also deletes the namespace.

This is problematic because:

  • Deleting the namespace destroys all resources in it
  • Platform namespaces like openshift-route-monitor-operator should persist
  • Operators may need to be removed without destroying their namespace

Solution

Create the namespace via a Job instead of a PKO-managed resource:

  1. Job runs in namespace phase - before other resources need the namespace
  2. Job creates namespace with oc apply - idempotent, no error if exists
  3. Namespace has NO owner reference - not owned by ClusterPackage
  4. Result: Namespace persists when ClusterPackage is deleted

Implementation Details

File: deploy_pko/Create-Namespace-Job.yaml

  • ServiceAccount in default namespace (target namespace doesn't exist yet)
  • ClusterRole with namespace create/patch permissions
  • Job that runs oc apply to create namespace
  • All resources use package-operator.run/phase: namespace annotation
  • All resources use IfNoController collision protection

Follows Established Pattern

This approach matches the pattern used by Cleanup-OLM-Job.yaml:

  • Job runs during a specific PKO phase
  • Job performs cluster operations (create/delete resources)
  • Job is owned by PKO and deleted, but resources it creates/deletes are independent

Test Plan

  • Verify PKO package builds with new manifest
  • Deploy to integration environment
  • Verify namespace is created
  • Delete ClusterPackage
  • Verify namespace persists after deletion

🤖 Generated with Claude Code

@openshift-ci openshift-ci bot requested review from aliceh and clcollins March 27, 2026 20:02
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 27, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: nephomaniac

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@nephomaniac
Copy link
Copy Markdown
Contributor Author

/hold

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Walkthrough

Added a new Kubernetes/OpenShift manifest that idempotently creates and verifies the operator namespace via a Job, plus a ServiceAccount and cluster-scoped RBAC to permit namespace creation.

Changes

Cohort / File(s) Summary
RBAC & Namespace Creation Job
deploy_pko/Create-Namespace-Job.yaml
New manifest (+120/-0) adding ServiceAccount rmo-namespace-creator, ClusterRole (verbs: get, create, patch, update on namespaces), ClusterRoleBinding, and a batch/v1 Job rmo-create-namespace that runs openshift/cli:latest to oc apply a Namespace and poll until its phase is Active. Pod template includes SCC annotation, imagePullPolicy: Always, restartPolicy: Never, backoffLimit: 4, and activeDeadlineSeconds: 60.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 27, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@deploy_pko/Create-Namespace-Job.yaml`:
- Around line 72-77: The job's command uses sh with a script that relies on the
bash-only "pipefail" option; update the command invocation and script shebang so
bash is used explicitly: change the command from "sh -c" to "bash -c" (or
equivalent) and update the script shebang from "#!/bin/sh" to "#!/bin/bash" (or
remove the shebang and rely on the invoked "bash -c"), ensuring the "set -euxo
pipefail" line runs under bash; locate the command block and inline script in
Create-Namespace-Job.yaml (the command: / - sh / - -c / - | block) and make
these substitutions.
- Around line 68-94: The container "create-namespace" currently has no
container-level securityContext; add an explicit securityContext block on that
container to harden it — set runAsNonRoot: true, runAsUser to a non-root UID
(e.g. 1000), ensure privileged: false, set allowPrivilegeEscalation: false, drop
all capabilities (capabilities.drop: ["ALL"]), enable readOnlyRootFilesystem:
true, and set seccompProfile.type to "RuntimeDefault" (and optionally set
procMount/selinuxOptions if required by environment) so the pod-level SCC is
complemented by container-level defense-in-depth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b3cab60b-3c14-493a-b783-22c9b8e9035b

📥 Commits

Reviewing files that changed from the base of the PR and between a7cd7f3 and dab48ee.

📒 Files selected for processing (1)
  • deploy_pko/Create-Namespace-Job.yaml

Comment on lines +68 to +94
containers:
- name: create-namespace
image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
imagePullPolicy: Always
command:
- sh
- -c
- |
#!/bin/sh
set -euxo pipefail

NS="openshift-route-monitor-operator"

# Create namespace if it doesn't exist (idempotent)
cat <<EOF | oc apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: ${NS}
labels:
openshift.io/cluster-monitoring: "true"
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
EOF

echo "Namespace ${NS} created or already exists"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add explicit security context to address static analysis findings.

The container lacks an explicit securityContext. While the restricted-v2 SCC annotation on the pod helps, container-level settings provide defense-in-depth and make the security posture explicit.

🛡️ Proposed fix
       containers:
         - name: create-namespace
           image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
           imagePullPolicy: Always
+          securityContext:
+            allowPrivilegeEscalation: false
+            runAsNonRoot: true
+            capabilities:
+              drop:
+                - ALL
           command:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
containers:
- name: create-namespace
image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
imagePullPolicy: Always
command:
- sh
- -c
- |
#!/bin/sh
set -euxo pipefail
NS="openshift-route-monitor-operator"
# Create namespace if it doesn't exist (idempotent)
cat <<EOF | oc apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: ${NS}
labels:
openshift.io/cluster-monitoring: "true"
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
EOF
echo "Namespace ${NS} created or already exists"
containers:
- name: create-namespace
image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
capabilities:
drop:
- ALL
command:
- sh
- -c
- |
#!/bin/sh
set -euxo pipefail
NS="openshift-route-monitor-operator"
# Create namespace if it doesn't exist (idempotent)
cat <<EOF | oc apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: ${NS}
labels:
openshift.io/cluster-monitoring: "true"
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
EOF
echo "Namespace ${NS} created or already exists"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy_pko/Create-Namespace-Job.yaml` around lines 68 - 94, The container
"create-namespace" currently has no container-level securityContext; add an
explicit securityContext block on that container to harden it — set
runAsNonRoot: true, runAsUser to a non-root UID (e.g. 1000), ensure privileged:
false, set allowPrivilegeEscalation: false, drop all capabilities
(capabilities.drop: ["ALL"]), enable readOnlyRootFilesystem: true, and set
seccompProfile.type to "RuntimeDefault" (and optionally set
procMount/selinuxOptions if required by environment) so the pod-level SCC is
complemented by container-level defense-in-depth.

Comment on lines +72 to +77
command:
- sh
- -c
- |
#!/bin/sh
set -euxo pipefail
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use bash instead of sh for pipefail compatibility.

The script uses set -euxo pipefail, but pipefail is a bash feature, not POSIX sh. While RHEL-based images typically symlink sh to bash, this is implicit. Using bash explicitly ensures the script works as intended.

🔧 Proposed fix
           command:
-            - sh
+            - /bin/bash
             - -c
             - |
-              #!/bin/sh
+              #!/bin/bash
               set -euxo pipefail
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
command:
- sh
- -c
- |
#!/bin/sh
set -euxo pipefail
command:
- /bin/bash
- -c
- |
#!/bin/bash
set -euxo pipefail
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy_pko/Create-Namespace-Job.yaml` around lines 72 - 77, The job's command
uses sh with a script that relies on the bash-only "pipefail" option; update the
command invocation and script shebang so bash is used explicitly: change the
command from "sh -c" to "bash -c" (or equivalent) and update the script shebang
from "#!/bin/sh" to "#!/bin/bash" (or remove the shebang and rely on the invoked
"bash -c"), ensuring the "set -euxo pipefail" line runs under bash; locate the
command block and inline script in Create-Namespace-Job.yaml (the command: / -
sh / - -c / - | block) and make these substitutions.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.26%. Comparing base (a7cd7f3) to head (91c4686).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #501   +/-   ##
=======================================
  Coverage   56.26%   56.26%           
=======================================
  Files          31       31           
  Lines        2851     2851           
=======================================
  Hits         1604     1604           
  Misses       1137     1137           
  Partials      110      110           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nephomaniac nephomaniac force-pushed the add-namespace-pko-resource branch from dab48ee to 91c4686 Compare March 27, 2026 20:29
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
deploy_pko/Create-Namespace-Job.yaml (2)

72-117: ⚠️ Potential issue | 🟠 Major

Add explicit container securityContext for least privilege.

The container currently relies only on SCC. Add explicit container-level hardening to prevent privilege escalation/root admission drift and address the CKV findings.

Proposed fix
       containers:
         - name: create-namespace
           image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
           imagePullPolicy: Always
+          securityContext:
+            allowPrivilegeEscalation: false
+            privileged: false
+            runAsNonRoot: true
+            capabilities:
+              drop:
+                - ALL
           command:

As per coding guidelines "**: -Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy_pko/Create-Namespace-Job.yaml` around lines 72 - 117, The
create-namespace container lacks an explicit container-level securityContext;
add one under the container spec for the container named "create-namespace" to
enforce least privilege: set runAsNonRoot: true and a non-root runAsUser (e.g.
1000), set allowPrivilegeEscalation: false, set readOnlyRootFilesystem: true,
drop all capabilities (capabilities: drop: ["ALL"]), and add a seccompProfile
(type: RuntimeDefault) to harden the runtime; place this securityContext block
beneath the container definition for "create-namespace" so it applies to the job
container regardless of cluster SCCs.

76-81: ⚠️ Potential issue | 🟠 Major

Use bash explicitly when enabling pipefail.

Line [77] runs sh -c, but Line [81] uses set -euxo pipefail (not guaranteed in POSIX sh). This can make the Job fail before doing any namespace work.

Proposed fix
           command:
-            - sh
+            - /bin/bash
             - -c
             - |
-              #!/bin/sh
+              #!/bin/bash
               set -euxo pipefail

As per coding guidelines "**: -Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy_pko/Create-Namespace-Job.yaml` around lines 76 - 81, The job's command
uses sh (- sh - -c) but the script sets "set -euxo pipefail", which is not
portable to POSIX sh; change the command to invoke bash (use - bash - -c) and
update the shebang line in the multi-line script to #!/usr/bin/env bash so that
the pipefail option is supported and the set invocation in the command block
(the script started under the command: section and its shebang) runs reliably.
🧹 Nitpick comments (1)
deploy_pko/Create-Namespace-Job.yaml (1)

74-75: Pin the CLI image to an immutable digest.

Using :latest with imagePullPolicy: Always makes rollout behavior non-deterministic and increases supply-chain drift risk. Prefer a pinned digest.

Proposed fix
-          image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
-          imagePullPolicy: Always
+          image: image-registry.openshift-image-registry.svc:5000/openshift/cli@sha256:<approved-digest>
+          imagePullPolicy: IfNotPresent

As per coding guidelines "**: -Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy_pko/Create-Namespace-Job.yaml` around lines 74 - 75, The image is
using a mutable tag
"image-registry.openshift-image-registry.svc:5000/openshift/cli:latest" with
imagePullPolicy: Always; replace that tag with an immutable digest (sha256) to
pin the CLI image and ensure deterministic rollouts. Update the "image" field to
the same registry URL but with the resolved digest (e.g., `@sha256`:<digest>) and
keep imagePullPolicy as Always (or change to IfNotPresent if desired), ensuring
you locate and modify the exact "image:
image-registry.openshift-image-registry.svc:5000/openshift/cli:latest" line and
its accompanying "imagePullPolicy" entry in this manifest.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@deploy_pko/Create-Namespace-Job.yaml`:
- Around line 72-117: The create-namespace container lacks an explicit
container-level securityContext; add one under the container spec for the
container named "create-namespace" to enforce least privilege: set runAsNonRoot:
true and a non-root runAsUser (e.g. 1000), set allowPrivilegeEscalation: false,
set readOnlyRootFilesystem: true, drop all capabilities (capabilities: drop:
["ALL"]), and add a seccompProfile (type: RuntimeDefault) to harden the runtime;
place this securityContext block beneath the container definition for
"create-namespace" so it applies to the job container regardless of cluster
SCCs.
- Around line 76-81: The job's command uses sh (- sh - -c) but the script sets
"set -euxo pipefail", which is not portable to POSIX sh; change the command to
invoke bash (use - bash - -c) and update the shebang line in the multi-line
script to #!/usr/bin/env bash so that the pipefail option is supported and the
set invocation in the command block (the script started under the command:
section and its shebang) runs reliably.

---

Nitpick comments:
In `@deploy_pko/Create-Namespace-Job.yaml`:
- Around line 74-75: The image is using a mutable tag
"image-registry.openshift-image-registry.svc:5000/openshift/cli:latest" with
imagePullPolicy: Always; replace that tag with an immutable digest (sha256) to
pin the CLI image and ensure deterministic rollouts. Update the "image" field to
the same registry URL but with the resolved digest (e.g., `@sha256`:<digest>) and
keep imagePullPolicy as Always (or change to IfNotPresent if desired), ensuring
you locate and modify the exact "image:
image-registry.openshift-image-registry.svc:5000/openshift/cli:latest" line and
its accompanying "imagePullPolicy" entry in this manifest.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f0d25046-79f9-4e6b-b37e-fc5b2e40b789

📥 Commits

Reviewing files that changed from the base of the PR and between dab48ee and 91c4686.

📒 Files selected for processing (1)
  • deploy_pko/Create-Namespace-Job.yaml

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 27, 2026

@nephomaniac: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

This Job creates the openshift-route-monitor-operator namespace during
the PKO namespace phase if it doesn't already exist.

Using a Job (instead of a PKO-managed Namespace resource) ensures the
namespace is created without owner references to the ClusterPackage,
so it persists when the ClusterPackage is deleted.

The Job runs in the 'default' namespace with cluster-level RBAC to
create namespaces, following the same pattern as Cleanup-OLM-Job.yaml.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@nephomaniac nephomaniac force-pushed the add-namespace-pko-resource branch from 91c4686 to 07ecca7 Compare March 27, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants