Skip to content

Add Cluster API plugin#273

Merged
illume merged 1 commit intoheadlamp-k8s:mainfrom
mboersma:cluster-api
Mar 6, 2026
Merged

Add Cluster API plugin#273
illume merged 1 commit intoheadlamp-k8s:mainfrom
mboersma:cluster-api

Conversation

@mboersma
Copy link
Copy Markdown
Contributor

@mboersma mboersma commented Jun 10, 2025

NOTE: This is still a work in progress. There are a few issues to address before it should merge.

Adds a headlamp plugin for rendering Cluster API objects in the Sidebar and Map.

capi-plugin
capi-plugin-2

Fixes kubernetes-sigs/cluster-api#12305

TODO:

  • The Detail views for all objects are generic, but should show more specific information.
  • The on-hover "Glance" tooltips in the Map should show more info, like basic k8s objects do.
  • There should be some basic tests.
  • Column spacing in list views could use some attention
  • The Cluster detail view should have a "Get kubeconfig" action button, and the downloaded kubeconfig should show up in Headlamp's "Clusters" list (see Headlamp.setCluster())
  • The MachinePool spec needs the template fields to be added.
  • The typescript defs for CAPI resources are not all complete and need reviewing.
  • The ClusterDetail view causes an error when its route is registered.
  • Time fields in List views should be formatted as kubectl -o table does, e.g. "2d5h".
  • The Sidebar needs a black-and-white "turtles" icon for CAPI.
  • All CAPI types are using the "turtles" icon, but they should have their own icons.
  • "Controlled by" field in Detail views should be a link to the owning object (see Pods for example)

Wishlist:

  • Should be able to render infra ref provider-specific objects in the tree, or other bootstrap components
  • Could elevate "Ready" condition to main detail view
  • There should be storybook tests for all components. (Currently not working--see comments below.)
  • The plugin should support the upcoming v1beta2 version of Cluster API resources.
  • KubeadmControlPlane and MachineDeployment|Set|Pool should have the ScaleButton and act like k8s Deployment/ReplicaSet (see Allow plugins to register as scalable resources kubernetes-sigs/headlamp#3536)
  • The Map filter menu should have multiple sources so it expands and can toggle all CAPI CRDs individually

Questions:
I don't know if this should be an official plugin or live in a separate repo. Any advice here is welcome.

@mboersma
Copy link
Copy Markdown
Contributor Author

/cc @willie-yao

@joaquimrocha
Copy link
Copy Markdown
Contributor

@mboersma , I am happy to have it as an official plugin.
Here is a turtle icon you may use: https://icon-sets.iconify.design/mdi/?icon-filter=turtle

We may also be able to early-merge it into a capi-plugin branch, so it continues being worked on without depending just on your branch. WDYT?

@mboersma mboersma changed the title Add Cluster API plugin [WIP] Add Cluster API plugin Jun 12, 2025
@mboersma
Copy link
Copy Markdown
Contributor Author

@joaquimrocha thanks for the info and the icon!

If it's ok to leave this as a work-in-progress for a few days, I think we can fix most of the known issues and then see if a capi-plugin branch would help with collaboration.

@mboersma mboersma force-pushed the cluster-api branch 3 times, most recently from 73d6515 to 87f84f5 Compare June 13, 2025 23:48
@mboersma mboersma force-pushed the cluster-api branch 2 times, most recently from 4e8c517 to f349a61 Compare June 17, 2025 23:22
@illume
Copy link
Copy Markdown
Contributor

illume commented Jun 18, 2025

For stories there's a problem with the current headlamp-plugin.

We have storybooks working in a headlamp-plugin alpha release, but there's still some bugs.

cd cluster-api
npx @kinvolk/headlamp-plugin upgrade --headlamp-plugin-version=0.13.0-alpha.5
diff --git a/cluster-api/src/index.tsx b/cluster-api/src/index.tsx
index a36d967..7eada7f 100644
--- a/cluster-api/src/index.tsx
+++ b/cluster-api/src/index.tsx
@@ -70,7 +70,7 @@ function registerClusterApiResource(config: ResourceRegistrationConfig) {
     path: `/cluster-api/${path}/${hasNamespace ? ':namespace/:name' : ':name'}`,
     sidebar: name,
     name: name.slice(0, -1), // Remove 's' from plural form
-    component: DetailComponent,
+    component: () => <DetailComponent />,
   });

   // Register list route
@@ -78,7 +78,7 @@ function registerClusterApiResource(config: ResourceRegistrationConfig) {
     path: `/cluster-api/${path}`,
     sidebar: name,
     name,
-    component: ListComponent,
+    component: () => <ListComponent />,
   });

   // Register icon for the resource kind   

One issue with the headlamp-plugin alpha is that it has issues with this import path when running the storybook.

diff --git a/cluster-api/src/resources/kubeadmcontrolplane.ts b/cluster-api/src/resources/kubeadmcontrolplane.ts
index 867af16..59ef79b 100644
--- a/cluster-api/src/resources/kubeadmcontrolplane.ts
+++ b/cluster-api/src/resources/kubeadmcontrolplane.ts
@@ -1,4 +1,4 @@
-import { KubeObject, KubeObjectInterface, Time } from '@kinvolk/headlamp-plugin/lib/k8s/cluster';
+import { KubeObject, KubeObjectInterface, Time } from '@kinvolk/headlamp-plugin/lib/lib/k8s/cluster';
 import { Condition, ObjectMeta, ReadinessGate } from './common';
 import { KubeadmConfigSpec } from './kubeadmconfig';

Autogenerated a storybook story:
src/components/kubeadmcontrolplanes/Glance.stories.tsx

import { Meta, StoryObj } from '@storybook/react';
import { KubeadmControlPlane } from '../../resources/kubeadmcontrolplane';
import { KubeadmControlPlaneGlance } from './Glance';

const meta: Meta<typeof KubeadmControlPlaneGlance> = {
  title: 'Components/KubeadmControlPlanes/Glance',
  component: KubeadmControlPlaneGlance,
  parameters: {
    layout: 'centered',
  },
};

export default meta;
type Story = StoryObj<typeof KubeadmControlPlaneGlance>;

export const Default: Story = {
  args: {
    node: {
      kubeObject: {
        kind: KubeadmControlPlane.kind,
        spec: {
          replicas: 3,
        },
        status: {
          readyReplicas: 2,
        },
      },
    },
  },
};

export const AllReplicasReady: Story = {
  args: {
    node: {
      kubeObject: {
        kind: KubeadmControlPlane.kind,
        spec: {
          replicas: 3,
        },
        status: {
          readyReplicas: 3,
        },
      },
    },
  },
};

export const NoReplicasReady: Story = {
  args: {
    node: {
      kubeObject: {
        kind: KubeadmControlPlane.kind,
        spec: {
          replicas: 3,
        },
        status: {
          readyReplicas: 0,
        },
      },
    },
  },
};

export const InvalidNodeKind: Story = {
  args: {
    node: {
      kubeObject: {
        kind: 'SomeOtherKind',
      },
    },
  },
};

Then you can see the storybook in here:
npm run storybook

Note, I didn't run the plugin with the headlamp-plugin alpha release. The npm run build, and npm run tsc run without error though. Let me know if you have any issues?

@illume
Copy link
Copy Markdown
Contributor

illume commented Jun 18, 2025

Sorry, I had the wrong line here:

npx @kinvolk/headlamp-plugin upgrade --headlamp-plugin-version=0.13.0-alpha.2

Should have been:

npx @kinvolk/headlamp-plugin upgrade --headlamp-plugin-version=0.13.0-alpha.5

@mboersma
Copy link
Copy Markdown
Contributor Author

Thanks @illume! I made the changes you suggested. Two problems:

  • npm run storybook won't compile without the change from lib/ to lib/lib/, but that change seems to break the plugin in general
  • When npm run storybook loads, it shows the Glance stories but won't render with this error:
ReferenceError: Cannot access 'KubeObject' before initialization
    at makeKubeObject (http://localhost:6007/vendors-node_modules_kinvolk_headlamp-plugin_lib_components_common_Resource_index_js-node_mod-dc3e88.iframe.bundle.js:34520:38)
    at ./node_modules/@kinvolk/headlamp-plugin/lib/lib/k8s/clusterRole.js (http://localhost:6007/vendors-node_modules_kinvolk_headlamp-plugin_lib_components_common_Resource_index_js-node_mod-dc3e88.iframe.bundle.js:37955:86)
    at __webpack_require__ (http://localhost:6007/runtime~main.iframe.bundle.js:28:33)
    at fn (http://localhost:6007/runtime~main.iframe.bundle.js:343:21)
    at ./node_modules/@kinvolk/headlamp-plugin/lib/lib/k8s/index.js (http://localhost:6007/vendors-node_modules_kinvolk_headlamp-plugin_lib_components_common_Resource_index_js-node_mod-dc3e88.iframe.bundle.js:39245:70)
    at __webpack_require__ (http://localhost:6007/runtime~main.iframe.bundle.js:28:33)
    at fn (http://localhost:6007/runtime~main.iframe.bundle.js:343:21)
    at ./node_modules/@kinvolk/headlamp-plugin/lib/components/account/Auth.js (http://localhost:6007/vendors-node_modules_kinvolk_headlamp-plugin_lib_components_common_Resource_index_js-node_mod-dc3e88.iframe.bundle.js:12957:66)
    at __webpack_require__ (http://localhost:6007/runtime~main.iframe.bundle.js:28:33)
    at fn (http://localhost:6007/runtime~main.iframe.bundle.js:343:21)

@illume
Copy link
Copy Markdown
Contributor

illume commented Jun 18, 2025

Ok, thanks for those notes. I’ll work on fixing them tomorrow.

@evmnaumov
Copy link
Copy Markdown

Hi there!
Is there any updates? I'm waiting for this plugin 🤗

agrawalcodes pushed a commit to agrawalcodes/plugins that referenced this pull request Feb 7, 2026
… add tests

- Enhance MachineDetail with cluster link, phase, version, provider ID,
  bootstrap/infra ready, node info, addresses, and ref fields
- Enhance KubeadmControlPlaneDetail with version, initialized/ready status,
  rollout strategy, remediation info, and infrastructure ref
- Enhance MachinePoolDetail with cluster link, phase, bootstrap/infra ready,
  min ready seconds, failure domains, and version
- Enhance MachineDrainRuleDetail with drain behavior, order, machine/pod selectors
- Enhance ClusterClassDetail with infrastructure ref, control plane info,
  worker classes, variables, and patches
- Fix MachineSetDetail duplicate Replicas field and add cluster link
- Fix MachinePoolsList: add cluster link, enable version column, add
  ready/available columns
- Add Cluster link to MachineDeploymentDetail
- Add Glance tooltips for Cluster (phase, CP/infra readiness) and Machine
  (phase, version, node name)
- Extract pure utility functions (formatUpdateStrategy, hasReplicas,
  getReplicaValues, formatKCPRolloutStrategy) into utils.ts for testability
- Add 25 unit tests covering all utility functions

Addresses PR headlamp-k8s#273 TODOs:
- "Detail views for all objects are generic, but should show more specific information"
- "Glance tooltips in the Map should show more info"
- "There should be some basic tests"

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Matt Boersma <Matt.Boersma@microsoft.com>
Copy link
Copy Markdown
Contributor

@illume illume left a comment

Choose a reason for hiding this comment

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

🎉 thanks!

@illume illume changed the title [WIP] Add Cluster API plugin Add Cluster API plugin Mar 6, 2026
@illume illume merged commit 006c40e into headlamp-k8s:main Mar 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Headlamp plugin for Cluster API

4 participants