Skip to content

OPNET-782: Render BGP VIP static pods instead of keepalived#6326

Open
mkowalski wants to merge 4 commits into
openshift:mainfrom
mkowalski:OPNET-595-mco-pr
Open

OPNET-782: Render BGP VIP static pods instead of keepalived#6326
mkowalski wants to merge 4 commits into
openshift:mainfrom
mkowalski:OPNET-595-mco-pr

Conversation

@mkowalski

@mkowalski mkowalski commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What

MCO side of BGP-based VIP management for on-premise platforms
(enhancement #1982, OPNET-773). When the BareMetal
Infrastructure CR requests vipManagement: BGP (behind the BGPBasedVIPManagement feature gate,
DevPreviewNoUpgrade), render frr-k8s + kube-vip static pods on control plane nodes instead of the
keepalived manifests. kube-vip runs in routing-table mode: it installs the VIP route into kernel
table 198 only while the local health check passes, and FRR advertises that table — per-node
health-gated ECMP from the ToR.

Four commits, each builds on its own:

  1. vendor: openshift/api with BGPBasedVIPManagement — interim pin to the api PR content
    (OPNET-780: Add BGPBasedVIPManagement feature gate and BGP VIP management fields api#2923); becomes a one-commit swap to the merged api on rebase.
  2. template: render BGP VIP static pods instead of keepalived — frr-k8s static pod (masters),
    kube-vip API/ingress static pods (keepalived parity), hostPath sockets prepared by a boot unit
    (0777 for the mixed-uid FRR daemons, container_file_t for the MCS-confined metrics companion
    that CNO deploys against them); requires non-empty VIPs (user-managed LB is rejected in BGP mode).
  3. operator: bootstrap and day-2 support — RenderBootstrap ingests the installer-generated
    bgp-vip-config ConfigMap (--bgp-vip-config-file) into ControllerConfigSpec.BGPVIPPeersJSON;
    bootstrap runs an FRR-only static pod so the API VIP is advertised while the control plane forms;
    day-2 the operator re-reads the ConfigMap each sync (absence degrades instead of blanking peers
    fleet-wide); missing frr-k8s/kube-vip images fail bootstrap render early.
  4. install: image-references for frr-k8s and kube-vip — split on purpose: payload assembly fails
    on an image-references entry whose tag does not exist, so this must land only after the kube-vip
    payload tag is onboarded (ART-21663, OPNET-779: kube-vip: build the image and promote to ocp/5.0 release#81957).

Dependencies / ordering

Privileged settings justification

The new static pod manifests intentionally use the following privileged
settings (also documented as comments in the manifests themselves):

  • hostNetwork: true (frr-k8s and kube-vip pods): required by function.
    The BGP session must originate from the node IP so the ToR peers with the
    node itself, and the health-gated VIP routes are installed into the host
    routing table (kernel table 198) that FRR redistributes. This is exact
    parity with both the keepalived/haproxy static pods being replaced and the
    frr-k8s DaemonSet shipped by CNO.
  • SYS_ADMIN on the frr container only: required by FRR's
    docker-start/watchfrr process supervision. Same capability set as the
    frr container of the CNO-shipped frr-k8s DaemonSet (upstream
    metallb/frr-k8s parity). Note this container deliberately does NOT use
    drop: ALL: it was tested live and FRR's privilege-separated startup
    (watchfrr as root spawning daemons as the frr user) fails without
    root-implicit SETUID/SETGID/DAC_OVERRIDE/CHOWN.
  • Every other container in these pods drops ALL capabilities with minimal
    re-adds (kube-vip: NET_ADMIN/NET_RAW for netlink route management;
    reloader/frr-status: DAC_OVERRIDE for root vtysh against frr-user-owned
    vty sockets), sets allowPrivilegeEscalation: false and
    readOnlyRootFilesystem: true, and has CPU/memory limits.

Testing

Validated end-to-end on dev-scripts baremetal IPI clusters (3 masters + 2 workers, dual VIP), most
recently on a 5.0.0-0.nightly-2026-07-20-081439 base: API VIP ECMP from all masters, ingress VIP
ECMP from router-bearing workers, health-gated withdrawal on node failure, console served over the
BGP-routed path, full frr metrics coverage in Prometheus (static pods via the CNO metrics companion).
Bootstrap-to-CRD handover exercised on every install.


This PR description was prepared with AI assistance. Please verify before acting on it.

Summary by CodeRabbit

  • New Features
    • Added BGP-based VIP management for bare-metal using FRR and kube-vip, including on-node static pods (FRR, kube-vip API, and kube-vip ingress).
    • Added RBAC for reading the BGP VIP peers ConfigMap.
    • Introduced CLI/image reference options to configure FRR-k8s and kube-vip bootstrap/controller images, plus configurable BGP VIP config input.
  • Bug Fixes
    • Prevented failures when platform IP lists are empty.
    • Ensured keepalived is disabled when BGP VIP management is active; missing optional BGP image mappings now warn instead of failing.
  • Chores
    • Updated manifests/templates and refreshed dependency versions.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 22, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@mkowalski: This pull request references OPNET-782 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

What

MCO side of BGP-based VIP management for on-premise platforms
(enhancement #1982, OPNET-773). When the BareMetal
Infrastructure CR requests vipManagement: BGP (behind the BGPBasedVIPManagement feature gate,
DevPreviewNoUpgrade), render frr-k8s + kube-vip static pods on control plane nodes instead of the
keepalived manifests. kube-vip runs in routing-table mode: it installs the VIP route into kernel
table 198 only while the local health check passes, and FRR advertises that table — per-node
health-gated ECMP from the ToR.

Four commits, each builds on its own:

  1. vendor: openshift/api with BGPBasedVIPManagement — interim pin to the api PR content
    (OPNET-780: Add BGPBasedVIPManagement feature gate and BGP VIP management fields api#2923); becomes a one-commit swap to the merged api on rebase.
  2. template: render BGP VIP static pods instead of keepalived — frr-k8s static pod (masters),
    kube-vip API/ingress static pods (keepalived parity), hostPath sockets prepared by a boot unit
    (0777 for the mixed-uid FRR daemons, container_file_t for the MCS-confined metrics companion
    that CNO deploys against them); requires non-empty VIPs (user-managed LB is rejected in BGP mode).
  3. operator: bootstrap and day-2 support — RenderBootstrap ingests the installer-generated
    bgp-vip-config ConfigMap (--bgp-vip-config-file) into ControllerConfigSpec.BGPVIPPeersJSON;
    bootstrap runs an FRR-only static pod so the API VIP is advertised while the control plane forms;
    day-2 the operator re-reads the ConfigMap each sync (absence degrades instead of blanking peers
    fleet-wide); missing frr-k8s/kube-vip images fail bootstrap render early.
  4. install: image-references for frr-k8s and kube-vip — split on purpose: payload assembly fails
    on an image-references entry whose tag does not exist, so this must land only after the kube-vip
    payload tag is onboarded (ART-21663, OPNET-779: kube-vip: build the image and promote to ocp/5.0 release#81957).

Dependencies / ordering

Testing

Validated end-to-end on dev-scripts baremetal IPI clusters (3 masters + 2 workers, dual VIP), most
recently on a 5.0.0-0.nightly-2026-07-20-081439 base: API VIP ECMP from all masters, ingress VIP
ECMP from router-bearing workers, health-gated withdrawal on node failure, console served over the
BGP-routed path, full frr metrics coverage in Prometheus (static pods via the CNO metrics companion).
Bootstrap-to-CRD handover exercised on every install.


This PR description was prepared with AI assistance. Please verify before acting on it.

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mkowalski
Once this PR has been reviewed and has the lgtm label, please assign dkhater-redhat for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@openshift-ci
openshift-ci Bot requested review from eslutsky and pablintino July 22, 2026 10:13
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds BareMetal BGP VIP management with peer synchronization, image wiring, FRR and kube-vip static pods, conditional keepalived replacement, bootstrap validation, RBAC access, and related tests. It also updates Go modules and container runtime policy fixtures.

Changes

BGP VIP management

Layer / File(s) Summary
BGP contracts and bootstrap inputs
pkg/controller/common/*, pkg/controller/template/constants.go, cmd/machine-config-operator/bootstrap.go, install/*
Adds BGP detection, image fields, bootstrap flags, image references, RBAC access, and optional peer configuration input.
Peer synchronization and render specification
pkg/operator/bootstrap_dependencies.go, pkg/operator/sync.go, pkg/operator/bootstrap.go, manifests/on-prem/frr-peers.json.tmpl, pkg/operator/*_test.go
Loads and compacts bgp-vip-config, propagates peer JSON and image entries, validates required images, and tests synchronization and rendering behavior.
Platform selection and template gating
pkg/operator/render.go, pkg/controller/template/render.go, templates/common/on-prem/files/*
Selects BGP resources for BareMetal, disables keepalived, guards empty platform IP slices, and adds conditional kube-vip ingress rendering.
FRR and kube-vip runtime resources
templates/master/00-master/on-prem/*, manifests/on-prem/*
Adds FRR configuration, static pods, kube-vip API resources, startup files, and host-path preparation.
Toolchain and runtime policy fixtures
go.mod, pkg/controller/container-runtime-config/*
Updates Go and module versions, adds an OpenShift API replacement, and adds container signature policy fixtures.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Bootstrap
  participant ConfigMap
  participant Operator
  participant FRR
  participant KubeVIP

  Bootstrap->>ConfigMap: read bgp-vip-config
  ConfigMap-->>Bootstrap: return config.json peer data
  Bootstrap->>Operator: provide images and peer configuration
  Operator->>FRR: render peer data and BGP configuration
  Operator->>KubeVIP: render API and ingress pods
Loading

Suggested reviewers: pablintino, eslutsky


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
No-Weak-Crypto ❌ Error New FRR BGP templates render neighbor ... password, and FRR docs state this command uses TCP MD5 auth, which this check flags. Avoid rendering BGP neighbor passwords or switch to a stronger auth mechanism if supported; otherwise document an explicit exception for TCP MD5.
Container-Privileges ❌ Error The PR adds hostNetwork:true to several Pods and adds SYS_ADMIN to the FRR container; those are explicitly disallowed by the check. Remove or gate hostNetwork and SYS_ADMIN from the rendered manifests, or narrow the check if these privileged settings are intentional and required.
Docstring Coverage ⚠️ Warning Docstring coverage is 44.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (12 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing keepalived with BGP VIP static pods.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The PR’s added tests use static, descriptive titles; no Ginkgo-style or dynamic identifiers/IPs/timestamps were introduced.
Test Structure And Quality ✅ Passed No Ginkgo/cluster tests were added; the new table-driven unit tests use fakes/TempDir, no waits, and match existing repo patterns.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the changed tests are standard Test... unit tests, so MicroShift-specific gating is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the touched test files are Go unit tests and contain no It/Describe/Context/When blocks or SNO assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed No new topology-sensitive scheduling was added: the BGP pods use existing broad static-pod placement and there are no new nodeSelectors, anti-affinity, spread constraints, or replica rules.
Ote Binary Stdout Contract ✅ Passed Changed setup paths only set flags or use klog after logtostderr; no new stdout writes appear in main/init/TestMain setup.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The added tests are unit tests using testing.T, with no Ginkgo/e2e constructs or external connectivity; no IPv6/disconnected CI issue is introduced.
No-Sensitive-Data-In-Logs ✅ Passed No new logs emit passwords/tokens/PII; new BGP peer data is rendered to files, and added warnings only mention image names or paths.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
go.mod

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

install/0000_80_machine-config_00_rbac.yaml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

install/0000_80_machine-config_02_images.configmap.yaml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

  • 13 others

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/operator/render.go (1)

280-313: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Gate kube-vip-ingress on ingress VIPs
isBGPVIPManagement only checks BareMetal.APIServerInternalIPs, so templates/common/on-prem/files/0020-kube-vip-ingress.yaml:26 can still render {{ onPremPlatformIngressIP . }} as <no value> when IngressIPs is empty. Add an ingress-IP check before enabling this manifest, or switch to the plural helper with a length guard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/render.go` around lines 280 - 313, Update the kube-vip-ingress
enablement logic associated with isBGPVIPManagement so the manifest renders only
when the selected on-prem platform has at least one IngressIP. Add the
ingress-IP presence check before enabling 0020-kube-vip-ingress.yaml, or use the
plural ingress-IP helper with an explicit length guard, preventing
onPremPlatformIngressIP from producing a missing value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Around line 476-477: Restrict the github.com/openshift/api replacement to the
specific required upstream version by adding that version to the replace
directive, rather than applying it to all selected versions. Preserve the fork
module and pinned fork version, and use the approved upstream/internal module if
the fork is not intended to remain globally substituted.

In `@manifests/on-prem/0000-frr-k8s.yaml`:
- Around line 42-51: Update the volume mounts for resource-dir,
frr-conf/frr-startup, kubeconfig, and manifests in the pod specifications to set
readOnly: true, including the additionally referenced mounts. Preserve
mountPropagation: HostToContainer on manifests and do not alter mounts that
require write access.
- Around line 73-105: Add liveness and readiness probes to the FRR container
definition in manifests/on-prem/0000-frr-k8s.yaml:73-105, using an appropriate
FRR health check. Add corresponding liveness and readiness probes to the
kube-vip container in manifests/on-prem/0010-kube-vip-api.yaml:15-52, ensuring
both critical static pods expose checks that detect unhealthy or hung processes.
- Around line 60-95: Harden both static pod manifests: in
manifests/on-prem/0000-frr-k8s.yaml lines 60-95, update every init and main
container securityContext to run as non-root with privilege escalation disabled,
drop ALL capabilities, and remove SYS_ADMIN unless explicitly justified; in
manifests/on-prem/0010-kube-vip-api.yaml lines 47-51, add the required non-root,
no-escalation, read-only-root-filesystem settings and drop ALL capabilities
while preserving only justified additions.
- Around line 54-59: Update the shell command in the init container’s command
block to fail immediately when either FRR configuration copy fails. Add `set
-eu` before the `cp` commands or chain both copies with `&&`, preserving the
existing copy paths and order.
- Around line 68-72: Update the pod volume definitions and mounts associated
with frr-startup and frr-conf to use the prepared hostPath directories instead
of emptyDir, mounting the host configuration and socket paths under
/run/frr-k8s/{conf,sockets}. Ensure the paths are writable by UID 100 and shared
with the metrics companion while preserving the existing container mount
targets.

In `@manifests/on-prem/frr.conf.tmpl`:
- Around line 44-50: Apply the VIP-COMMUNITY route-map to outbound peer updates
by adding the neighbor route-map command inside the peer loop in
manifests/on-prem/frr.conf.tmpl#L10-L24 and
templates/master/00-master/on-prem/files/frr-k8s-conf.yaml#L14-L28, using each
peer’s PeerAddress. Keep the existing VIP-COMMUNITY definition and community
entries unchanged.

In `@pkg/operator/bootstrap_dependencies.go`:
- Around line 285-305: Update fillBGPVIPConfig to reject an empty config.json
payload consistently with syncBGPVIPPeersJSON. After reading the ConfigMap,
ensure compactBGPVIPPeersJSON or the surrounding logic returns the same error
for empty input instead of assigning a blank BGPVIPPeersJSON; preserve the
existing optional-missing-ConfigMap behavior.

In `@templates/common/on-prem/files/0020-kube-vip-ingress.yaml`:
- Around line 51-59: Update the container specification in the Kubernetes
manifest to add CPU and memory resource limits alongside the existing requests,
drop all capabilities before adding only the required NET_ADMIN and NET_RAW
capabilities, and set allowPrivilegeEscalation to false in the container
securityContext.

In `@templates/master/00-master/on-prem/files/0000-frr-k8s.yaml`:
- Around line 14-173: Harden every container and initContainer in
templates/master/00-master/on-prem/files/0000-frr-k8s.yaml (lines 14-173) and
templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml (lines 15-55)
with allowPrivilegeEscalation: false, readOnlyRootFilesystem: true, drop ALL
capabilities, only explicitly required capabilities, and CPU/memory limits;
retain hostNetwork only where required. For the frr container, remove SYS_ADMIN
unless a documented exception justifies it, and document that exception if
retained.

---

Outside diff comments:
In `@pkg/operator/render.go`:
- Around line 280-313: Update the kube-vip-ingress enablement logic associated
with isBGPVIPManagement so the manifest renders only when the selected on-prem
platform has at least one IngressIP. Add the ingress-IP presence check before
enabling 0020-kube-vip-ingress.yaml, or use the plural ingress-IP helper with an
explicit length guard, preventing onPremPlatformIngressIP from producing a
missing value.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9ee0fd22-7ea3-478e-a550-d1d305d76a75

📥 Commits

Reviewing files that changed from the base of the PR and between df0b2d6 and 31750b2.

⛔ Files ignored due to path filters (76)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_infrastructure.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_ingress.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_criocredentialproviderconfigs.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_console_01_consoles.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1alpha1/types_clusterapi.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/prototext/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/descfmt/stringer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/text/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/codec_map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/validate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/version/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/proto/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/editions.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (34)
  • cmd/machine-config-operator/bootstrap.go
  • go.mod
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/container-runtime-config/actual.json
  • pkg/controller/container-runtime-config/expected.json
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml

Comment thread go.mod
Comment thread manifests/on-prem/0000-frr-k8s.yaml
Comment thread manifests/on-prem/0000-frr-k8s.yaml
Comment thread manifests/on-prem/0000-frr-k8s.yaml
Comment thread manifests/on-prem/0000-frr-k8s.yaml
Comment thread manifests/on-prem/0000-frr-k8s.yaml
Comment thread manifests/on-prem/frr.conf.tmpl
Comment thread pkg/operator/bootstrap_dependencies.go
Comment thread templates/common/on-prem/files/0020-kube-vip-ingress.yaml
Comment thread templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
@mkowalski

Copy link
Copy Markdown
Contributor Author

Re the outside-diff comment on pkg/operator/render.go (kube-vip-ingress rendering with empty IngressIPs): fixed at the shared gate — IsBGPVIPManagement now requires both APIServerInternalIPs and IngressIPs to be non-empty, so the template renderer, bootstrap manifest selection, and operator ingestion all fall back to the keepalived default together. Test case added.

Summary of the review round: all inline comments addressed or answered in-thread; the securityContext changes were validated live on a running BGP-VIP cluster (which also caught that drop: ALL on the frr container breaks FRR's privilege-separated startup — details in the thread and in-manifest comments).

This comment was written with AI assistance. Please verify before acting on it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@templates/common/on-prem/files/0020-kube-vip-ingress.yaml`:
- Around line 55-63: Set runAsNonRoot: true and an explicit non-zero runAsUser
in the kube-vip pod security contexts at
templates/common/on-prem/files/0020-kube-vip-ingress.yaml lines 55-63 and
templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml lines 51-59. In
templates/master/00-master/on-prem/files/0000-frr-k8s.yaml lines 41-46, apply
the same non-root settings only to render-config-frr; leave cp-frr-files, frr,
reloader, and frr-status unchanged.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9cd86428-3547-4439-8d98-23f21081658d

📥 Commits

Reviewing files that changed from the base of the PR and between 31750b2 and a3aa0f9.

📒 Files selected for processing (31)
  • cmd/machine-config-operator/bootstrap.go
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml
🚧 Files skipped from review as they are similar to previous changes (24)
  • manifests/on-prem/frr.conf.tmpl
  • install/0000_80_machine-config_02_images.configmap.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • install/image-references
  • pkg/operator/render_test.go
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/0010-kube-vip-api.yaml
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • manifests/on-prem/frr-startup-daemons
  • pkg/controller/template/constants.go
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • pkg/controller/template/render_test.go
  • manifests/on-prem/0000-frr-k8s.yaml
  • pkg/operator/sync.go
  • pkg/operator/render.go
  • pkg/operator/bootstrap_dependencies.go
  • install/0000_80_machine-config_00_rbac.yaml
  • pkg/operator/bootstrap_test.go
  • cmd/machine-config-operator/bootstrap.go
  • pkg/controller/template/render.go
  • pkg/operator/bootstrap.go

Comment thread templates/common/on-prem/files/0020-kube-vip-ingress.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@templates/master/00-master/on-prem/files/0000-frr-k8s.yaml`:
- Around line 13-19: Update the pod specification’s
terminationGracePeriodSeconds in the FRR Kubernetes manifest from zero to a
positive grace period sufficient for the frr, reloader, and controller
containers to gracefully close BGP sessions and withdraw VIP routes during
termination.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4d2dc89b-eaa1-4776-9104-161bf8a49944

📥 Commits

Reviewing files that changed from the base of the PR and between a3aa0f9 and 9d3ad42.

📒 Files selected for processing (31)
  • cmd/machine-config-operator/bootstrap.go
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml
🚧 Files skipped from review as they are similar to previous changes (26)
  • manifests/on-prem/frr-startup-vtysh.conf
  • install/0000_80_machine-config_02_images.configmap.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • install/image-references
  • install/0000_80_machine-config_00_rbac.yaml
  • manifests/on-prem/frr-startup-daemons
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • manifests/on-prem/frr.conf.tmpl
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • pkg/operator/render.go
  • pkg/controller/common/helpers.go
  • pkg/operator/render_test.go
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • pkg/controller/common/images.go
  • pkg/controller/template/constants.go
  • pkg/operator/bootstrap_test.go
  • pkg/controller/template/render_test.go
  • manifests/on-prem/0000-frr-k8s.yaml
  • pkg/operator/bootstrap_dependencies.go
  • cmd/machine-config-operator/bootstrap.go
  • pkg/operator/bootstrap.go
  • pkg/controller/template/render.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go

Comment thread templates/master/00-master/on-prem/files/0000-frr-k8s.yaml Outdated
@mkowalski

Copy link
Copy Markdown
Contributor Author

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@mkowalski

Copy link
Copy Markdown
Contributor Author

@coderabbitai The hostNetwork and SYS_ADMIN usage flagged by the Container-Privileges pre-merge check is required and now justified explicitly in the PR description ("Privileged settings justification" section) and as comments in the manifests: hostNetwork is functionally required (BGP sessions originate from the node IP; VIP routes live in the host routing table — keepalived parity), and SYS_ADMIN on the frr container matches the CNO-shipped frr-k8s DaemonSet and is required by FRR's docker-start/watchfrr supervision. Please re-evaluate the check.

This comment was written with AI assistance. Please verify before acting on it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
templates/master/00-master/on-prem/files/frr-k8s-conf.yaml (1)

1-63: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use decimal 420 for the file mode
Ignition file permissions are decimal integers, so 0644 is parser-dependent here; 420 makes the intended -rw-r--r-- explicit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@templates/master/00-master/on-prem/files/frr-k8s-conf.yaml` around lines 1 -
63, Update the file mode declaration for the FRR configuration template to use
decimal 420 instead of the octal-style 0644, preserving the resulting -rw-r--r--
permissions.
🧹 Nitpick comments (1)
pkg/operator/bootstrap.go (1)

249-294: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Use the typed constant instead of a bare string literal for the BGP comparison.

vipManagement == "BGP" compares against a literal string, while the assignment site (line 175) correctly uses configv1.VIPManagementTypeBGP. A silent typo or future constant-value change here would make BGP clusters silently render keepalived manifests instead of failing loudly.

♻️ Suggested fix
-	if vipManagement == "BGP" {
+	if vipManagement == configv1.VIPManagementTypeBGP {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/bootstrap.go` around lines 249 - 294, Update the BGP comparison
in getPlatformManifests to use configv1.VIPManagementTypeBGP instead of the bare
"BGP" string literal, preserving the existing manifest-selection behavior for
BGP and non-BGP VIP management types.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Around line 476-477: Document the temporary fork replacement directly
alongside the github.com/openshift/api replace directive, including a reference
to the relevant upstream issue or PR and the condition or planned point for
removing it. Keep the replacement unchanged unless upstream support is already
available, in which case remove it.

In `@manifests/on-prem/0010-kube-vip-api.yaml`:
- Around line 20-46: Add the kube-vip control-plane health-check address setting
alongside the existing health-check environment variables in the on-prem API
manifest, using the local apiserver endpoint required to withdraw the VIP when
unhealthy. Apply the same configuration to the matching day-2 manifest,
preserving the existing backend_health_check_interval setting.

In `@pkg/operator/sync.go`:
- Around line 393-407: Update syncBGPVIPPeersJSON to avoid an unbounded live API
call: first reuse an existing informer/lister for the
openshift-network-operator/bgp-vip-config ConfigMap if one is already available,
otherwise create a context.Context with an appropriate timeout and pass it to
the ConfigMaps Get call, ensuring cancellation and cleanup while preserving the
existing not-found and other error handling.

In `@templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml`:
- Around line 20-46: Add the kube-vip control-plane health gate to the container
environment in the manifest, matching the ingress VIP’s
control_plane_health_check_address and timeout settings while preserving the
existing routing-table configuration.

In `@templates/master/00-master/on-prem/files/frr-k8s-peers.yaml`:
- Around line 1-5: Update the mode for the frr-peers.json resource in the
surrounding template to restrict access to owner/group-only rather than
world-readable, using the repository’s established mode encoding convention
consistently with frr-k8s-conf.yaml.

---

Outside diff comments:
In `@templates/master/00-master/on-prem/files/frr-k8s-conf.yaml`:
- Around line 1-63: Update the file mode declaration for the FRR configuration
template to use decimal 420 instead of the octal-style 0644, preserving the
resulting -rw-r--r-- permissions.

---

Nitpick comments:
In `@pkg/operator/bootstrap.go`:
- Around line 249-294: Update the BGP comparison in getPlatformManifests to use
configv1.VIPManagementTypeBGP instead of the bare "BGP" string literal,
preserving the existing manifest-selection behavior for BGP and non-BGP VIP
management types.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 39f9155a-27dd-40e6-923b-7306a3c00826

📥 Commits

Reviewing files that changed from the base of the PR and between 58108b0 and 9b1afc6.

⛔ Files ignored due to path filters (76)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_infrastructure.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_ingress.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_criocredentialproviderconfigs.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_console_01_consoles.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1alpha1/types_clusterapi.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/prototext/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/descfmt/stringer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/text/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/codec_map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/validate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/version/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/proto/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/editions.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (34)
  • cmd/machine-config-operator/bootstrap.go
  • go.mod
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/container-runtime-config/actual.json
  • pkg/controller/container-runtime-config/expected.json
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml

Comment thread go.mod
Comment thread manifests/on-prem/0010-kube-vip-api.yaml
Comment thread pkg/operator/sync.go
Comment on lines +20 to +46
- name: kube-vip
image: {{.Images.kubeVipImage}}
args:
- manager
env:
- name: address
value: "{{ onPremPlatformAPIServerInternalIP . }}"
- name: k8s_config_file
value: "/etc/kubernetes/kubeconfig"
- name: kubernetes_addr
value: "https://localhost:6443"
- name: port
value: "6443"
- name: cp_enable
value: "true"
- name: vip_leaderelection
value: "true"
- name: vip_routingtable
value: "true"
- name: vip_cleanroutingtable
value: "true"
- name: vip_routingtableid
value: "198"
- name: vip_routingtableprotocol
value: "248"
- name: backend_health_check_interval
value: "5"

@coderabbitai coderabbitai Bot Jul 22, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

printf '\n## File listing\n'
git ls-files 'templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml' \
             'manifests/on-prem/0010-kube-vip-api.yaml' \
             'templates/common/on-prem/files/0020-kube-vip-ingress.yaml' \
             'manifests/on-prem/0020-kube-vip-ingress.yaml'

printf '\n## Search health-check env vars\n'
rg -n 'control_plane_health_check|backend_health_check_interval|vip_leaderelection|kube-vip' templates manifests -g '*.yaml' -g '*.yml'

printf '\n## Read target file excerpt\n'
sed -n '1,120p' templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml

printf '\n## Read sibling ingress excerpt\n'
sed -n '1,160p' templates/common/on-prem/files/0020-kube-vip-ingress.yaml

printf '\n## Read bootstrap api excerpt\n'
sed -n '1,120p' manifests/on-prem/0010-kube-vip-api.yaml

Repository: openshift/machine-config-operator

Length of output: 1952


🌐 Web query:

kube-vip control_plane_health_check_address control_plane_health_check_timeout_seconds env vars manager mode api vip local apiserver health check

💡 Result:

Kube-vip provides a mechanism to monitor the local Kubernetes API server and automatically withdraw BGP routes if the server becomes unresponsive. This feature is designed primarily for BGP mode to maintain high availability [1][2]. Control Plane Health Check Configuration The health check is disabled by default [1]. To enable it, you must configure the following environment variables (or their corresponding CLI flags) [1][3]: - control_plane_health_check_address: The URL to poll for health status (e.g., https://localhost:6443/livez) [1][3]. Setting this enables the health check [2]. - control_plane_health_check_period_seconds: The interval between health check requests (default: 5) [1][3]. - control_plane_health_check_timeout_seconds: The timeout for each individual HTTP request (default: 3) [1][3]. - control_plane_health_check_failure_threshold: The number of consecutive failed probes before the BGP route is withdrawn (default: 3) [1][3]. - control_plane_health_check_ca_path: The path to a CA certificate for HTTPS verification. This is required if the API server uses a private CA [1][3]. How the Health Check Works When enabled, kube-vip continuously polls the specified address. If the endpoint fails to respond successfully within the configured timeout, it records a failure. The BGP route is withdrawn only after the number of consecutive failures reaches the configured threshold [1][2]. This approach prevents route flapping caused by transient network issues or temporary API server restarts [2]. Important Considerations - Behavioral Change: When this feature is enabled, BGP routes are not announced until the first successful health check probe is completed [2]. - Performance: Reducing the period and timeout values allows for faster detection of failures but increases the polling load on the API server [1]. - API server dependency: While commonly used for the local API server (e.g., localhost:6443), the address field is generic and can technically be used to monitor any service endpoint [2]. For additional context on kube-vip configuration, see the official documentation for environment variables [3] and BGP-specific health check details [1].

Citations:


🌐 Web query:

kube-vip vip_routingtable control_plane_health_check_address routing table mode health check official docs

💡 Result:

In kube-vip, Routing Table mode allows the tool to manage virtual IP (VIP) addresses by adding or deleting them directly in the node's routing tables (typically using table ID 198 and protocol ID 248) rather than using dynamic routing protocols like BGP [1][2]. The control_plane_health_check_address functionality, initially designed for BGP mode [3][4], has been extended to support Routing Table mode [5]. This health check mechanism polls a specified URL (e.g., https://localhost:6443/livez) to determine the health of the control plane [3][6]. Key configuration details include: * Health Check Address (control_plane_health_check_address): Set this URL to enable the health check [3][6]. When enabled, kube-vip will not announce or configure the VIP route until the first successful probe [3][4]. If the probe fails consecutively beyond the failure threshold, the route is withdrawn [3][4]. * Thresholds and Timing: * control_plane_health_check_period_seconds: Defaults to 5 seconds [3][6]. * control_plane_health_check_timeout_seconds: Defaults to 3 seconds [3][6]. * control_plane_health_check_failure_threshold: Defaults to 3 consecutive failures before the route is withdrawn [3][6]. * HTTPS Support: Use control_plane_health_check_ca_path to specify the path to a CA certificate if using HTTPS with a private CA [3][6]. * Routing Table Mode Specifics: In Routing Table mode, enabling this health check ensures that the VIP is only managed (present in the routing table) when the polled endpoint is healthy [5]. For Routing Table mode, ensure vip_routingtable is set to true in your configuration [7]. You can also optionally use vip_cleanroutingtable to clear unwanted routes at startup [7]. While BGP mode relies on a routing daemon (like BIRD) to read and advertise these routes to neighbors [7], Routing Table mode simply performs the netlink operations to update the local node's routing table [1].

Citations:


Add the control-plane health gate to the API VIP manifest
templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml should set control_plane_health_check_address (and timeout) like the ingress VIP does; routing-table mode supports this gate, and without it kube-vip can keep advertising the API VIP even when the local apiserver is unhealthy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml` around lines
20 - 46, Add the kube-vip control-plane health gate to the container environment
in the manifest, matching the ingress VIP’s control_plane_health_check_address
and timeout settings while preserving the existing routing-table configuration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same as on the bootstrap manifest: the API VIP is already health-gated by kube-vip's backend check (ServerVersion against the local apiserver every backend_health_check_interval); control_plane_health_check_address is the override used by the ingress pod because routers have no apiserver. See the fuller explanation on the bootstrap-manifest thread.

This reply was written with AI assistance. Please verify before acting on it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@mkowalski I couldn't re-verify this change because repository access failed, so I'm leaving the finding unresolved. Please retry the recheck after sandbox access is restored.


✏️ Learnings added
Learnt from: mkowalski
Repo: openshift/machine-config-operator PR: 6326
File: templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml:20-46
Timestamp: 2026-07-22T15:32:55.850Z
Learning: In openshift/machine-config-operator PR `#6326` BGP VIP static pods, `templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml` already health-gates the API VIP using kube-vip’s `backend_health_check_interval`: with its local API kubeconfig/endpoint configuration, kube-vip probes the local apiserver through `ServerVersion()`. Do not require `control_plane_health_check_address` there. That explicit HTTP health-check override is used by the ingress kube-vip pod because ingress routers do not have a local apiserver for the backend check.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: mkowalski
Repo: openshift/machine-config-operator PR: 6326
File: manifests/on-prem/0000-frr-k8s.yaml:91-131
Timestamp: 2026-07-22T11:15:44.757Z
Learning: For BGP VIP static pods, do not require liveness/readiness probes on the FRR daemon container in `0000-frr-k8s.yaml` (reason: FRR is supervised by `watchfrr`; an unreliable `vtysh`-based probe can restart the container and tear down BGP sessions). In the day-2 FRR static pod template `templates/master/00-master/on-prem/files/0000-frr-k8s.yaml`, ensure probes are provided by the separate controller container via `/healthz` and `/readyz`, not by probing the FRR daemon directly; rely on the CNO-managed metrics companion DaemonSet for externally visible metrics/live status. For the kube-vip container in `0010-kube-vip-api.yaml`, do not add probes; in routing-table mode kube-vip fails safe by withdrawing the VIP route on death, and there is no suitable independent health endpoint to probe.

Comment thread templates/master/00-master/on-prem/files/frr-k8s-peers.yaml Outdated
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== PR description ==='
gh pr view 6326 --repo openshift/machine-config-operator --json body --jq .body

echo '=== Candidate manifest files ==='
fd -t f . manifests templates | rg '(frr-k8s|kube-vip|keepalived)'

echo '=== hostNetwork, SYS_ADMIN, and justification comments ==='
rg -n -i -C 8 '(hostNetwork:|SYS_ADMIN|privileged settings|BGP sessions|routing table|watchfrr|docker-start)' \
  manifests templates

Length of output: 46704


@mkowalski Re-evaluated and confirmed. The static pod manifests and PR description now provide a concrete, appropriately scoped rationale:

  • hostNetwork is required for node-originated BGP sessions and for FRR to advertise health-gated VIP routes from host routing table 198; it also matches the keepalived replacement model.
  • SYS_ADMIN is limited to the FRR container and documented as necessary for docker-start/watchfrr supervision. The container retains allowPrivilegeEscalation: false and a read-only root filesystem.
  • The other containers use narrower capability sets and hardened security contexts.

I’m withdrawing the Container-Privileges finding.


✏️ Learnings added
Learnt from: mkowalski
URL: https://github.com/openshift/machine-config-operator/pull/6326

Timestamp: 2026-07-22T14:31:42.615Z
Learning: For the BGP VIP static pods in `manifests/on-prem/0000-frr-k8s.yaml` and `templates/master/00-master/on-prem/files/0000-frr-k8s.yaml`, `hostNetwork: true` is required because BGP sessions originate from the node IP and FRR advertises health-gated VIP routes from the host routing table. The FRR container requires `SYS_ADMIN` for `docker-start`/`watchfrr` supervision and deliberately cannot use `drop: ALL`, because its privilege-separated startup needs root-implicit capabilities to spawn FRR daemons as the `frr` user.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@mkowalski

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Temporary: vendors the openshift/api#2923 branch (BGPBasedVIPManagement
feature gate, Infrastructure vipManagement, ControllerConfigSpec
BGPVIPPeersJSON) via a module replace. Swapped for the merged module as
soon as openshift/api#2923 lands; every subsequent commit builds against
the identical API surface either way.
When the BareMetal Infrastructure CR requests vipManagement "BGP"
(BGPBasedVIPManagement gate), render the frr-k8s static pod on control
plane nodes and the kube-vip static pods (API VIP on masters, ingress
VIP on every node, keepalived parity) instead of the keepalived
manifests. kube-vip runs in routing table mode: it installs a VIP route
into kernel table 198 only while the local backend health check passes,
and FRR advertises that table, giving per-node health-gated ECMP.

The frr-k8s sockets and config live on a hostPath prepared by a boot
unit (0777 emptyDir-parity for the mixed-uid FRR daemons,
container_file_t for the MCS-confined metrics companion that CNO
deploys against them).

BGP mode additionally requires VIPs to exist: with a user-managed load
balancer there is nothing to advertise and the templates would render
empty values.
Bootstrap: RenderBootstrap reads the installer-generated bgp-vip-config
ConfigMap manifest (--bgp-vip-config-file) and exposes its config.json
as ControllerConfigSpec.BGPVIPPeersJSON, from which the templates render
the node peers file that baremetal-runtimecfg resolves on each node. The
bootstrap node itself runs an FRR-only static pod so the API VIP is
advertised while the control plane forms. When BGP VIP management is
enabled, missing frr-k8s/kube-vip images fail the bootstrap render
instead of dying later with empty image fields.

Day-2: the operator re-reads the same ConfigMap on every sync (new
Role/RoleBinding for openshift-network-operator) so ControllerConfig
follows peer changes; absence degrades the operator rather than
blanking the peers file fleet-wide.

The frr-k8s and kube-vip images resolve from the release payload; the
image-references addition ships separately (payload assembly needs the
kube-vip tag onboarded first).
Split from the previous commit on purpose: nightly payload assembly
fails on an image-references entry whose tag does not exist, so this
lands only after the kube-vip image is onboarded (ART-21663,
openshift/release#81957).
@mkowalski

Copy link
Copy Markdown
Contributor Author

Also addressing the outside-diff comment on frr-k8s-conf.yaml (mode 0644 vs decimal 420): keeping the octal form — the MCO template loader parses YAML 1.1 octal literals and every existing template file in this repo uses that convention (0644/0755/0600 across templates/). frr-peers.json was however tightened to 0600 since it can carry BGP MD5 passwords.

@coderabbitai full review

This comment was written with AI assistance. Please verify before acting on it.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

@mkowalski Full review requested. I’ll evaluate the octal-mode convention and the tightened frr-peers.json permissions as part of the review.


✏️ Learnings added
Learnt from: mkowalski
URL: https://github.com/openshift/machine-config-operator/pull/6326

Timestamp: 2026-07-22T15:32:25.823Z
Learning: In the Machine Config Operator template YAML files, file modes follow YAML 1.1 octal notation (for example, `0644`, `0755`, and `0600`), which the MCO template loader parses correctly. For BGP VIP support, `templates/master/00-master/on-prem/files/frr-k8s-peers.yaml` must render `frr-peers.json` with mode `0600` because its BGP peer configuration can contain MD5 passwords.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
manifests/on-prem/frr-peers.json.tmpl (1)

1-2: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Bootstrap render still writes frr-peers.json as 0644

pkg/operator/bootstrap.go writes this payload with os.WriteFile(..., 0o644), so it does not get the same 0600 hardening as the day-2 file. Make the bootstrap write 0600 too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@manifests/on-prem/frr-peers.json.tmpl` around lines 1 - 2, Update the
bootstrap write for the BGP VIP peers payload in pkg/operator/bootstrap.go to
use file mode 0600 instead of 0644, ensuring the frr-peers.json bootstrap output
matches the day-2 file hardening. Locate the os.WriteFile call handling
BGPVIPPeersJSON and change only its permission mode.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml`:
- Line 18: Update the ExecStart setup in the frr-k8s-hostpath service to remove
world-writable 0777 permissions from the shared sockets and conf directories.
Configure a shared group with 0770 permissions, or equivalent ACLs limited to
the FRR and metrics companion identities, while preserving directory creation
and SELinux labeling.

---

Outside diff comments:
In `@manifests/on-prem/frr-peers.json.tmpl`:
- Around line 1-2: Update the bootstrap write for the BGP VIP peers payload in
pkg/operator/bootstrap.go to use file mode 0600 instead of 0644, ensuring the
frr-peers.json bootstrap output matches the day-2 file hardening. Locate the
os.WriteFile call handling BGPVIPPeersJSON and change only its permission mode.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 71eaad5c-e346-4329-91f9-d91616684fb9

📥 Commits

Reviewing files that changed from the base of the PR and between 9b1afc6 and dfb4e14.

⛔ Files ignored due to path filters (76)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_infrastructure.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_ingress.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_criocredentialproviderconfigs.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_console_01_consoles.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1alpha1/types_clusterapi.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/prototext/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/descfmt/stringer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/text/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/codec_map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/validate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/version/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/proto/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/editions.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (34)
  • cmd/machine-config-operator/bootstrap.go
  • go.mod
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/container-runtime-config/actual.json
  • pkg/controller/container-runtime-config/expected.json
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml
🚧 Files skipped from review as they are similar to previous changes (25)
  • manifests/on-prem/frr-startup-vtysh.conf
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • pkg/controller/container-runtime-config/actual.json
  • install/image-references
  • pkg/controller/container-runtime-config/expected.json
  • manifests/on-prem/frr-startup-daemons
  • pkg/controller/common/helpers.go
  • install/0000_80_machine-config_02_images.configmap.yaml
  • pkg/controller/template/constants.go
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • pkg/controller/common/images.go
  • install/0000_80_machine-config_00_rbac.yaml
  • pkg/operator/render_test.go
  • cmd/machine-config-operator/bootstrap.go
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • manifests/on-prem/0000-frr-k8s.yaml
  • pkg/operator/bootstrap_test.go
  • go.mod
  • pkg/operator/render.go
  • pkg/operator/sync.go
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go

@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@mkowalski: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/okd-scos-images dfb4e14 link true /test okd-scos-images
ci/prow/images dfb4e14 link true /test images
ci/prow/bootstrap-unit dfb4e14 link true /test bootstrap-unit

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.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

@mkowalski Full review requested. I’ll verify the template file-mode convention and the frr-peers.json permission tightening along with the complete PR changes.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml (1)

18-18: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Restrict the shared FRR directories.

Line 18 makes both runtime directories world-writable. This permits tampering with FRR sockets/configuration, including configuration that can contain BGP peer passwords. Preserve companion access with explicit shared ownership/ACLs and restrictive modes instead of 0777.

#!/bin/bash
set -euo pipefail

rg -n -C 4 '/run/frr-k8s/(sockets|conf)|runAsUser|runAsGroup|fsGroup|frr.conf.tmpl|frr-peers.json' \
  templates manifests -g '*.yaml' -g '*.yml'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml` at
line 18, Restrict the /run/frr-k8s/sockets and /run/frr-k8s/conf directories in
the ExecStart command instead of applying 0777. Preserve access for the FRR
companion processes by using the established shared group/ACL configuration and
restrictive directory modes, ensuring configuration and socket contents are not
writable by everyone.
🧹 Nitpick comments (2)
pkg/operator/bootstrap.go (1)

249-294: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider comparing against the typed constant instead of a literal string.

vipManagement == "BGP" (line 273) duplicates the value already expressed by configv1.VIPManagementTypeBGP (used to set vipManagement a few lines earlier at line 175). Using the constant on both sides avoids silent drift if the underlying value ever changes.

♻️ Proposed refactor
-	if lbType == configv1.LoadBalancerTypeOpenShiftManagedDefault || lbType == "" {
-		if vipManagement == "BGP" {
+	if lbType == configv1.LoadBalancerTypeOpenShiftManagedDefault || lbType == "" {
+		if vipManagement == configv1.VIPManagementTypeBGP {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/bootstrap.go` around lines 249 - 294, Update the VIP management
comparison in getPlatformManifests to use configv1.VIPManagementTypeBGP instead
of the literal "BGP", preserving the existing BGP and non-BGP manifest-selection
behavior.
pkg/controller/template/render_test.go (1)

599-743: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage for isBGPVIPManagement; consider also covering the nil-IP-list fix directly.

The table-driven test thoroughly covers nil infra, nil/empty platform status, BGP with/without VIPs, Keepalived, and non-BareMetal platforms. However, none of the cases exercise onPremPlatformIngressIP/onPremPlatformAPIServerInternalIP directly for the new empty-slice guard added in render.go (Lines 501-513, 526-528, 573-585, 598-600) — that behavior change (returning nil instead of panicking on IngressIPs[0]) is only indirectly implied here. Consider adding a small test rendering {{ onPremPlatformIngressIP . }} against a BareMetal status with empty IngressIPs to lock in the fix.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/controller/template/render_test.go` around lines 599 - 743, Add a focused
test for onPremPlatformIngressIP that renders the template with a BareMetal
platform status whose IngressIPs slice is empty, and assert it returns the
expected nil-safe result without an error or panic. Anchor the new case to the
existing renderTemplate test setup and, if appropriate, add the analogous
coverage for onPremPlatformAPIServerInternalIP.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Line 3: Update the go directive in go.mod from Go 1.26.0 to at least Go
1.26.5, ensuring the repository uses a patched Go 1.26 toolchain; alternatively,
add an equivalent newer toolchain pin in the project’s CI configuration.

In `@pkg/operator/bootstrap.go`:
- Around line 115-123: Extend the BGP validation guard in buildSpec, alongside
the existing imgs.FRRK8s and imgs.KubeVip checks, to reject an empty
dependencies.BGPVIPPeersJSON when
ctrlcommon.IsBGPVIPManagement(dependencies.Infrastructure) is true. Return a
descriptive error identifying the missing BGP VIP peers payload, while
preserving the current validation behavior for non-BGP configurations.

---

Duplicate comments:
In `@templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml`:
- Line 18: Restrict the /run/frr-k8s/sockets and /run/frr-k8s/conf directories
in the ExecStart command instead of applying 0777. Preserve access for the FRR
companion processes by using the established shared group/ACL configuration and
restrictive directory modes, ensuring configuration and socket contents are not
writable by everyone.

---

Nitpick comments:
In `@pkg/controller/template/render_test.go`:
- Around line 599-743: Add a focused test for onPremPlatformIngressIP that
renders the template with a BareMetal platform status whose IngressIPs slice is
empty, and assert it returns the expected nil-safe result without an error or
panic. Anchor the new case to the existing renderTemplate test setup and, if
appropriate, add the analogous coverage for onPremPlatformAPIServerInternalIP.

In `@pkg/operator/bootstrap.go`:
- Around line 249-294: Update the VIP management comparison in
getPlatformManifests to use configv1.VIPManagementTypeBGP instead of the literal
"BGP", preserving the existing BGP and non-BGP manifest-selection behavior.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c0c3a62b-891b-4fd8-9cc1-5d6061a65a03

📥 Commits

Reviewing files that changed from the base of the PR and between 58108b0 and dfb4e14.

⛔ Files ignored due to path filters (76)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_infrastructure.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_ingress.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_criocredentialproviderconfigs.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_console_01_consoles.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1alpha1/types_clusterapi.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/prototext/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/descfmt/stringer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/text/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/codec_map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/validate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/version/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/proto/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/editions.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (34)
  • cmd/machine-config-operator/bootstrap.go
  • go.mod
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/container-runtime-config/actual.json
  • pkg/controller/container-runtime-config/expected.json
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml

Comment thread go.mod
module github.com/openshift/machine-config-operator

go 1.25.3
go 1.26.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n --hidden \
  -g 'go.mod' -g 'go.work' -g 'Dockerfile*' -g '*.yml' -g '*.yaml' -g 'Makefile' \
  'go1\.26|GO_VERSION|golang:' .

Repository: openshift/machine-config-operator

Length of output: 2936


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== go.mod ==\n'
cat -n go.mod

printf '\n== go toolchain / version directives in repo ==\n'
rg -n --hidden --glob '!vendor/**' '^[[:space:]]*(toolchain|go)[[:space:]]' go.mod go.work .github . || true

printf '\n== CI Go version pins ==\n'
rg -n --hidden --glob '!vendor/**' 'go-version|GO_VERSION|golang:' .github . || true

Repository: openshift/machine-config-operator

Length of output: 38773


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== workflow files ==\n'
fd -t f '.*\.(yml|yaml)$' .github 2>/dev/null || true

printf '\n== setup-go / toolchain references ==\n'
rg -n --hidden --glob '!vendor/**' --glob '.github/**/*.yml' --glob '.github/**/*.yaml' \
  'setup-go|go-version|toolchain|GOTOOLCHAIN|golang:' .github . || true

Repository: openshift/machine-config-operator

Length of output: 232


🌐 Web query:

Go 1.26.5 release notes security fixes July 7 2026

💡 Result:

Go 1.26.5 was released on July 7, 2026 [1][2]. This minor point release includes two critical security fixes along with various bug fixes for the compiler, runtime, go command, and several standard library packages [1][3]. The two security vulnerabilities addressed in this release are: 1. os: Root escape via symlink plus trailing slash (CVE-2026-39822) On Unix systems, the os.Root functionality improperly followed symbolic links to locations outside the intended root directory when the final path component was a symbolic link and the path ended with a trailing slash [2][4]. This failure to account for openat behavior with trailing slashes allowed paths to escape the root. The issue has been resolved by properly sanitizing the path parameter [4][5]. 2. crypto/tls: Encrypted Client Hello privacy leak (CVE-2026-42505) The Encrypted Client Hello (ECH) implementation leaked pre-shared key (PSK) identities during the handshake [2][6]. This vulnerability could allow a passive network observer to de-anonymize the server's hostname even when ECH was in use [4][5]. Additional updates in Go 1.26.5 include bug fixes for the compiler, runtime, the go command, and the net, os, and syscall packages [1][3]. Detailed technical changes can be found in the official Go release history [1][7].

Citations:


Pin a patched Go toolchain. go 1.26.0 leaves this repo on the initial 1.26 release, and there’s no toolchain or CI version pin here. Bump to at least go 1.26.5 or enforce a newer toolchain in CI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@go.mod` at line 3, Update the go directive in go.mod from Go 1.26.0 to at
least Go 1.26.5, ensuring the repository uses a patched Go 1.26 toolchain;
alternatively, add an equivalent newer toolchain pin in the project’s CI
configuration.

Comment thread pkg/operator/bootstrap.go
Comment on lines +115 to +123
// BGP-based VIP management renders frr-k8s and kube-vip static pods at
// bootstrap; without their images the manifests would carry empty image
// fields and the install dies much later with no useful signal.
if ctrlcommon.IsBGPVIPManagement(dependencies.Infrastructure) {
if imgs.FRRK8s == "" || imgs.KubeVip == "" {
return nil, fmt.Errorf("BGP-based VIP management is enabled but the frr-k8s (%q) or kube-vip (%q) image is missing from the release payload", imgs.FRRK8s, imgs.KubeVip)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

BGP bootstrap doesn't hard-fail on an empty peers payload, unlike the adjacent image check.

buildSpec requires imgs.FRRK8s/imgs.KubeVip to be non-empty when BGP VIP management is active, but doesn't apply the same guard to dependencies.BGPVIPPeersJSON. fillBGPVIPConfig in pkg/operator/bootstrap_dependencies.go tolerates a missing bgp-vip-config file unconditionally — it never checks whether BGP is actually enabled on the infrastructure before deciding absence is fine. If the file is missing while BGP is enabled (wrong --bgp-vip-config-file path, installer ordering issue, etc.), spec.BGPVIPPeersJSON stays empty, and manifests/on-prem/frr-peers.json.tmpl ({{- .ControllerConfig.BGPVIPPeersJSON -}}) silently renders an empty peers file — the FRR static pod comes up with no configured peers instead of the bootstrap failing loudly, the same failure mode the image check right above was added to prevent. TestBuildSpecBGPImageValidation doesn't cover this case either.

🐛 Proposed fix: extend the existing BGP guard to cover the peers payload
 	if ctrlcommon.IsBGPVIPManagement(dependencies.Infrastructure) {
 		if imgs.FRRK8s == "" || imgs.KubeVip == "" {
 			return nil, fmt.Errorf("BGP-based VIP management is enabled but the frr-k8s (%q) or kube-vip (%q) image is missing from the release payload", imgs.FRRK8s, imgs.KubeVip)
 		}
+		if dependencies.BGPVIPPeersJSON == "" {
+			return nil, fmt.Errorf("BGP-based VIP management is enabled but no BGP VIP peers configuration (bgp-vip-config ConfigMap) was found")
+		}
 	}

Also applies to: 142-142

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/bootstrap.go` around lines 115 - 123, Extend the BGP validation
guard in buildSpec, alongside the existing imgs.FRRK8s and imgs.KubeVip checks,
to reject an empty dependencies.BGPVIPPeersJSON when
ctrlcommon.IsBGPVIPManagement(dependencies.Infrastructure) is true. Return a
descriptive error identifying the missing BGP VIP peers payload, while
preserving the current validation behavior for non-BGP configurations.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
pkg/operator/bootstrap.go (1)

118-122: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

BGP bootstrap still doesn't hard-fail on an empty peers payload.

The guard validates imgs.FRRK8s/imgs.KubeVip but not dependencies.BGPVIPPeersJSON. If BGP is genuinely enabled (VIPs present) but the peers ConfigMap/file is missing, spec.BGPVIPPeersJSON stays empty and frr-peers.json.tmpl silently renders no peers instead of failing bootstrap loudly — the same failure mode the image check was added to prevent.

🐛 Proposed fix
 	if ctrlcommon.IsBGPVIPManagement(dependencies.Infrastructure) {
 		if imgs.FRRK8s == "" || imgs.KubeVip == "" {
 			return nil, fmt.Errorf("BGP-based VIP management is enabled but the frr-k8s (%q) or kube-vip (%q) image is missing from the release payload", imgs.FRRK8s, imgs.KubeVip)
 		}
+		if dependencies.BGPVIPPeersJSON == "" {
+			return nil, fmt.Errorf("BGP-based VIP management is enabled but no BGP VIP peers configuration (bgp-vip-config ConfigMap) was found")
+		}
 	}

Also applies to: 142-142

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/bootstrap.go` around lines 118 - 122, The BGP validation in the
bootstrap flow must also reject a missing peers payload. Within the
ctrlcommon.IsBGPVIPManagement guard, validate dependencies.BGPVIPPeersJSON
alongside imgs.FRRK8s and imgs.KubeVip, returning the existing bootstrap error
path when it is empty so frr-peers.json.tmpl cannot render without peers.
🧹 Nitpick comments (1)
pkg/operator/bootstrap.go (1)

249-293: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer the typed constant over a raw string literal.

if vipManagement == "BGP" works today but drifts from configv1.VIPManagementTypeBGP used in helpers.go and render.go; using the constant avoids future typos if more VIPManagementType values are added.

-		if vipManagement == "BGP" {
+		if vipManagement == configv1.VIPManagementTypeBGP {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/bootstrap.go` around lines 249 - 293, Update the vipManagement
comparison in getPlatformManifests to use the typed
configv1.VIPManagementTypeBGP constant instead of the raw "BGP" string,
preserving the existing BGP manifest-selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Line 425: Update the google.golang.org/protobuf dependency in go.mod from the
unreleased pseudo-version to an available tagged release; only retain the
pseudo-version if this specific commit is required, and document that temporary
exception.

In `@pkg/controller/template/render_test.go`:
- Around line 663-675: The render test suite is missing coverage for ingress
VIPs being present while the API VIP is absent. Add a case alongside the
existing baremetal VIPManagement BGP cases in the relevant test table,
configuring ingress VIPs without APIServerInternalIPs and asserting the result
remains "false", thereby preserving the APIServerInternalIPs guard.

In `@templates/master/00-master/on-prem/files/frr-k8s-conf.yaml`:
- Around line 1-17: Change the mode for the rendered FRR configuration in the
manifest entry containing frr.conf.tmpl from 0644 to 0600, keeping the existing
path and contents unchanged so BGP peer passwords remain readable only by the
owning user.

---

Duplicate comments:
In `@pkg/operator/bootstrap.go`:
- Around line 118-122: The BGP validation in the bootstrap flow must also reject
a missing peers payload. Within the ctrlcommon.IsBGPVIPManagement guard,
validate dependencies.BGPVIPPeersJSON alongside imgs.FRRK8s and imgs.KubeVip,
returning the existing bootstrap error path when it is empty so
frr-peers.json.tmpl cannot render without peers.

---

Nitpick comments:
In `@pkg/operator/bootstrap.go`:
- Around line 249-293: Update the vipManagement comparison in
getPlatformManifests to use the typed configv1.VIPManagementTypeBGP constant
instead of the raw "BGP" string, preserving the existing BGP manifest-selection
behavior.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c0c3a62b-891b-4fd8-9cc1-5d6061a65a03

📥 Commits

Reviewing files that changed from the base of the PR and between 58108b0 and dfb4e14.

⛔ Files ignored due to path filters (76)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_infrastructure.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_ingress.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_criocredentialproviderconfigs.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/machineconfiguration/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_console_01_consoles.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1alpha1/types_clusterapi.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/encoding/prototext/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/descfmt/stringer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/encoding/text/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/codec_map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/impl/validate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/version/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/proto/decode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/editions.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (34)
  • cmd/machine-config-operator/bootstrap.go
  • go.mod
  • install/0000_80_machine-config_00_rbac.yaml
  • install/0000_80_machine-config_02_images.configmap.yaml
  • install/image-references
  • manifests/on-prem/0000-frr-k8s.yaml
  • manifests/on-prem/0010-kube-vip-api.yaml
  • manifests/on-prem/frr-peers.json.tmpl
  • manifests/on-prem/frr-startup-daemons
  • manifests/on-prem/frr-startup-vtysh.conf
  • manifests/on-prem/frr.conf.tmpl
  • pkg/controller/common/helpers.go
  • pkg/controller/common/images.go
  • pkg/controller/container-runtime-config/actual.json
  • pkg/controller/container-runtime-config/expected.json
  • pkg/controller/template/constants.go
  • pkg/controller/template/render.go
  • pkg/controller/template/render_test.go
  • pkg/operator/bootstrap.go
  • pkg/operator/bootstrap_dependencies.go
  • pkg/operator/bootstrap_test.go
  • pkg/operator/render.go
  • pkg/operator/render_test.go
  • pkg/operator/sync.go
  • pkg/operator/sync_test.go
  • templates/common/on-prem/files/0020-kube-vip-ingress.yaml
  • templates/common/on-prem/files/keepalived.yaml
  • templates/master/00-master/on-prem/files/0000-frr-k8s.yaml
  • templates/master/00-master/on-prem/files/0010-kube-vip-api.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-conf.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-peers.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-daemons.yaml
  • templates/master/00-master/on-prem/files/frr-k8s-startup-vtysh.yaml
  • templates/master/00-master/on-prem/units/frr-k8s-hostpath.service.yaml

Comment thread go.mod
golang.org/x/text v0.40.0 // indirect
golang.org/x/tools v0.47.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
go list -m -json google.golang.org/protobuf
go mod graph | rg 'google\.golang\.org/protobuf'
git ls-remote --tags https://github.com/protocolbuffers/protobuf-go.git 'v1.36.*'

Repository: openshift/machine-config-operator

Length of output: 8699


Avoid the protobuf pseudo-version google.golang.org/protobuf is pinned to unreleased v1.36.12-0.20260120151049-f2248ac996af with no matching tagged v1.36.12 release. Switch to a tagged version, or document a temporary exception if this commit is required.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@go.mod` at line 425, Update the google.golang.org/protobuf dependency in
go.mod from the unreleased pseudo-version to an available tagged release; only
retain the pseudo-version if this specific commit is required, and document that
temporary exception.

Source: Path instructions

Comment on lines +663 to +675
name: "baremetal with VIPManagement BGP but no ingress VIPs",
infra: &configv1.Infrastructure{
Status: configv1.InfrastructureStatus{
PlatformStatus: &configv1.PlatformStatus{
Type: configv1.BareMetalPlatformType,
BareMetal: &configv1.BareMetalPlatformStatus{
VIPManagement: "BGP",
APIServerInternalIPs: []string{"192.168.111.5"},
},
},
},
},
result: "false",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover the missing API-VIP branch. The suite tests absent ingress VIPs but not ingress-present/API-absent. Add that case so a regression removing the APIServerInternalIPs guard cannot enable BGP rendering without an API VIP.

Proposed test case
+		{
+			name: "baremetal with VIPManagement BGP but no API VIPs",
+			infra: &configv1.Infrastructure{
+				Status: configv1.InfrastructureStatus{
+					PlatformStatus: &configv1.PlatformStatus{
+						Type: configv1.BareMetalPlatformType,
+						BareMetal: &configv1.BareMetalPlatformStatus{
+							VIPManagement: "BGP",
+							IngressIPs:    []string{"192.168.111.4"},
+						},
+					},
+				},
+			},
+			result: "false",
+		},
📝 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
name: "baremetal with VIPManagement BGP but no ingress VIPs",
infra: &configv1.Infrastructure{
Status: configv1.InfrastructureStatus{
PlatformStatus: &configv1.PlatformStatus{
Type: configv1.BareMetalPlatformType,
BareMetal: &configv1.BareMetalPlatformStatus{
VIPManagement: "BGP",
APIServerInternalIPs: []string{"192.168.111.5"},
},
},
},
},
result: "false",
name: "baremetal with VIPManagement BGP but no ingress VIPs",
infra: &configv1.Infrastructure{
Status: configv1.InfrastructureStatus{
PlatformStatus: &configv1.PlatformStatus{
Type: configv1.BareMetalPlatformType,
BareMetal: &configv1.BareMetalPlatformStatus{
VIPManagement: "BGP",
APIServerInternalIPs: []string{"192.168.111.5"},
},
},
},
},
result: "false",
},
{
name: "baremetal with VIPManagement BGP but no API VIPs",
infra: &configv1.Infrastructure{
Status: configv1.InfrastructureStatus{
PlatformStatus: &configv1.PlatformStatus{
Type: configv1.BareMetalPlatformType,
BareMetal: &configv1.BareMetalPlatformStatus{
VIPManagement: "BGP",
IngressIPs: []string{"192.168.111.4"},
},
},
},
},
result: "false",
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/controller/template/render_test.go` around lines 663 - 675, The render
test suite is missing coverage for ingress VIPs being present while the API VIP
is absent. Add a case alongside the existing baremetal VIPManagement BGP cases
in the relevant test table, configuring ingress VIPs without
APIServerInternalIPs and asserting the result remains "false", thereby
preserving the APIServerInternalIPs guard.

Comment on lines +1 to +17
mode: 0644
path: "/etc/kubernetes/static-pod-resources/frr-k8s/frr.conf.tmpl"
contents:
inline: |
frr version 9.1
frr defaults traditional
hostname {{`{{.Hostname}}`}}
!
router bgp {{`{{.LocalASN}}`}}
bgp router-id {{`{{.RouterID}}`}}
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
!
{{`{{- range .Peers}}`}}
neighbor {{`{{.PeerAddress}}`}} remote-as {{`{{.PeerASN}}`}}
{{`{{- if .Password}}`}}
neighbor {{`{{.PeerAddress}}`}} password {{`{{.Password}}`}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Restrict the rendered FRR configuration.

This file renders peer passwords on Line 17 but is written as 0644; use 0600 so local non-root users cannot read BGP credentials.

Proposed fix
-mode: 0644
+mode: 0600

Based on learnings, sensitive rendered content should use restrictive mode 0600.

📝 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
mode: 0644
path: "/etc/kubernetes/static-pod-resources/frr-k8s/frr.conf.tmpl"
contents:
inline: |
frr version 9.1
frr defaults traditional
hostname {{`{{.Hostname}}`}}
!
router bgp {{`{{.LocalASN}}`}}
bgp router-id {{`{{.RouterID}}`}}
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
!
{{`{{- range .Peers}}`}}
neighbor {{`{{.PeerAddress}}`}} remote-as {{`{{.PeerASN}}`}}
{{`{{- if .Password}}`}}
neighbor {{`{{.PeerAddress}}`}} password {{`{{.Password}}`}}
mode: 0600
path: "/etc/kubernetes/static-pod-resources/frr-k8s/frr.conf.tmpl"
contents:
inline: |
frr version 9.1
frr defaults traditional
hostname {{`{{.Hostname}}`}}
!
router bgp {{`{{.LocalASN}}`}}
bgp router-id {{`{{.RouterID}}`}}
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
!
{{`{{- range .Peers}}`}}
neighbor {{`{{.PeerAddress}}`}} remote-as {{`{{.PeerASN}}`}}
{{`{{- if .Password}}`}}
neighbor {{`{{.PeerAddress}}`}} password {{`{{.Password}}`}}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@templates/master/00-master/on-prem/files/frr-k8s-conf.yaml` around lines 1 -
17, Change the mode for the rendered FRR configuration in the manifest entry
containing frr.conf.tmpl from 0644 to 0600, keeping the existing path and
contents unchanged so BGP peer passwords remain readable only by the owning
user.

Source: Learnings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants