Skip to content

OPNET-781: Add BGP VIP management support - #10718

Open
mkowalski wants to merge 7 commits into
openshift:mainfrom
mkowalski:opnet-781-bgp-vip
Open

OPNET-781: Add BGP VIP management support#10718
mkowalski wants to merge 7 commits into
openshift:mainfrom
mkowalski:opnet-781-bgp-vip

Conversation

@mkowalski

@mkowalski mkowalski commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What

Installer side of BGP-based VIP management for baremetal
(enhancement #1982, OPNET-773; API merged in
openshift/api#2923, already vendored on main via #10713). Adds platform.baremetal.bgpVIPConfig
to the install-config: when set, the cluster's API/ingress VIPs are advertised via BGP (kube-vip
routing-table mode + frr-k8s static pods, rendered by MCO) instead of managed by keepalived/VRRP.

Seven commits:

  1. validation and feature gatebgpVIPConfig is only accepted with the
    BGPBasedVIPManagement gate (DevPreviewNoUpgrade); invalid ASNs/peer addresses rejected at
    install-config validation
  2. BGPVIPConfig/BGPPeerConfig types — localASN, peers (address, ASN, optional password, BFD,
    eBGP multihop, timers), communities, per-host overrides
  3. Infrastructure CR — sets status.platformStatus.baremetal.vipManagement: BGP (immutable
    once set, per the API's CEL) so MCO/CNO select the BGP rendering path
  4. bgp-vip-config ConfigMap — installer-generated handover artifact consumed by MCO's
    bootstrap render and CNO's FRRConfiguration rendering
  5. schema alignment — the ConfigMap's config.json matches baremetal-runtimecfg's
    FRRPeerMapping exactly (one schema end to end; frr-peers.json == config.json)
  6. FRR routing capability — enables additionalRoutingCapabilities.providers: [FRR] on the
    operator Network CR when bgpVIPConfig is set (ships the FRRConfiguration CRD; without it CNO
    degrades)
  7. negative test — no bgpVIPConfig → no CR changes (regression guard for every existing
    baremetal install)

Inert without the feature gate and the new install-config section: no vendoring changes (the API
is already on main), no behavior change for existing installs.

Companions

Testing

Unit tests included (validation, manifest generation, negative case). Validated end-to-end on
dev-scripts baremetal IPI clusters (3 masters + 2 workers, dual VIP): API VIP ECMP from all
masters, ingress VIP ECMP from router-bearing workers, health-gated withdrawal, bootstrap-to-CRD
handover on every install. Note: pkg/asset/installconfig/vsphere unit tests currently fail on
untouched main (post-#10713 fallout), unrelated to this change.


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

Summary by CodeRabbit

  • New Features
    • Added BGP-based VIP advertisement for bare-metal installs, including local ASN, global peers, optional communities, and per-host peer overrides.
    • Generates a dedicated runtime configuration ConfigMap and enables FRR routing capabilities for OVN-Kubernetes.
  • Bug Fixes
    • Reports BGP VIP management in cluster platform status when configured.
  • Tests
    • Added unit tests for ConfigMap runtime JSON schema, OVN/FRR behavior, and BGP VIP validation rules (feature gate, host overrides, and peer constraints).

@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 28, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

@mkowalski: This pull request references OPNET-781 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

Installer side of BGP-based VIP management for baremetal
(enhancement #1982, OPNET-773; API merged in
openshift/api#2923, already vendored on main via #10713). Adds platform.baremetal.bgpVIPConfig
to the install-config: when set, the cluster's API/ingress VIPs are advertised via BGP (kube-vip
routing-table mode + frr-k8s static pods, rendered by MCO) instead of managed by keepalived/VRRP.

Seven commits:

  1. validation and feature gatebgpVIPConfig is only accepted with the
    BGPBasedVIPManagement gate (DevPreviewNoUpgrade); invalid ASNs/peer addresses rejected at
    install-config validation
  2. BGPVIPConfig/BGPPeerConfig types — localASN, peers (address, ASN, optional password, BFD,
    eBGP multihop, timers), communities, per-host overrides
  3. Infrastructure CR — sets status.platformStatus.baremetal.vipManagement: BGP (immutable
    once set, per the API's CEL) so MCO/CNO select the BGP rendering path
  4. bgp-vip-config ConfigMap — installer-generated handover artifact consumed by MCO's
    bootstrap render and CNO's FRRConfiguration rendering
  5. schema alignment — the ConfigMap's config.json matches baremetal-runtimecfg's
    FRRPeerMapping exactly (one schema end to end; frr-peers.json == config.json)
  6. FRR routing capability — enables additionalRoutingCapabilities.providers: [FRR] on the
    operator Network CR when bgpVIPConfig is set (ships the FRRConfiguration CRD; without it CNO
    degrades)
  7. negative test — no bgpVIPConfig → no CR changes (regression guard for every existing
    baremetal install)

Inert without the feature gate and the new install-config section: no vendoring changes (the API
is already on main), no behavior change for existing installs.

Companions

Testing

Unit tests included (validation, manifest generation, negative case). Validated end-to-end on
dev-scripts baremetal IPI clusters (3 masters + 2 workers, dual VIP): API VIP ECMP from all
masters, ingress VIP ECMP from router-bearing workers, health-gated withdrawal, bootstrap-to-CRD
handover on every install. Note: pkg/asset/installconfig/vsphere unit tests currently fail on
untouched main (post-#10713 fallout), unrelated to this change.


This PR 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.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Changes

BGP VIP management

Layer / File(s) Summary
Configuration types and validation
pkg/types/baremetal/platform.go, pkg/types/baremetal/validation/*
Adds BGP VIP and peer configuration types, host overrides, feature gating, OVN-Kubernetes requirements, and validation for ASN, peer count, addresses, ports, communities, durations, and boolean flags.
Runtime ConfigMap generation
pkg/asset/manifests/bgpvipconfig.go, pkg/asset/manifests/bgpvipconfig_test.go
Builds runtimecfg-compatible JSON, includes host peer overrides, embeds it in a Kubernetes ConfigMap, renders the asset, and verifies the generated schema.
Manifest and network integration
pkg/asset/manifests/infrastructure.go, pkg/asset/manifests/network.go, pkg/asset/manifests/network_test.go, pkg/asset/manifests/operators.go
Reports BGP VIP management for bare metal, enables FRR for supported OVN-Kubernetes configurations, and adds the ConfigMap to generated operator manifests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: approved, lgtm, verified


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
No-Weak-Crypto ❌ Error The PR adds a BGPPeerConfig.Password for TCP MD5 signature auth, explicitly introducing MD5 usage. Avoid MD5-based auth or gate it behind a stronger, approved mechanism; remove the field or rename/scope it if it must remain non-cryptographic.
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding BGP-based VIP management support for bare-metal clusters.
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 All added/changed test titles are fixed string literals; no dynamic data or generated identifiers appear in names.
Test Structure And Quality ✅ Passed PASS: These are plain unit tests; each subtest targets one behavior, and there are no cluster resources, waits, or cleanup gaps to flag.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the new tests are standard Go unit tests using testing.T and do not hit MicroShift-unsupported OpenShift APIs.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the changed tests are unit tests and don’t assume multi-node topology.
Topology-Aware Scheduling Compatibility ✅ Passed The diff only adds BGP VIP config/validation and a CNO routing capability flag; it introduces no new anti-affinity, topology-spread, nodeSelector, PDB, or replica assumptions.
Ote Binary Stdout Contract ✅ Passed Changed files add library code and ordinary tests only; no main/init/TestMain/BeforeSuite stdout writes were introduced.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the changed tests are unit tests only, with no external connectivity or IPv6-specific test harness issues.
Container-Privileges ✅ Passed Changed files only add a ConfigMap, Network CR updates, and validation/types; no privileged/hostPID/hostNetwork/hostIPC/SYS_ADMIN/allowPrivilegeEscalation fields appear in touched manifests.
No-Sensitive-Data-In-Logs ✅ Passed The BGP VIP changes add no new log statements; searches found only pre-existing, unrelated logrus calls and no logging of passwords/tokens/PII.
✨ 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.

🔧 golangci-lint (2.12.2)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


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

@openshift-ci
openshift-ci Bot requested review from dtantsur and sadasu July 28, 2026 07:43
@openshift-ci

openshift-ci Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign rvanderp3 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

@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

🤖 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 `@pkg/asset/manifests/bgpvipconfig.go`:
- Around line 134-137: Implement BGPVIPConfigMap.Load using the provided
asset.FileFetcher to read the already-rendered manifest, populate the asset’s
ConfigMap and File fields, and return the appropriate loaded status and errors
instead of always returning (false, nil). Add test coverage for restoring the
writable asset from disk.
- Around line 76-110: Update the BGP VIP manifest generation around
bgpVIPConfigJSON and hostOverrides so BGPPeerConfig.Password is never serialized
into config.json or stored in the ConfigMap. Use the existing secret-backed
mechanism for any required BGP peer credentials, and remove or avoid MD5-based
authentication material; flag any remaining MD5 usage according to project
guidelines.

In `@pkg/asset/manifests/network.go`:
- Around line 149-157: Update platform validation to reject bare-metal
configurations that set BGPVIPConfig when the selected network type is not
OVNKubernetes. In the baremetal branch of the manifest generation logic around
ovnNetworkOperatorConfig, retain an explicit OVNKubernetes guard before creating
the OVN configuration, and add a regression test covering the rejected
combination.

In `@pkg/types/baremetal/validation/platform.go`:
- Around line 595-617: Update validateBGPPeer to validate peer.Port when it is
nonzero, rejecting values outside the inclusive range 1..65535 while allowing
zero to remain omitted and default to port 179. Add the validation error using
the existing field.ErrorList pattern and the peer port field path.
- Around line 530-535: Update the host iteration in the platform validation flow
to check whether each host is nil before accessing host.BGPPeers. Skip nil hosts
while preserving existing validation for non-nil hosts and their BGP peers,
consistent with the ConfigMap generator’s 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 YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 447449cb-06c3-41a5-a789-05d6e9f36f68

📥 Commits

Reviewing files that changed from the base of the PR and between 25d6f5e and cb75feb.

⛔ Files ignored due to path filters (1)
  • pkg/types/baremetal/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (9)
  • pkg/asset/manifests/bgpvipconfig.go
  • pkg/asset/manifests/bgpvipconfig_test.go
  • pkg/asset/manifests/infrastructure.go
  • pkg/asset/manifests/network.go
  • pkg/asset/manifests/network_test.go
  • pkg/asset/manifests/operators.go
  • pkg/types/baremetal/platform.go
  • pkg/types/baremetal/validation/featuregates.go
  • pkg/types/baremetal/validation/platform.go

Comment on lines +76 to +110
configData := bgpVIPConfigJSON{
LocalASN: bgpConfig.LocalASN,
DefaultPeers: bgpConfig.Peers,
Communities: bgpConfig.Communities,
APIVIPs: bm.APIVIPs,
IngressVIPs: bm.IngressVIPs,
}

// Collect per-host BGP peer overrides.
hostOverrides := make(map[string][]baremetal.BGPPeerConfig)
for _, host := range bm.Hosts {
if host != nil && len(host.BGPPeers) > 0 {
hostOverrides[host.Name] = host.BGPPeers
}
}
if len(hostOverrides) > 0 {
configData.HostOverrides = hostOverrides
}

jsonBytes, err := json.Marshal(configData)
if err != nil {
return errors.Wrap(err, "failed to marshal BGP VIP config JSON")
}

cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: bgpVIPConfigMapNamespace,
Name: bgpVIPConfigMapName,
},
Data: map[string]string{
bgpVIPConfigMapDataKey: string(jsonBytes),

@coderabbitai coderabbitai Bot Jul 28, 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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not render BGP credentials into a ConfigMap.

BGPPeerConfig.Password is marshaled into config.json, then published in a ConfigMap. This exposes BGP session credentials in rendered manifests and implements the newly added MD5-based authentication model. Use a secret-backed mechanism and avoid MD5 authentication material.

As per coding guidelines, flag MD5 usage.

🤖 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/asset/manifests/bgpvipconfig.go` around lines 76 - 110, Update the BGP
VIP manifest generation around bgpVIPConfigJSON and hostOverrides so
BGPPeerConfig.Password is never serialized into config.json or stored in the
ConfigMap. Use the existing secret-backed mechanism for any required BGP peer
credentials, and remove or avoid MD5-based authentication material; flag any
remaining MD5 usage according to project guidelines.

Source: Coding guidelines

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.

Known DevPreview limitation, deliberate for now: the password is BGP TCP-MD5 session authentication (RFC 2385) — the hash is mandated by the BGP protocol option itself, not a choice of ours — and the whole config flows installer → ConfigMap → MCO/CNO as one schema. Moving it to a Secret requires the full chain (installer generates the Secret, MCO bootstrap render and CNO FRRConfiguration consume passwordSecret references) and is planned alongside the TechPreview structured API; the CNO side documents the same limitation (cluster-network-operator#3047, docs/bgp_vip_management.md). Splitting just the installer side now would leave mixed sources without removing the exposure.

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.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Relevant installer symbols ==='
ast-grep outline pkg/types/baremetal/platform.go --items all --match 'BGPPeerConfig|BGPVIPConfig|Host|Platform' --view expanded
ast-grep outline pkg/asset/manifests/bgpvipconfig.go --items all --match 'bgpVIPConfigJSON|BGPVIPConfigMap' --view expanded

printf '%s\n' '=== BGP fields and serialization ==='
rg -n -A18 -B4 'type BGPPeerConfig|type BGPVIPConfig|BGPPeers|BGPVIPConfig|json\.Marshal|hostOverrides' \
  pkg/types/baremetal/platform.go pkg/asset/manifests/bgpvipconfig.go pkg/asset/manifests/bgpvipconfig_test.go

printf '%s\n' '=== In-repository BGP VIP documentation/references ==='
rg -n -i -C3 'BGPBasedVIPManagement|BGP VIP|bgpVIPConfig|passwordSecret|TCP-MD5|RFC 2385|bgp_vip_management' \
  README.md docs pkg data cmd 2>/dev/null || true

printf '%s\n' '=== Referenced CNO item metadata ==='
gh api repos/openshift/cluster-network-operator/issues/3047 \
  --jq '{number, title, state, body, html_url, labels: [.labels[].name]}' || true

printf '%s\n' '=== Referenced CNO item comments containing credential/schema terms ==='
gh api --paginate repos/openshift/cluster-network-operator/issues/3047/comments \
  --jq '.[] | select((.body | ascii_downcase) | test("password|secret|md5|bgp-vip|frrconfiguration")) | {user: .user.login, created_at, body, html_url}' || true

Length of output: 104813


@mkowalski, verified. BGPPeerConfig.Password is currently serialized end-to-end through bgp-vip-config, and the referenced CNO change consumes that same schema for BGP session configuration. There is no compatible secret-reference field in this branch, so removing the field only in installer would break the feature without eliminating the broader exposure.

I also correct the MD5 wording: installer does not implement MD5; this is the BGP TCP-MD5 shared secret required by the protocol.

Given the DevPreview scope and coupled consumer changes, I won’t require a partial installer-only change. The plaintext ConfigMap exposure remains a known pre-GA security limitation and should stay explicitly documented and tracked for the Secret-backed structured API work. Would you like a dedicated follow-up issue created for that end-to-end migration?


✏️ Learnings added
Learnt from: mkowalski
Repo: openshift/installer PR: 10718
File: pkg/asset/manifests/bgpvipconfig.go:76-110
Timestamp: 2026-07-28T07:57:44.312Z
Learning: For BareMetal BGP VIP management, `pkg/asset/manifests/bgpvipconfig.go` intentionally serializes `baremetal.BGPPeerConfig.Password` into the `bgp-vip-config` ConfigMap as a DevPreview limitation. The current installer → CNO → baremetal-runtimecfg schema consumes inline BGP TCP-MD5 session secrets, and an installer-only Secret migration would break that coupled schema. A Secret-backed design requires coordinated installer, MCO bootstrap/static-pod, and CNO `FRRConfiguration` support and is planned with the TechPreview structured API.

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.

Comment thread pkg/asset/manifests/bgpvipconfig.go
Comment on lines +149 to +157
case baremetal.Name:
// BGP-based VIP management needs frr-k8s CRDs/namespace deployed by
// CNO; enable the FRR routing capability provider.
if ic.Config.Platform.BareMetal.BGPVIPConfig != nil {
cnoCfg = ovnNetworkOperatorConfig(cns, sn)
cnoCfg.Spec.AdditionalRoutingCapabilities = &operatorv1.AdditionalRoutingCapabilities{
Providers: []operatorv1.RoutingCapabilitiesProvider{operatorv1.RoutingCapabilitiesProviderFRR},
}
}

@coderabbitai coderabbitai Bot Jul 28, 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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject BGP VIP configuration on non-OVN networks.

Line 153 always creates an OVN configuration, whose default network type is OVNKubernetes. A BGP VIP-configured bare-metal install using another network type would silently render an incompatible network manifest. Reject that install-config combination in platform validation and retain an OVN-type guard here; add a regression test.

🤖 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/asset/manifests/network.go` around lines 149 - 157, Update platform
validation to reject bare-metal configurations that set BGPVIPConfig when the
selected network type is not OVNKubernetes. In the baremetal branch of the
manifest generation logic around ovnNetworkOperatorConfig, retain an explicit
OVNKubernetes guard before creating the OVN configuration, and add a regression
test covering the rejected combination.

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.

Fixed: install-config validation now rejects bgpVIPConfig with any network type other than OVNKubernetes, and the manifest generator additionally guards the OVN config creation on the network type. Regression test added (TestValidateBGPVIP: 'bgp requires OVNKubernetes').

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.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Candidate files =='
fd -t f . pkg/types/baremetal pkg/asset/manifests | rg '(platform|network).*(_test)?\.go$|featuregates\.go$'

printf '%s\n' '== Validation structure =='
ast-grep outline pkg/types/baremetal/validation --items all --type function --match 'ValidatePlatform|validateBGPVIPConfig|TestValidateBGPVIP' 2>/dev/null || true

printf '%s\n' '== Relevant validation and regression-test references =='
rg -n -C 8 'BGPVIPConfig|OVNKubernetes|bgp requires OVNKubernetes|TestValidateBGPVIP' \
  pkg/types/baremetal/validation pkg/asset/manifests/network.go pkg/asset/manifests/network_test.go

printf '%s\n' '== Manifest guard =='
sed -n '140,170p' pkg/asset/manifests/network.go

Length of output: 31127


@mkowalski, verified on the current PR branch.

  • Validation rejects bgpVIPConfig unless NetworkType is OVNKubernetes.
  • The manifest generator retains the explicit OVN guard before rendering the FRR-enabled CNO configuration.
  • TestValidateBGPVIP includes the bgp requires OVNKubernetes regression case and checks the expected error.

This resolves the incompatible manifest path. Static verification passed; tests were not executed in this environment.

Comment thread pkg/types/baremetal/validation/platform.go
Comment thread pkg/types/baremetal/validation/platform.go

Copilot AI 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.

Pull request overview

Adds installer-side support for BGP-based VIP management on BareMetal by introducing new install-config types/validation and rendering the required handover artifacts/manifests (Infrastructure status, CNO routing capability, and a CNO-consumed ConfigMap) when platform.baremetal.bgpVIPConfig is set.

Changes:

  • Added BGPVIPConfig / BGPPeerConfig types (plus per-host bgpPeers overrides) and updated deepcopy generation.
  • Added validation + feature-gate wiring for bgpVIPConfig, and enabled BGP VIP management in rendered manifests (Infrastructure status + CNO FRR routing capability).
  • Added generation + tests for a bgp-vip-config ConfigMap containing config.json in the runtimecfg-aligned schema.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/types/baremetal/zz_generated.deepcopy.go Adds deepcopy support for new BareMetal BGP VIP config types/fields.
pkg/types/baremetal/platform.go Introduces BGPVIPConfig, BGPPeerConfig, and per-host bgpPeers override field.
pkg/types/baremetal/validation/platform.go Validates bgpVIPConfig and per-host BGP peer settings.
pkg/types/baremetal/validation/featuregates.go Gates bgpVIPConfig behind BGPBasedVIPManagement.
pkg/asset/manifests/operators.go Wires the new BGP VIP ConfigMap asset into manifest generation.
pkg/asset/manifests/bgpvipconfig.go Generates the bgp-vip-config ConfigMap manifest with runtimecfg-aligned JSON.
pkg/asset/manifests/bgpvipconfig_test.go Tests that generated config.json matches the expected schema.
pkg/asset/manifests/infrastructure.go Sets BareMetal Infrastructure status VIP management to BGP when configured.
pkg/asset/manifests/network.go Enables CNO FRR routing capability for baremetal when BGP VIP config is set.
pkg/asset/manifests/network_test.go Adds tests for the CNO FRR capability enablement / negative case.
Files not reviewed (1)
  • pkg/types/baremetal/zz_generated.deepcopy.go: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/asset/manifests/infrastructure.go Outdated
config.Spec.PlatformSpec.BareMetal.MachineNetworks = types.MachineNetworksToCIDRs(installConfig.Config.MachineNetwork)
config.Status.PlatformStatus.BareMetal.MachineNetworks = types.MachineNetworksToCIDRs(installConfig.Config.MachineNetwork)
if installConfig.Config.Platform.BareMetal.BGPVIPConfig != nil {
config.Status.PlatformStatus.BareMetal.VIPManagement = "BGP"

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.

Fixed: uses configv1.VIPManagementTypeBGP — the typed constant is available now that the merged API is vendored on main.

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

Comment thread pkg/asset/manifests/network_test.go Outdated
Networking: &types.Networking{NetworkType: "OVNKubernetes"},
Platform: types.Platform{
BareMetal: &baremetal.Platform{
BGPVIPConfig: &baremetal.BGPVIPConfig{LocalASN: 64512},

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.

Fixed: the fixture now carries a valid peer (validation requires at least one).

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

Comment on lines +31 to +37
type bgpVIPConfigJSON struct {
LocalASN int64 `json:"localASN"`
DefaultPeers []baremetal.BGPPeerConfig `json:"defaultPeers"`
Communities []string `json:"communities,omitempty"`
APIVIPs []string `json:"apiVIPs"`
IngressVIPs []string `json:"ingressVIPs"`
HostOverrides map[string][]baremetal.BGPPeerConfig `json:"hostOverrides,omitempty"`

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.

Known DevPreview limitation, deliberate for now: the password is BGP TCP-MD5 session authentication (RFC 2385) — the hash is mandated by the BGP protocol option itself, not a choice of ours — and the whole config flows installer → ConfigMap → MCO/CNO as one schema. Moving it to a Secret requires the full chain (installer generates the Secret, MCO bootstrap render and CNO FRRConfiguration consume passwordSecret references) and is planned alongside the TechPreview structured API; the CNO side documents the same limitation (cluster-network-operator#3047, docs/bgp_vip_management.md). Splitting just the installer side now would leave mixed sources without removing the exposure.

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

Comment on lines +530 to +535
for i, host := range p.Hosts {
for j, peer := range host.BGPPeers {
hostPath := fldPath.Child("hosts").Index(i).Child("bgpPeers").Index(j)
allErrs = append(allErrs, validateBGPPeer(peer, hostPath)...)
}
}

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.

Both fixed: nil host entries are skipped in the peer-override loop (see the sibling thread for the pre-existing upstream caveat), and host-level bgpPeers are now rejected with field.Forbidden when platform.baremetal.bgpVIPConfig is not set — no more silent ignoring. Tests added for both.

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

@mkowalski
mkowalski force-pushed the opnet-781-bgp-vip branch from cb75feb to dcd7dbf Compare July 28, 2026 07:56

@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

🤖 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 `@pkg/types/baremetal/platform.go`:
- Around line 89-92: Apply the 16-peer maximum to the host override field
BGPPeers in pkg/types/baremetal/platform.go, using the existing validation
mechanism so lists exceeding 16 peers are rejected. Add a regression test in
pkg/types/baremetal/validation/platform_test.go covering a 17-peer host override
and verify the boundary cases remain covered.
- Around line 58-75: Extend BGP validation to cover BGPPeerConfig HoldTime and
KeepaliveTime duration syntax and BGPVIPConfig Communities ASN:value format
before generating runtime configuration, using allow-list validation consistent
with existing peer address/ASN/port/flag checks. Update the validation tests in
pkg/types/baremetal/validation/platform_test.go for invalid timer and community
values, while preserving valid configurations.
- Around line 45-46: Remove the BGP password from BGPPeerConfig and the
generated bgp-vip-config ConfigMap serialization; update the BGP authentication
flow to consume the credential from a Kubernetes Secret-backed path instead,
ensuring no plaintext password remains in ConfigMap data.
🪄 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 YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 2f9fe70f-4d2c-4e34-b202-09c3a4dd9429

📥 Commits

Reviewing files that changed from the base of the PR and between cb75feb and dcd7dbf.

⛔ Files ignored due to path filters (1)
  • pkg/types/baremetal/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (10)
  • pkg/asset/manifests/bgpvipconfig.go
  • pkg/asset/manifests/bgpvipconfig_test.go
  • pkg/asset/manifests/infrastructure.go
  • pkg/asset/manifests/network.go
  • pkg/asset/manifests/network_test.go
  • pkg/asset/manifests/operators.go
  • pkg/types/baremetal/platform.go
  • pkg/types/baremetal/validation/featuregates.go
  • pkg/types/baremetal/validation/platform.go
  • pkg/types/baremetal/validation/platform_test.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • pkg/types/baremetal/validation/featuregates.go
  • pkg/asset/manifests/infrastructure.go
  • pkg/asset/manifests/operators.go
  • pkg/asset/manifests/network_test.go
  • pkg/types/baremetal/validation/platform.go
  • pkg/asset/manifests/bgpvipconfig_test.go
  • pkg/asset/manifests/bgpvipconfig.go

Comment thread pkg/types/baremetal/platform.go Outdated
Comment thread pkg/types/baremetal/platform.go
Comment thread pkg/types/baremetal/platform.go

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pkg/types/baremetal/zz_generated.deepcopy.go: Generated file
Comments suppressed due to low confidence (2)

pkg/types/baremetal/validation/platform.go:638

  • BGPPeerConfig includes holdTime/keepaliveTime duration strings, but validateBGPPeer currently does not validate them. This means invalid values (e.g. "90" or "abc") will pass install-config validation and likely fail later during static-pod/FRR rendering. Consider validating non-empty values with time.ParseDuration (and optionally rejecting keepaliveTime > holdTime if both are set).
	if peer.Port != 0 && (peer.Port < 1 || peer.Port > 65535) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("port"), peer.Port,
			"must be between 1 and 65535, or omitted for the default 179"))
	}

pkg/types/baremetal/platform.go:72

  • validateBGPVIPConfig enforces peers length (min 1, max 16), but the BGPVIPConfig.Peers field lacks corresponding kubebuilder validation markers. As a result, the generated install-config schema (data/data/install.openshift.io_installconfigs.yaml) does not reflect these constraints, and invalid configs may only fail at installer validation time. Add kubebuilder tags like +kubebuilder:validation:MinItems=1 and +kubebuilder:validation:MaxItems=16 on the Peers field (and regenerate the installconfig CRD) to keep schema and validation aligned.
	// LocalASN is the Autonomous System Number for this cluster's BGP speaker.
	LocalASN int64 `json:"localASN"`

	// Peers is the list of BGP peers to advertise VIPs to.
	Peers []BGPPeerConfig `json:"peers"`

When BGPVIPConfig is present in install-config.yaml, generate a ConfigMap
named bgp-vip-config in the openshift-network-operator namespace. This
ConfigMap contains the full BGP peer configuration as JSON so that CNO
can read it and create FRRConfiguration CRs during the bootstrap-to-CRD
handover.

The config.json data includes:
- localASN from bgpVIPConfig.localASN
- peers from bgpVIPConfig.peers (default peer list)
- communities from bgpVIPConfig.communities
- apiVIPs from platform.baremetal.apiVIPs
- ingressVIPs from platform.baremetal.ingressVIPs
- hostOverrides from hosts[].bgpPeers (keyed by hostname)
@mkowalski
mkowalski force-pushed the opnet-781-bgp-vip branch from 839b271 to 64e7189 Compare July 28, 2026 19:58

@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.

🧹 Nitpick comments (1)
pkg/types/baremetal/validation/platform_test.go (1)

1221-1228: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover invalid keepaliveTime too.

Add a table case with malformed KeepaliveTime; it shares the timer-validation path but currently has no regression coverage.

As per path instructions, “Verify edge cases are covered, especially for validation and defaulting logic.”

🤖 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/types/baremetal/validation/platform_test.go` around lines 1221 - 1228,
Add a table-driven validation case alongside “invalid holdTime” that sets
BGPVIPConfig.Peers[0].KeepaliveTime to a malformed duration, uses the existing
ovnNetwork fixture, and expects the same “must be a valid duration” validation
error.

Source: Path instructions

🤖 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.

Nitpick comments:
In `@pkg/types/baremetal/validation/platform_test.go`:
- Around line 1221-1228: Add a table-driven validation case alongside “invalid
holdTime” that sets BGPVIPConfig.Peers[0].KeepaliveTime to a malformed duration,
uses the existing ovnNetwork fixture, and expects the same “must be a valid
duration” validation error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: f7b3c0fe-37b9-4bc8-a861-80d083a08d41

📥 Commits

Reviewing files that changed from the base of the PR and between 839b271 and 64e7189.

⛔ Files ignored due to path filters (2)
  • data/data/install.openshift.io_installconfigs.yaml is excluded by !data/data/install.openshift.io_installconfigs.yaml
  • pkg/types/baremetal/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (10)
  • pkg/asset/manifests/bgpvipconfig.go
  • pkg/asset/manifests/bgpvipconfig_test.go
  • pkg/asset/manifests/infrastructure.go
  • pkg/asset/manifests/network.go
  • pkg/asset/manifests/network_test.go
  • pkg/asset/manifests/operators.go
  • pkg/types/baremetal/platform.go
  • pkg/types/baremetal/validation/featuregates.go
  • pkg/types/baremetal/validation/platform.go
  • pkg/types/baremetal/validation/platform_test.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • pkg/asset/manifests/infrastructure.go
  • pkg/asset/manifests/network.go
  • pkg/types/baremetal/validation/featuregates.go
  • pkg/asset/manifests/bgpvipconfig_test.go
  • pkg/asset/manifests/bgpvipconfig.go
  • pkg/types/baremetal/validation/platform.go
  • pkg/asset/manifests/operators.go

@openshift-ci

openshift-ci Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

@mkowalski: all tests passed!

Full PR test history. Your PR dashboard.

Details

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

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.

3 participants