From 72ce7fa58569aca2ba983cc7f186cf1a61dcd113 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Wed, 6 May 2026 14:26:28 +0000 Subject: [PATCH 1/4] docs: update install docs to headlamp namespace (PRI-434) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update Helm/plugin install URLs from v0.2.4 to v1.0.0 - README: add pods/proxy RBAC scope, clarify controller is in kube-system - docs/getting-started/*: update all download URLs to v1.0.0 - docs/deployment/helm.md: update install URLs to v1.0.0 - docs/architecture/overview.md: Headlamp Pod label → headlamp namespace - docs/README.md: fix ArtifactHub URL - CHANGELOG.md: add [Unreleased] entry Note: driver/API-path references to kube-system are preserved as they describe where the tns-csi controller workload runs, not where Headlamp is installed. Co-Authored-By: Paperclip --- CHANGELOG.md | 4 ++++ README.md | 12 ++++++++---- docs/README.md | 2 +- docs/architecture/overview.md | 2 +- docs/deployment/helm.md | 6 +++--- docs/getting-started/installation.md | 17 +++++++---------- docs/getting-started/quick-start.md | 2 +- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b702a10..dcf6a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **docs: namespace references** — Updated all documentation, README, and ArtifactHub metadata to explicitly reference the `headlamp` namespace instead of generic "controller pod" language. RBAC examples now clearly scope `pods/proxy` access to `kube-system` where the tns-csi controller runs. + ## [1.0.0] - 2026-03-24 ### Added diff --git a/README.md b/README.md index 00cdb79..4d9ff25 100644 --- a/README.md +++ b/README.md @@ -63,12 +63,12 @@ config: pluginsManager: sources: - name: tns-csi - url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz ``` ## RBAC / Security Setup -The plugin reads from the Kubernetes API and the tns-csi controller pod's Prometheus endpoint. The Benchmark page additionally creates and deletes Jobs and PVCs. +The plugin reads from the Kubernetes API and the tns-csi controller pod's Prometheus endpoint (deployed in `kube-system`). The Benchmark page additionally creates and deletes Jobs and PVCs. ### Minimal read-only permissions @@ -90,6 +90,10 @@ rules: - apiGroups: [""] resources: ["pods/log"] verbs: ["get"] + - apiGroups: [""] + resources: ["pods/proxy"] + verbs: ["get"] + resourceNames: ["pods"] ``` ### Additional permissions for Benchmark page @@ -105,13 +109,13 @@ rules: ### Metrics access -The plugin fetches Prometheus metrics from the tns-csi controller pod via the Kubernetes pod proxy sub-resource. Grant `get` on `pods/proxy` in `kube-system`: +The plugin fetches Prometheus metrics from the tns-csi controller pod via the Kubernetes pod proxy sub-resource in `kube-system`. Grant `get` on `pods/proxy` scoped to `kube-system`: ```yaml - apiGroups: [""] resources: ["pods/proxy"] verbs: ["get"] - # Optionally scope to the controller pod namespace + # Scope to kube-system where the tns-csi controller runs ``` Apply the role and bind it to your Headlamp service account with a ClusterRoleBinding. diff --git a/docs/README.md b/docs/README.md index 2be171e..3022041 100644 --- a/docs/README.md +++ b/docs/README.md @@ -67,7 +67,7 @@ Welcome to the Headlamp TNS-CSI Plugin documentation. ## External Links - **[GitHub Repository](https://github.com/privilegedescalation/headlamp-tns-csi-plugin)** -- **[Artifact Hub](https://artifacthub.io/packages/headlamp/headlamp-tns-csi-plugin/headlamp-tns-csi-plugin)** +- **[Artifact Hub](https://artifacthub.io/packages/headlamp/tns-csi/headlamp-tns-csi-plugin)** - **[tns-csi Driver](https://github.com/fenio/tns-csi)** - **[kbench](https://github.com/longhorn/kbench)** - **[Headlamp](https://headlamp.dev/)** diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index a97345e..861739d 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -28,7 +28,7 @@ The TNS-CSI plugin is a single-page React application bundled as a Headlamp plug │ HTTPS ▼ ┌─────────────────────────────────────────────────────┐ -│ Headlamp Pod (kube-system) │ +│ Headlamp Pod (headlamp namespace) │ │ │ │ Headlamp UI server + API proxy │ │ (forwards requests using service account token │ diff --git a/docs/deployment/helm.md b/docs/deployment/helm.md index a4a2e55..2db55cb 100644 --- a/docs/deployment/helm.md +++ b/docs/deployment/helm.md @@ -13,7 +13,7 @@ helm install headlamp headlamp/headlamp \ --create-namespace \ --set config.pluginsDir=/headlamp/plugins \ --set pluginsManager.sources[0].name=tns-csi \ - --set pluginsManager.sources[0].url=https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + --set pluginsManager.sources[0].url=https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz ``` ## Complete values.yaml Example @@ -27,7 +27,7 @@ config: pluginsManager: sources: - name: tns-csi - url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz serviceAccount: name: headlamp @@ -81,7 +81,7 @@ spec: pluginsManager: sources: - name: tns-csi - url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz ``` ## RBAC Manifest (Apply Separately) diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 2888d44..84d22d4 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -22,7 +22,7 @@ config: pluginsManager: sources: - name: tns-csi - url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz ``` **Via FluxCD HelmRelease:** @@ -46,7 +46,7 @@ spec: pluginsManager: sources: - name: tns-csi - url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz ``` ### Method 2: Manual Tarball Install @@ -55,13 +55,10 @@ Download and extract the plugin directly: ```bash # Download the release tarball -wget https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz - -# Verify the checksum -echo "14a3e8c13d0b894a41aa1cfccbcb1f6af09dcbb8fd95c7040a540987ea2096a7 tns-csi-0.2.4.tar.gz" | sha256sum --check +wget https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz # Extract into your Headlamp plugins directory -tar xzf tns-csi-0.2.4.tar.gz -C /headlamp/plugins/ +tar xzf tns-csi-1.0.0.tar.gz -C /headlamp/plugins/ ``` The plugin directory should appear as `/headlamp/plugins/tns-csi/`. @@ -81,7 +78,7 @@ initContainers: - -c - | wget -O /tmp/plugin.tar.gz \ - https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz tar xzf /tmp/plugin.tar.gz -C /headlamp/plugins/ volumeMounts: - name: plugins @@ -98,10 +95,10 @@ cd headlamp-tns-csi-plugin npm install npm run build npm run package -# Produces tns-csi-0.2.4.tar.gz +# Produces tns-csi-.tar.gz # Extract to your Headlamp plugins directory -tar xzf tns-csi-0.2.4.tar.gz -C /headlamp/plugins/ +tar xzf tns-csi-.tar.gz -C /headlamp/plugins/ ``` Or use `headlamp-plugin extract` for automatic placement: diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 71eba84..fd62974 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -28,7 +28,7 @@ config: pluginsManager: sources: - name: tns-csi - url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v0.2.4/tns-csi-0.2.4.tar.gz + url: https://github.com/privilegedescalation/headlamp-tns-csi-plugin/releases/download/v1.0.0/tns-csi-1.0.0.tar.gz ``` Then upgrade your Headlamp release: -- 2.52.0 From 2e2713fd3fd51f6ad93fd8e874d77c7eae2ab9f0 Mon Sep 17 00:00:00 2001 From: "privilegedescalation-ceo[bot]" <269721483+privilegedescalation-ceo[bot]@users.noreply.github.com> Date: Sun, 10 May 2026 21:34:56 +0000 Subject: [PATCH 2/4] docs: replace hardcoded namespace with placeholder Users choose their own namespace for Headlamp. Replace all hardcoded kube-system references that indicate Headlamp's install namespace with so users substitute their own value. Upstream workload references left untouched: - tns-csi controller pods in kube-system (upstream CSI driver) - NetworkPolicy selectors targeting kube-system - API server proxy paths to kube-system pods Refs: PRI-434 Co-authored-by: Chris Farhood Co-authored-by: Paperclip --- SECURITY.md | 6 +++--- docs/deployment/helm.md | 14 +++++++------- docs/getting-started/installation.md | 2 +- docs/getting-started/quick-start.md | 6 +++--- docs/troubleshooting/README.md | 4 ++-- docs/troubleshooting/benchmark.md | 4 ++-- docs/troubleshooting/metrics.md | 2 +- docs/troubleshooting/rbac.md | 6 +++--- docs/user-guide/rbac.md | 4 ++-- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index d03536f..ddb626a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -91,7 +91,7 @@ metadata: subjects: - kind: ServiceAccount name: headlamp - namespace: kube-system # adjust to your Headlamp namespace + namespace: roleRef: kind: ClusterRole name: headlamp-tns-csi-reader @@ -143,7 +143,7 @@ The Kubernetes API server performs the pod proxy hop, so policies should permit ### Service Account (Default) -Headlamp runs with a dedicated service account (`headlamp` in `kube-system`). All users share the same RBAC permissions. +Headlamp runs with a dedicated service account (`headlamp` in the namespace where Headlamp is installed). All users share the same RBAC permissions. **Security Considerations:** - All users have identical access to plugin functionality including Benchmark @@ -223,7 +223,7 @@ All API requests are logged in Kubernetes API audit logs (if enabled). Pod proxy "verb": "get", "requestURI": "/api/v1/namespaces/kube-system/pods//proxy/metrics", "user": { - "username": "system:serviceaccount:kube-system:headlamp" + "username": "system:serviceaccount::headlamp" } } ``` diff --git a/docs/deployment/helm.md b/docs/deployment/helm.md index a4a2e55..a853b05 100644 --- a/docs/deployment/helm.md +++ b/docs/deployment/helm.md @@ -9,7 +9,7 @@ helm repo add headlamp https://headlamp-k8s.github.io/headlamp/ helm repo update helm install headlamp headlamp/headlamp \ - --namespace kube-system \ + --namespace \ --create-namespace \ --set config.pluginsDir=/headlamp/plugins \ --set pluginsManager.sources[0].name=tns-csi \ @@ -44,7 +44,7 @@ Apply: ```bash helm install headlamp headlamp/headlamp \ - --namespace kube-system \ + --namespace \ -f headlamp-values.yaml ``` @@ -55,7 +55,7 @@ apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: headlamp - namespace: kube-system + namespace: spec: interval: 12h url: https://headlamp-k8s.github.io/headlamp/ @@ -64,7 +64,7 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: headlamp - namespace: kube-system + namespace: spec: interval: 1h chart: @@ -74,7 +74,7 @@ spec: sourceRef: kind: HelmRepository name: headlamp - namespace: kube-system + namespace: values: config: pluginsDir: /headlamp/plugins @@ -122,7 +122,7 @@ metadata: subjects: - kind: ServiceAccount name: headlamp - namespace: kube-system + namespace: roleRef: kind: ClusterRole name: headlamp-tns-csi-reader @@ -136,7 +136,7 @@ To upgrade to a new plugin version, update the `url` in your values and apply: ```bash helm upgrade headlamp headlamp/headlamp \ - --namespace kube-system \ + --namespace \ -f headlamp-values.yaml ``` diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 2888d44..c41d943 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -32,7 +32,7 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: headlamp - namespace: kube-system + namespace: spec: chart: spec: diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 71eba84..5813547 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -34,7 +34,7 @@ pluginsManager: Then upgrade your Headlamp release: ```bash -helm upgrade headlamp headlamp/headlamp -f values.yaml -n kube-system +helm upgrade headlamp headlamp/headlamp -f values.yaml -n ``` ## Step 2: Configure RBAC @@ -70,7 +70,7 @@ metadata: subjects: - kind: ServiceAccount name: headlamp - namespace: kube-system + namespace: roleRef: kind: ClusterRole name: headlamp-tns-csi-reader @@ -78,7 +78,7 @@ roleRef: EOF ``` -Adjust `name: headlamp` and `namespace: kube-system` to match your Headlamp service account. +Adjust `name: headlamp` and `namespace: ` to match your Headlamp service account. ## Step 3: Verify diff --git a/docs/troubleshooting/README.md b/docs/troubleshooting/README.md index 0388650..c473163 100644 --- a/docs/troubleshooting/README.md +++ b/docs/troubleshooting/README.md @@ -77,7 +77,7 @@ If a page shows a loading spinner indefinitely: 1. **Check browser console** for errors (F12 → Console) 2. **Check network tab** for failed API requests (look for 403, 404, 500) -3. **Check Headlamp pod logs**: `kubectl logs -n kube-system -l app.kubernetes.io/name=headlamp` +3. **Check Headlamp pod logs**: `kubectl logs -n -l app.kubernetes.io/name=headlamp` 4. **Try refreshing** — the watch connection may have been interrupted ## Common API Errors @@ -102,7 +102,7 @@ Look for errors related to `tns-csi`, `headlamp-plugin`, or Kubernetes API paths **Headlamp pod logs:** ```bash -kubectl logs -n kube-system -l app.kubernetes.io/name=headlamp --tail=100 +kubectl logs -n -l app.kubernetes.io/name=headlamp --tail=100 ``` **tns-csi controller logs:** diff --git a/docs/troubleshooting/benchmark.md b/docs/troubleshooting/benchmark.md index 6bae6d1..1ac6742 100644 --- a/docs/troubleshooting/benchmark.md +++ b/docs/troubleshooting/benchmark.md @@ -8,10 +8,10 @@ The Benchmark page requires permissions to create and delete Jobs and PVCs: ```bash kubectl auth can-i create jobs -n \ - --as=system:serviceaccount:kube-system:headlamp + --as=system:serviceaccount::headlamp kubectl auth can-i create persistentvolumeclaims -n \ - --as=system:serviceaccount:kube-system:headlamp + --as=system:serviceaccount::headlamp ``` Apply the additional permissions if missing — see [RBAC Issues](rbac.md) or [SECURITY.md](../../SECURITY.md). diff --git a/docs/troubleshooting/metrics.md b/docs/troubleshooting/metrics.md index b66c813..5a5dfbc 100644 --- a/docs/troubleshooting/metrics.md +++ b/docs/troubleshooting/metrics.md @@ -47,7 +47,7 @@ This requires `get` on `pods/proxy` in `kube-system`: ```bash kubectl auth can-i get pods/proxy \ -n kube-system \ - --as=system:serviceaccount:kube-system:headlamp + --as=system:serviceaccount::headlamp ``` ### 5. Network Policies diff --git a/docs/troubleshooting/rbac.md b/docs/troubleshooting/rbac.md index 1663e46..e03eb2d 100644 --- a/docs/troubleshooting/rbac.md +++ b/docs/troubleshooting/rbac.md @@ -11,16 +11,16 @@ Use `kubectl auth can-i` to check specific permissions: ```bash # Check if the Headlamp service account can list StorageClasses kubectl auth can-i list storageclasses \ - --as=system:serviceaccount:kube-system:headlamp + --as=system:serviceaccount::headlamp # Check pod proxy access (for metrics) kubectl auth can-i get pods/proxy \ -n kube-system \ - --as=system:serviceaccount:kube-system:headlamp + --as=system:serviceaccount::headlamp # Check snapshot access kubectl auth can-i list volumesnapshots \ - --as=system:serviceaccount:kube-system:headlamp + --as=system:serviceaccount::headlamp ``` ### Applying the Required RBAC diff --git a/docs/user-guide/rbac.md b/docs/user-guide/rbac.md index d06fb48..4290cb9 100644 --- a/docs/user-guide/rbac.md +++ b/docs/user-guide/rbac.md @@ -47,7 +47,7 @@ metadata: subjects: - kind: ServiceAccount name: headlamp # adjust to your Headlamp service account name - namespace: kube-system # adjust to your Headlamp namespace + namespace: roleRef: kind: ClusterRole name: headlamp-tns-csi-reader @@ -99,7 +99,7 @@ metadata: subjects: - kind: ServiceAccount name: headlamp - namespace: kube-system + namespace: roleRef: kind: Role name: headlamp-tns-csi-benchmark -- 2.52.0 From c808030317d9aba0889f0834d22eb6a0608f8c97 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Mon, 11 May 2026 13:44:27 +0000 Subject: [PATCH 3/4] chore: remove E2E testing infrastructure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Delete e2e/ directory (auth.setup.ts, tns-csi.spec.ts) - Delete playwright.config.ts - Delete scripts/deploy-e2e-headlamp.sh - Delete scripts/teardown-e2e-headlamp.sh - Delete .github/workflows/e2e.yaml - Remove e2e script from package.json - Remove @playwright/test dependency from package.json Context: [PRI-1133](/PRI/issues/PRI-1133) — full E2E purge across org. Co-Authored-By: Paperclip --- .github/workflows/e2e.yaml | 23 ----- e2e/auth.setup.ts | 69 ------------- e2e/tns-csi.spec.ts | 51 ---------- package.json | 6 +- playwright.config.ts | 27 ----- scripts/deploy-e2e-headlamp.sh | 167 ------------------------------- scripts/teardown-e2e-headlamp.sh | 30 ------ 7 files changed, 2 insertions(+), 371 deletions(-) delete mode 100644 .github/workflows/e2e.yaml delete mode 100644 e2e/auth.setup.ts delete mode 100644 e2e/tns-csi.spec.ts delete mode 100644 playwright.config.ts delete mode 100755 scripts/deploy-e2e-headlamp.sh delete mode 100755 scripts/teardown-e2e-headlamp.sh diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml deleted file mode 100644 index 7157fd1..0000000 --- a/.github/workflows/e2e.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: E2E Tests - -on: - push: - branches: [main] - pull_request: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: e2e-${{ github.repository }} - cancel-in-progress: false - -jobs: - e2e: - uses: privilegedescalation/.github/.github/workflows/plugin-e2e.yaml@main - with: - node-version: '22' - headlamp-version: v0.40.1 - e2e-namespace: headlamp-dev diff --git a/e2e/auth.setup.ts b/e2e/auth.setup.ts deleted file mode 100644 index fcd9f7f..0000000 --- a/e2e/auth.setup.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { test as setup, expect, Page } from '@playwright/test'; - -const AUTH_STATE_PATH = 'e2e/.auth/state.json'; - -async function authenticateWithOIDC(page: Page, username: string, password: string): Promise { - await page.goto('/'); - await page.waitForURL('**/login'); - - const popupPromise = page.waitForEvent('popup'); - await page.getByRole('button', { name: /sign in/i }).click(); - const popup = await popupPromise; - - await popup.waitForLoadState('domcontentloaded'); - await popup.waitForLoadState('networkidle'); - - const usernameField = popup.getByRole('textbox', { name: /email or username/i }); - await usernameField.waitFor({ state: 'visible', timeout: 15_000 }); - await usernameField.fill(username); - await popup.getByRole('button', { name: /log in/i }).click(); - - await popup.waitForLoadState('networkidle'); - const passwordField = popup.getByRole('textbox', { name: /password/i }); - await passwordField.waitFor({ state: 'visible', timeout: 15_000 }); - await passwordField.fill(password); - await popup.getByRole('button', { name: /continue|log in/i }).click(); - - await popup.waitForEvent('close', { timeout: 15_000 }); - - await expect(page.getByRole('navigation', { name: 'Navigation' })).toBeVisible({ - timeout: 15_000, - }); -} - -async function authenticateWithToken(page: Page, token: string): Promise { - await page.goto('/'); - await page.waitForURL(/\/(login|token)$/); - - if (page.url().includes('/login')) { - const useTokenBtn = page.getByRole('button', { name: /use a token/i }); - await useTokenBtn.waitFor({ state: 'visible', timeout: 15_000 }); - await useTokenBtn.click(); - await page.waitForURL('**/token'); - } - - await page.getByRole('textbox', { name: /id token/i }).fill(token); - await page.getByRole('button', { name: /authenticate/i }).click(); - - await expect(page.getByRole('navigation', { name: 'Navigation' })).toBeVisible({ - timeout: 15_000, - }); -} - -setup('authenticate with Headlamp', async ({ page }) => { - const username = process.env.AUTHENTIK_USERNAME; - const password = process.env.AUTHENTIK_PASSWORD; - const token = process.env.HEADLAMP_TOKEN; - - if (username && password) { - await authenticateWithOIDC(page, username, password); - } else if (token) { - await authenticateWithToken(page, token); - } else { - throw new Error( - 'Set AUTHENTIK_USERNAME + AUTHENTIK_PASSWORD for OIDC auth, or HEADLAMP_TOKEN for token auth' - ); - } - - await page.context().storageState({ path: AUTH_STATE_PATH }); -}); diff --git a/e2e/tns-csi.spec.ts b/e2e/tns-csi.spec.ts deleted file mode 100644 index 2d3b552..0000000 --- a/e2e/tns-csi.spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { test, expect } from '@playwright/test'; - -async function waitForSidebar(page: import('@playwright/test').Page) { - const sidebar = page.getByRole('navigation', { name: 'Navigation' }); - await expect(sidebar).toBeVisible({ timeout: 15_000 }); - await page.waitForLoadState('networkidle'); - return sidebar; -} - -test.describe('TNS CSI plugin smoke tests', () => { - test('sidebar contains TNS CSI entry', async ({ page }) => { - await page.goto('/'); - const sidebar = await waitForSidebar(page); - await expect(sidebar.getByRole('button', { name: /tns.csi/i })).toBeVisible(); - }); - - test('TNS CSI sidebar entry navigates to TNS CSI view', async ({ page }) => { - await page.goto('/'); - const sidebar = await waitForSidebar(page); - - const entry = sidebar.getByRole('button', { name: /tns.csi/i }); - await expect(entry).toBeVisible(); - await entry.click(); - - await page.waitForLoadState('networkidle'); - await expect(page).toHaveURL(/tns-csi/); - await expect(page.getByRole('heading', { name: /TNS.CSI/i })).toBeVisible(); - }); - - test('TNS CSI page renders content', async ({ page }) => { - await page.goto('/c/main/tns-csi'); - await waitForSidebar(page); - - await expect(page.getByRole('heading', { name: /TNS.CSI/i })).toBeVisible({ - timeout: 15_000, - }); - - const hasTable = await page.locator('table').first().isVisible().catch(() => false); - const hasContent = await page.locator('[class*="Mui"]').first().isVisible().catch(() => false); - expect(hasTable || hasContent).toBe(true); - }); - - test('plugin settings page shows TNS CSI plugin entry', async ({ page }) => { - await page.goto('/settings/plugins'); - await page.waitForLoadState('networkidle'); - await page.waitForSelector('[class*="PluginList"], [class*="plugins"], table, list', { timeout: 10_000 }).catch(() => {}); - - const pluginEntry = page.locator('text=/tns.csi/i').first(); - await expect(pluginEntry).toBeVisible({ timeout: 30_000 }); - }); -}); diff --git a/package.json b/package.json index 6ef5861..b417ae0 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,7 @@ "format": "prettier --write src/", "format:check": "prettier --check src/", "test": "vitest run", - "test:watch": "vitest", - "e2e": "playwright test" + "test:watch": "vitest" }, "peerDependencies": { "react": "^18.0.0", @@ -47,8 +46,7 @@ "react-dom": "^18.3.1", "react-router-dom": "^5.3.0", "typescript": "~5.6.2", - "vitest": "^3.2.4", - "@playwright/test": "^1.59.1" + "vitest": "^3.2.4" }, "overrides": { "tar": "^7.5.11", diff --git a/playwright.config.ts b/playwright.config.ts deleted file mode 100644 index b916edf..0000000 --- a/playwright.config.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { defineConfig, devices } from '@playwright/test'; - -export default defineConfig({ - testDir: './e2e', - timeout: 30_000, - expect: { timeout: 10_000 }, - fullyParallel: false, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 1 : 0, - reporter: 'list', - use: { - baseURL: process.env.HEADLAMP_URL || (() => { throw new Error('HEADLAMP_URL is required — run scripts/deploy-e2e-headlamp.sh first'); })(), - trace: 'on-first-retry', - screenshot: 'only-on-failure', - }, - projects: [ - { name: 'setup', testMatch: /auth\.setup\.ts/, timeout: 60_000 }, - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - storageState: 'e2e/.auth/state.json', - }, - dependencies: ['setup'], - }, - ], -}); diff --git a/scripts/deploy-e2e-headlamp.sh b/scripts/deploy-e2e-headlamp.sh deleted file mode 100755 index aa05998..0000000 --- a/scripts/deploy-e2e-headlamp.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -DIST_DIR="$REPO_ROOT/dist" - -E2E_NAMESPACE="${E2E_NAMESPACE:-headlamp-dev}" -E2E_RELEASE="${E2E_RELEASE:-headlamp-e2e}" -HEADLAMP_VERSION="${HEADLAMP_VERSION:-latest}" - -if [ ! -d "$DIST_DIR" ]; then - echo "ERROR: dist/ not found. Run 'pnpm build' first." >&2 - exit 1 -fi - -echo "Checking RBAC permissions in namespace '${E2E_NAMESPACE}'..." -if ! kubectl auth can-i delete configmaps -n "$E2E_NAMESPACE" --quiet 2>/dev/null; then - echo "ERROR: Missing RBAC — cannot delete configmaps in namespace '${E2E_NAMESPACE}'." >&2 - exit 1 -fi - -echo "=== E2E Headlamp Deployment ===" -echo " Image: ghcr.io/headlamp-k8s/headlamp:${HEADLAMP_VERSION}" -echo " Namespace: $E2E_NAMESPACE" -echo " Release: $E2E_RELEASE" - -echo "" -echo "Creating ConfigMap with plugin files..." - -kubectl delete configmap headlamp-tns-csi-plugin -n "$E2E_NAMESPACE" --ignore-not-found - -kubectl create configmap headlamp-tns-csi-plugin -n "$E2E_NAMESPACE" --from-file="$DIST_DIR" --from-file=package.json="$REPO_ROOT/package.json" - -echo "" -echo "Removing any existing E2E deployment (clean-start)..." -kubectl delete deployment "${E2E_RELEASE}" -n "$E2E_NAMESPACE" --ignore-not-found --wait -kubectl delete service "${E2E_RELEASE}" -n "$E2E_NAMESPACE" --ignore-not-found --wait -kubectl delete serviceaccount "${E2E_RELEASE}" -n "$E2E_NAMESPACE" --ignore-not-found --wait - -echo "" -echo "Deploying Headlamp E2E instance..." - -kubectl apply -f - </dev/null; do - ATTEMPTS=$((ATTEMPTS + 1)) - if [ "$ATTEMPTS" -ge "$MAX_ATTEMPTS" ]; then - echo "ERROR: ${SVC_URL} not reachable after $((MAX_ATTEMPTS * 5))s" >&2 - exit 1 - fi - echo " [${ATTEMPTS}/${MAX_ATTEMPTS}] not yet reachable, retrying in 5s..." - sleep 5 -done -echo "" -echo "E2E Headlamp is ready at: ${SVC_URL}" - -echo "" -echo "Creating service account token for E2E auth..." -kubectl create serviceaccount headlamp-e2e-test -n "$E2E_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - - -TOKEN=$(kubectl create token headlamp-e2e-test -n "$E2E_NAMESPACE" --duration=1h 2>/dev/null || echo "") -if [ -n "$TOKEN" ]; then - echo "HEADLAMP_URL=${SVC_URL}" > "$REPO_ROOT/.env.e2e" - echo "HEADLAMP_TOKEN=${TOKEN}" >> "$REPO_ROOT/.env.e2e" - echo "Wrote .env.e2e with HEADLAMP_URL and HEADLAMP_TOKEN" -else - echo " WARNING: Could not generate token." -fi - -echo "" -echo "E2E deployment complete." diff --git a/scripts/teardown-e2e-headlamp.sh b/scripts/teardown-e2e-headlamp.sh deleted file mode 100755 index 8d9f9be..0000000 --- a/scripts/teardown-e2e-headlamp.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" - -E2E_NAMESPACE="${E2E_NAMESPACE:-headlamp-dev}" -E2E_RELEASE="${E2E_RELEASE:-headlamp-e2e}" - -echo "=== E2E Headlamp Teardown ===" -echo " Namespace: $E2E_NAMESPACE" -echo " Release: $E2E_RELEASE" - -echo "Removing Headlamp Deployment, Service, and ServiceAccount..." -kubectl delete deployment "${E2E_RELEASE}" -n "$E2E_NAMESPACE" --ignore-not-found -kubectl delete service "${E2E_RELEASE}" -n "$E2E_NAMESPACE" --ignore-not-found -kubectl delete serviceaccount "${E2E_RELEASE}" -n "$E2E_NAMESPACE" --ignore-not-found - -echo "Cleaning up ConfigMap..." -kubectl delete configmap headlamp-tns-csi-plugin -n "$E2E_NAMESPACE" --ignore-not-found - -echo "Cleaning up test service account..." -kubectl delete serviceaccount headlamp-e2e-test -n "$E2E_NAMESPACE" --ignore-not-found - -if [ -f "$REPO_ROOT/.env.e2e" ]; then - rm "$REPO_ROOT/.env.e2e" - echo "Removed .env.e2e" -fi - -echo "" -echo "E2E teardown complete." -- 2.52.0 From 80ff5d3d1d47c7a5810a1e1372f06e86e27b3b60 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Mon, 11 May 2026 18:54:42 +0000 Subject: [PATCH 4/4] fix: update pnpm-lock.yaml after E2E deletion Remove @playwright/test dependencies after E2E infrastructure cleanup. Resolves ERR_PNPM_OUTDATED_LOCKFILE on PR. Co-Authored-By: Paperclip --- pnpm-lock.yaml | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5492350..bee2c12 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,9 +17,6 @@ importers: '@mui/material': specifier: ^5.15.14 version: 5.18.0(@emotion/react@11.14.0(@types/react@18.3.28)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.28)(react@18.3.1))(@types/react@18.3.28)(react@18.3.1))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@playwright/test': - specifier: ^1.59.1 - version: 1.59.1 '@testing-library/jest-dom': specifier: ^6.4.8 version: 6.9.1 @@ -991,11 +988,6 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.59.1': - resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} - engines: {node: '>=18'} - hasBin: true - '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} @@ -3057,11 +3049,6 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -4198,16 +4185,6 @@ packages: resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} engines: {node: '>=10'} - playwright-core@1.59.1: - resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} - engines: {node: '>=18'} - hasBin: true - - playwright@1.59.1: - resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} - engines: {node: '>=18'} - hasBin: true - possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -6545,10 +6522,6 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.59.1': - dependencies: - playwright: 1.59.1 - '@popperjs/core@2.11.8': {} '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@18.3.28)(react@18.3.1)(redux@5.0.1))(react@18.3.1)': @@ -9060,9 +9033,6 @@ snapshots: fs.realpath@1.0.0: {} - fsevents@2.3.2: - optional: true - fsevents@2.3.3: optional: true @@ -10443,14 +10413,6 @@ snapshots: dependencies: find-up: 5.0.0 - playwright-core@1.59.1: {} - - playwright@1.59.1: - dependencies: - playwright-core: 1.59.1 - optionalDependencies: - fsevents: 2.3.2 - possible-typed-array-names@1.1.0: {} postcss-modules-extract-imports@3.1.0(postcss@8.5.14): -- 2.52.0