Skip to content

Conversation

@mangelajo
Copy link
Member

@mangelajo mangelajo commented Oct 28, 2025

This commit implements route detection

requires #176 (builds on top)

Summary by CodeRabbit

  • New Features

    • OpenShift Route resources are now supported as an alternative to Ingress for exposing service endpoints in OpenShift clusters
    • Implemented automatic detection of available cluster APIs, enabling the operator to intelligently use Ingress or Route resources based on platform capabilities
  • Chores

    • Added OpenShift API library as a new dependency

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2025

Walkthrough

This PR adds OpenShift Route support to the Jumpstarter controller by introducing API discovery to detect available Kubernetes resources, extending the endpoints reconciler to conditionally create Route objects as alternatives to Ingress, and refactoring pointer handling in deployment specifications using utility functions.

Changes

Cohort / File(s) Summary
Dependency Management
deploy/operator/go.mod
Added openshift/api dependency to support OpenShift-specific resources like Routes.
API Discovery
deploy/operator/internal/controller/jumpstarter/endpoints/discovery.go
New file introducing discoverAPIResource() helper to detect presence of Kubernetes API resources in a cluster by querying the discovery API and matching Kind names.
Reconciler Core Updates
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go
Updated NewReconciler signature to accept *rest.Config; added IngressAvailable and RouteAvailable boolean fields; added API discovery logic during initialization to detect Ingress and Route availability.
Route Reconciliation
deploy/operator/internal/controller/jumpstarter/endpoints/route.go
New file implementing Route reconciliation with createOrUpdateRoute() and createRouteForEndpoint() functions; conditionally creates Routes with passthrough TLS and HAProxy configuration when Route API is available.
Ingress Guard Logic
deploy/operator/internal/controller/jumpstarter/endpoints/ingress.go
Added early guard to skip ingress creation when IngressAvailable is false; refactored logger initialization for consistency.
Controller Integration
deploy/operator/cmd/main.go
Updated call to endpoints.NewReconciler() to pass mgr.GetConfig() as third argument.
Pointer Helper Refactoring
deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
Added import for k8s.io/utils/ptr; replaced inline int32Ptr and int64Ptr helper functions with ptr.To() utility for pointer creation across deployment and pod specs; removed now-unused helper functions.
Test Updates
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints_test.go, deploy/operator/internal/controller/jumpstarter/jumpstarter_controller_test.go
Updated all calls to endpoints.NewReconciler() to include cfg (*rest.Config) as third parameter to match updated constructor signature.

Sequence Diagram

sequenceDiagram
    participant Ctrl as Controller
    participant Recon as Reconciler
    participant Disc as Discovery
    participant API as Kubernetes API
    
    Ctrl->>Recon: NewReconciler(client, scheme, config)
    activate Recon
    Recon->>Disc: discoverAPIResource(..., "networking.k8s.io/v1", "Ingress")
    activate Disc
    Disc->>API: Query ServerResourcesForGroupVersion
    API-->>Disc: APIResourceList
    Disc-->>Recon: IngressAvailable=true/false
    deactivate Disc
    
    Recon->>Disc: discoverAPIResource(..., "route.openshift.io/v1", "Route")
    activate Disc
    Disc->>API: Query ServerResourcesForGroupVersion
    API-->>Disc: APIResourceList
    Disc-->>Recon: RouteAvailable=true/false
    deactivate Disc
    Recon-->>Ctrl: Reconciler initialized
    deactivate Recon
    
    Note over Ctrl,Recon: During Reconciliation
    Ctrl->>Recon: Reconcile(endpoint)
    activate Recon
    alt IngressAvailable
        Recon->>API: Create/Update Ingress
    end
    alt RouteAvailable
        Recon->>API: Create/Update Route
    end
    Recon-->>Ctrl: Reconciliation complete
    deactivate Recon
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Route reconciliation logic in route.go requires validation of hostname extraction, TLS passthrough configuration, and correct owner reference setup
  • API discovery mechanism in discovery.go and initialization in endpoints.go should be verified for error handling and correctness
  • Conditional resource creation based on IngressAvailable and RouteAvailable flags must be consistently applied across controller and router reconciliation paths
  • Test coverage for new Route functionality and API discovery scenarios

Possibly related PRs

  • operator: ingress support #176: Modifies the same endpoints controller package, adjusting ingress reconciliation functions and service handling; this PR extends that work with API discovery and OpenShift Route support.
  • Add the operator in deploy/operator #169: Modifies deploy/operator/cmd/main.go and deploy/operator/go.mod; the main PR's addition of mgr.GetConfig() parameter relates to operator scaffolding and initialization patterns introduced there.

Suggested reviewers

  • bennyz
  • bkhizgiy

Poem

🐰 Routes now flow where Ingress once reigned,
Discovery whispers which APIs are claimed,
With conditional grace, both paths align,
OpenShift's doors now widely shine!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "operator: implement routes and api detection" directly and accurately captures the two primary objectives of this changeset. The PR introduces new route reconciliation functionality (new route.go file with createRouteForEndpoint and createOrUpdateRoute functions) and implements API resource detection capabilities (new discovery.go file with discoverAPIResource function, plus IngressAvailable and RouteAvailable flags). The title is concise, specific, and avoids vague terminology, making it clear to reviewers scanning history that this PR adds route support and API availability detection to the operator. Secondary changes like the ptr.To refactoring are properly excluded from the title.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch autodetect-and-route-support

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

❤️ Share

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

}

// int32Ptr returns a pointer to an int32 value
func int32Ptr(i int32) *int32 {
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

(we should already have this dependency through all the k8s stuff)

Copy link
Member Author

Choose a reason for hiding this comment

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

+1!! makes sense

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, also across some other instances in the operator.

@mangelajo mangelajo force-pushed the operator-ingress branch 2 times, most recently from c1f42c4 to 3e595c8 Compare October 29, 2025 16:18
Base automatically changed from operator-ingress to main October 30, 2025 11:49
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
deploy/operator/internal/controller/jumpstarter/endpoints/route.go (1)

96-103: Clarify the route log message

This branch logs “Skipping ingress creation” even though we’re handling Routes here. It’s confusing during debugging—please adjust the message to say “route” so operators know which path was skipped.

deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (2)

44-60: Handle nil REST config to keep API discovery safe

Right now we defer straight to discoverAPIResource, so any caller that passes a nil or fake *rest.Config (common in unit tests) will panic inside the discovery client. A tiny guard that treats a missing config as “APIs unavailable” preserves the old behavior and avoids a crash.

Apply this diff (or similar):

 func NewReconciler(client client.Client, scheme *runtime.Scheme, config *rest.Config) *Reconciler {
 	log := logf.Log.WithName("endpoints-reconciler")

+	if config == nil {
+		log.Info("REST config not provided; skipping API discovery", "ingressAvailable", false, "routeAvailable", false)
+		return &Reconciler{
+			Client: client,
+			Scheme: scheme,
+		}
+	}
+
 	// Discover API availability at initialization
 	ingressAvailable := discoverAPIResource(config, "networking.k8s.io/v1", "Ingress")
 	routeAvailable := discoverAPIResource(config, "route.openshift.io/v1", "Route")

301-302: Please refresh the stale comment

This note still says “Route resources still need to be implemented,” but the Route code now exists just above. Updating or dropping it will prevent future confusion.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c850a15 and 6f91c55.

⛔ Files ignored due to path filters (1)
  • deploy/operator/go.sum is excluded by !**/*.sum
📒 Files selected for processing (9)
  • deploy/operator/cmd/main.go (1 hunks)
  • deploy/operator/go.mod (1 hunks)
  • deploy/operator/internal/controller/jumpstarter/endpoints/discovery.go (1 hunks)
  • deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (4 hunks)
  • deploy/operator/internal/controller/jumpstarter/endpoints/endpoints_test.go (2 hunks)
  • deploy/operator/internal/controller/jumpstarter/endpoints/ingress.go (1 hunks)
  • deploy/operator/internal/controller/jumpstarter/endpoints/route.go (1 hunks)
  • deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go (5 hunks)
  • deploy/operator/internal/controller/jumpstarter/jumpstarter_controller_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: NickCao
PR: jumpstarter-dev/jumpstarter-controller#137
File: deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml:23-26
Timestamp: 2025-05-13T19:56:27.924Z
Learning: In the jumpstarter-controller project, the router service uses the same ConfigMap as the controller service (controller-cm.yaml) even though it has been moved to its own separate deployment.
Learnt from: mangelajo
PR: jumpstarter-dev/jumpstarter-controller#170
File: deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go:328-333
Timestamp: 2025-10-24T11:57:23.796Z
Learning: In the jumpstarter-controller operator (deploy/operator/), the design allows only one Jumpstarter CR per namespace, which will be enforced by a validation webhook. This constraint eliminates concerns about resource name collisions within a namespace.
Learnt from: NickCao
PR: jumpstarter-dev/jumpstarter-controller#137
File: hack/deploy_with_helm.sh:26-34
Timestamp: 2025-05-13T19:57:56.811Z
Learning: The jumpstarter project uses a custom kind cluster configuration with an expanded NodePort range (3000-32767) and explicit port mappings for ingress (5080/5443) and gRPC services (30010/30011 mapped to 8082/8083).
Learnt from: NickCao
PR: jumpstarter-dev/jumpstarter-controller#137
File: hack/deploy_with_helm.sh:26-34
Timestamp: 2025-05-13T19:57:56.811Z
Learning: The jumpstarter-dev repository uses a custom kind cluster configuration that allows NodePort services to use non-standard ports 5080 and 5443, outside the default Kubernetes NodePort range (30000-32767).
📚 Learning: 2025-10-24T11:57:23.796Z
Learnt from: mangelajo
PR: jumpstarter-dev/jumpstarter-controller#170
File: deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go:328-333
Timestamp: 2025-10-24T11:57:23.796Z
Learning: In the jumpstarter-controller operator (deploy/operator/), the design allows only one Jumpstarter CR per namespace, which will be enforced by a validation webhook. This constraint eliminates concerns about resource name collisions within a namespace.

Applied to files:

  • deploy/operator/cmd/main.go
  • deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go
🧬 Code graph analysis (6)
deploy/operator/cmd/main.go (1)
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (1)
  • NewReconciler (44-61)
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints_test.go (1)
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (1)
  • NewReconciler (44-61)
deploy/operator/internal/controller/jumpstarter/endpoints/route.go (3)
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (1)
  • Reconciler (36-41)
deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py (1)
  • Route (85-90)
deploy/operator/internal/utils/utils.go (1)
  • MergeMaps (5-19)
deploy/operator/internal/controller/jumpstarter/jumpstarter_controller_test.go (1)
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (1)
  • NewReconciler (44-61)
deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (1)
deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py (1)
  • Route (85-90)
deploy/operator/internal/controller/jumpstarter/endpoints/discovery.go (1)
internal/log/levels.go (1)
  • Error (51-53)
🪛 OSV Scanner (2.2.3)
deploy/operator/go.mod

[HIGH] 10-10: github.com/golang-jwt/jwt/v5 5.2.1: Excessive memory allocation during header parsing in github.com/golang-jwt/jwt

(GO-2025-3553)


[HIGH] 10-10: github.com/golang-jwt/jwt/v5 5.2.1: jwt-go allows excessive memory allocation during header parsing

(GHSA-mh63-6h87-95cp)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: deploy-kind
  • GitHub Check: deploy-with-operator
  • GitHub Check: e2e-tests (ubuntu-24.04-arm)
  • GitHub Check: e2e-tests-release-0-7
  • GitHub Check: e2e-tests (ubuntu-24.04)
  • GitHub Check: lint-go
  • GitHub Check: tests
🔇 Additional comments (2)
deploy/operator/cmd/main.go (1)

218-223: Config wiring confirmed

Passing mgr.GetConfig() keeps the reconciler aligned with the new signature and ensures discovery has the right REST config context. Thanks for updating the constructor call accordingly.

deploy/operator/internal/controller/jumpstarter/endpoints/endpoints.go (1)

155-162: Route creation path looks solid

Thanks for mirroring the ingress flow for Routes; reusing the ClusterIP service keeps things consistent and should make OpenShift users happy.

@mangelajo mangelajo merged commit 0bdc3f7 into main Oct 30, 2025
9 of 10 checks passed
@mangelajo mangelajo deleted the autodetect-and-route-support branch October 30, 2025 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants