-
Notifications
You must be signed in to change notification settings - Fork 86
Add Konflux plugin #1826
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add Konflux plugin #1826
Conversation
Changed Packages
|
d84218f to
ca32561
Compare
| export function getSubcomponentsWithFallback( | ||
| relatedEntities: Entity[] | null | undefined, | ||
| mainEntity: Entity, | ||
| ): Entity[] { | ||
| if (!relatedEntities?.length) { | ||
| return [mainEntity]; | ||
| } | ||
|
|
||
| const filtered = relatedEntities.filter( | ||
| e => | ||
| e.metadata.name !== 'guest' && | ||
| e.relations?.some(rel => rel?.type === 'partOf'), | ||
| ); | ||
|
|
||
| // fallback to main entity if no valid subcomponents found | ||
| if (!filtered.length) { | ||
| return [mainEntity]; | ||
| } | ||
|
|
||
| return filtered; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: when subcomponents exist, we only use their cluster configs and ignore the main entity's config. falls back to main entity only if no subcomponents are found.
| ); | ||
|
|
||
| // case 1: continue from Kubearchive (k8s already exhausted) | ||
| if (kubearchiveToken && !k8sToken && hasKubearchive) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kubearchive fallback: if K8s is exhausted, automatically continue from Kubearchive. So, frontend only sees continuation tokens and doesn't need to know which source is used
| // decode continuation token to get pagination state for each source | ||
| let paginationState: PaginationState = {}; | ||
| const isLoadMoreRequest = !!validatedFilters?.continuationToken; | ||
|
|
||
| const userId = userEntityRef || userEmail || 'unknown'; | ||
|
|
||
| if (validatedFilters?.continuationToken) { | ||
| try { | ||
| paginationState = decodeContinuationToken( | ||
| validatedFilters.continuationToken, | ||
| userId, | ||
| ); | ||
| } catch (error) { | ||
| this.konfluxLogger.error('Failed to decode continuation token', error, { | ||
| userId, | ||
| entityRef, | ||
| resource, | ||
| }); | ||
| throw error instanceof Error | ||
| ? error | ||
| : new Error('Invalid continuation token'); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each source (cluster:namespace) maintains separate pagination state with tokens for both K8s API and karchive
| const sourceState = paginationState[sourceKey] || {}; | ||
| const hasAnyToken = sourceState.k8sToken || sourceState.kubearchiveToken; | ||
|
|
||
| if (isLoadMoreRequest && !hasAnyToken) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
skip exhausted sources (no tokens) in "Load More" requests to avoid unnecessary API calls
| } | ||
| }; | ||
|
|
||
| export const determineClusterNamespaceCombinations = async ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
combines app-config.yaml cluster configs with entity annotations. Groups by subcomponent+cluster+namespace and merges applications lists when multiple subcomponents reference the same cluster:namespace
| @@ -0,0 +1,79 @@ | |||
| { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for those unfamiliar with Backstage framework/architecture: the packages/ directory contains a "local development environment" (app + backend) for building and testing the plugin. This is standard Backstage workspace structure and not part of the plugin itself - it's only used for local development/testing :)
a65d96c to
fcd689a
Compare
|
This PR has been automatically marked as stale because it has not had recent activity from the author. It will be closed if no further activity occurs. If the PR was closed and you want it re-opened, let us know and we'll re-open the PR so that you can continue the contribution! |
0fdfd06 to
bbab9e3
Compare
09c22ee to
453afd9
Compare
workspaces/konflux/app-config.yaml
Outdated
| cluster1: | ||
| apiUrl: https://api.cluster1.example.com | ||
| uiUrl: https://ui.cluster1.example.com | ||
| kubearchiveApiUrl: https://archive.cluster1.example.com |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about we use something like ${SA_TOKEN_CLUSTER_NAME} to keep consistent usage with github_token?
We have several parameters here. For me, i create a .env and set all the variables then 'set -a; source .env; set +a'. then start the app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also i checked some other plugins, in their gitignore files, they ignore '.env'. i guess they recommend this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated the code to use "env vars" naming to keep it consistent!
| options?: { | ||
| pageSize?: number; | ||
| pageToken?: string; | ||
| filter?: string; // TODO: handle filter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether the // TODO comments are valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. I left this TODO for a future improvement :)
|
|
||
| - **serviceAccount**: Uses service account tokens | ||
| - **impersonationHeaders**: Uses Kubernetes impersonation headers (validates userEmail) | ||
| - **[UNSTABLE / NOT TESTED]** **oidc**: Uses OIDC tokens from the frontend (passed via X-OIDC-Token header) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it possible to test this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately, I don't think so 😕 it requires upgrading to OCP 4.19. That's a message from Gal in a discussion on Slack:
"we currently use user impersonation for the Konflux UI but we are going to stop doing it after upgrading to OCP 4.19 which allows to integrate with external OIDC providers. With this approach the same token would be recognized by both Konflux proxy and the api server."
For dev/stage we can use serviceAccount and impersonationHeaders. But, for production, we'll have to wait for upgrading to OCP 4.19, so we can use OIDC auth.
If you have some ideas on how we could test this oidc provider approach in a dev/local environment, pls let me know :)
| }), | ||
| ); | ||
|
|
||
| const results = await Promise.all(fetchPromises); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
promise all? whether we have potential performance problems here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it should be fine to use Promise.all() here. I'd propose to keep it this way and once we have this in alpha testing, we can gather more info regarding if it's causing issues and could be improved. wdyt? :)
testcara
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally LGTM, i just left few tiny comments. Thank you for the great patch.
testcara
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally lgtm, according to testing, the function works well.
For me, it is ready for user testing as we plan.
* add workspace package.json * add tsconfig.json * add app-config.yaml template * create plugins/ directory structure
- add konflux cluster configuration to app-config.yaml - add example entities and org data - add config.d.ts file with konflux configuration type definition
- add common types (PipelineRun, Application, Component, Release) - add configuration parsing utilities - add pagination constants and utilities - add entity processing utilities - add subcomponent utilities - add README
…tion - add KonfluxService for aggregating resources across clusters - add ResourceFetcherService for Kubernetes API and Kubearchive integration - add KubearchiveService for "archived resource fallback" - add router with /entity/:entityRef/resource/:resource endpoint - add configuration helpers and validation - add error extraction and logging utilities - support multiple auth methods (serviceAccount, impersonationHeaders) - IMPORTANT: OIDC still not tested - add README
- add KonfluxPage component for Applications and Components resources - add KonfluxCIPage component for Commits and PipelineRuns resources - add KonfluxStatus component for status display - add LatestReleases component - add resource hooks (useApplications, useComponents, usePipelineruns, useReleases) - add filtering and pagination utilities - add table components with PatternFly styling - add main README.md
…space - add app package with Backstage app setup - add backend package with backend server configuration - configure app routes and entity pages - set up authentication providers - add dependencies on konflux plugins - integrate konflux plugin into Backstage app
Add owners to konflux workspace.
Fix dependencies dedupe issues.
95f39f1 to
25c02b2
Compare
|
hopehadfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay in reviewing. Overall very nice work on the plugin, I just left a few comments to address before we can go ahead and merge 😄🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file isn't necessary for this repository, only for the backstage/community-plugins repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should instead exist within the plugin packages themselves, either in workspaces/konflux/plugins/konflux-common or in both the frontend and backend package. Also, the visibility annotations should be double-checked (i.e. serviceAccountToken should probably be @visibility secret)
| "backstage": { | ||
| "role": "backend" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "backstage": { | |
| "role": "backend" | |
| }, | |
| "backstage": { | |
| "role": "backend-plugin", | |
| "pluginId": "konflux", | |
| "pluginPackage": "@red-hat-developer-hub/backstage-plugin-konflux-backend", | |
| "pluginPackages": [ | |
| "@red-hat-developer-hub/backstage-plugin-konflux", | |
| "@red-hat-developer-hub/backstage-plugin-konflux-backend", | |
| "@red-hat-developer-hub/backstage-plugin-konflux-common" | |
| ] | |
| }, |
| "prettier --write" | ||
| ] | ||
| }, | ||
| "dependencies": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider cleaning these up, most of these likely belong in or are already in the individual plugin packages.



Add Konflux Plugin for Backstage
Overview
This PR is adding a Backstage integration plugin for Konflux (Red Hat's application delivery platform). The plugin aggregates and displays Kubernetes resources (Applications, Components, PipelineRuns, Releases) from multiple clusters and namespaces, providing a unified view of Konflux resources within Backstage.
Alpha Testing Phase
Once this plugin is merged and integrated into RHDH, it will enter an "alpha testing phase" on the InScope Backstage instance. During this period, we'll gather feedback from early users and iterate on improvements. The plugin is being developed in
rhdh-pluginsrepo (rather thanbackstage/community-plugins) to enable faster iteration cycles during this testing period. Once alpha testing is complete and we've gathered sufficient feedback, we plan to polish the plugin and make it generally available.Fixes
The main Epic ticket has several smaller tickets to help tracking the work :)
Fixes https://issues.redhat.com/browse/KFLUXUI-791
Fixes https://issues.redhat.com/browse/KFLUXUI-815
Fixes https://issues.redhat.com/browse/KFLUXUI-816
Fixes https://issues.redhat.com/browse/KFLUXUI-817
Fixes https://issues.redhat.com/browse/KFLUXUI-836
Fixes https://issues.redhat.com/browse/KFLUXUI-837
Fixes https://issues.redhat.com/browse/KFLUXUI-840
Fixes https://issues.redhat.com/browse/KFLUXUI-841
For a broader feature description see https://issues.redhat.com/browse/KONFLUX-8254
Architecture
The plugin consists of three packages:
Key Features
How It Works
app-config.yamlwith entity-specific configuration from catalog annotations (konflux-ci.dev/clusters)konflux-ci.dev/overview,konflux-ci.dev/konflux,konflux-ci.dev/ci)Visual References
Demo Video
This is a short demo video that goes through all the components available with the Konflux plugin, including navigation between tabs and demonstration of filtering/pagination features.
short-demo.mp4
Screenshots
Entity Overview with Konflux Components (KonfluxStatus and KonfluxLatestReleases)
![Entity Overview tab showing KonfluxStatus and KonfluxLatestReleases components integrated into the standard Backstage entity overview]
Konflux Tab - Applications and Components
![KonfluxPage displaying ApplicationsList and ComponentsList with filtering and pagination controls]
CI/CD Tab - Pipeline Runs and Commits
![KonfluxCIPage showing PipelineRunsList and CommitsList with filtering and pagination controls]
Configuration
The plugin requires configuration in two places:
app-config.yamlfor cluster configuration and entity annotations for feature enablement and resource mapping.app Configuration (
app-config.yaml)Configure clusters and authentication in the backend configuration:
Entity Configuration (
catalog-info.yaml)Entities can enable Konflux features via annotations:
Feature Control Annotations:
konflux-ci.dev/overview: 'true'- shows Konflux components in Overview tabkonflux-ci.dev/konflux: 'true'- enables Konflux tabkonflux-ci.dev/ci: 'true'- enables CI/CD tabCluster Configuration Annotation:
konflux-ci.dev/clusters- cluster/namespace/applications configuration (YAML format)Example Entity Configuration:
Note: when subcomponents exist, only their cluster configurations are used. If no subcomponents exist, the main entity's configuration is used as a fallback.
Testing
Note: this PR adds the complete konflux plugin workspace including all three packages, configuration, and documentation ☕️
✔️ Checklist