Skip to content

project: Add ability to import and convert namespaces into projects #314

Merged
sniok merged 8 commits intoAzure:mainfrom
gambtho:thgamble/nstoproj
Mar 10, 2026
Merged

project: Add ability to import and convert namespaces into projects #314
sniok merged 8 commits intoAzure:mainfrom
gambtho:thgamble/nstoproj

Conversation

@gambtho
Copy link
Collaborator

@gambtho gambtho commented Feb 24, 2026

Summary

Implements the namespace-to-project conversion experience allowing users to import existing AKS managed namespaces as AKS Desktop projects.

For issue:

Unified Import Page

  • Rewrites ImportAKSProjects to discover all managed namespaces (not just pre-labeled ones) via Azure Resource Graph
  • Adds an "AKS Project?" status column showing whether each namespace already has AKS Desktop labels
  • When importing namespaces that aren't yet projects, a ConversionDialog confirms label application (headlamp.dev/project-managed-by: aks-desktop) before proceeding
  • Handles permission errors gracefully with clear messaging

Shared Utilities

  • Extracts assignRolesToNamespace() from CreateAKSProject into utils/azure/roleAssignment.ts for reuse
  • Adds applyProjectLabels() and fetchNamespaceData() in utils/kubernetes/namespaceUtils.ts for K8s label operations
  • Refactors CreateAKSProject.tsx to use the shared role assignment utility (~130 lines removed)

New Components

  • ConversionDialog — confirmation popup disclosing which labels will be added
  • useNamespaceDiscovery hook — Resource Graph discovery with isAksProject status, system namespace filtering, already-imported filtering
  • CreateProjectFromNamespace wizard — 5-step flow for advanced conversion (namespace selection, networking, compute, access, review)

Other

  • Adds documentation links in README
  • Registers new routes and create-project options in index.tsx

File Changes

Category Files
New ConversionDialog.tsx, ImportAKSProjects/hooks/useNamespaceDiscovery.ts, CreateProjectFromNamespace/ (wizard + components + hook), roleAssignment.ts, namespaceUtils.ts
Modified ImportAKSProjects.tsx (rewrite), CreateAKSProject.tsx (refactor), index.tsx (registrations), README.md
Tests namespaceUtils.test.ts (10 tests), roleAssignment.test.ts (9 tests)

Test plan

  • All CI checks pass (tsc, lint, format, build, tests)
  • ImportAKSProjects page shows all managed namespaces with "AKS Project?" column
  • Selecting already-labeled namespaces imports directly without dialog
  • Selecting unlabeled namespaces shows ConversionDialog with label disclosure
  • Confirming conversion applies labels and imports successfully
  • Permission denied errors show clear messaging
  • CreateAKSProject wizard still works after role assignment refactor
  • CreateProjectFromNamespace wizard works end-to-end for advanced conversion

Copilot AI review requested due to automatic review settings February 24, 2026 19:53
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds a new "AKS project from existing namespace" feature that enables users to convert existing AKS managed namespaces into Headlamp projects. The feature addresses the gap where namespaces created outside AKS Desktop (via Azure CLI or Portal) could not be turned into projects. The implementation follows the codebase's established patterns and successfully extracts shared role assignment logic into reusable utilities.

Changes:

  • New wizard flow for converting or importing managed namespaces with 5 steps: namespace selection, networking policies, compute quota, access control, and review
  • Shared utility modules for role assignment (roleAssignment.ts) and namespace label management (namespaceUtils.ts)
  • Azure Resource Graph-based namespace discovery with platform-specific query quoting for Windows compatibility
  • Documentation links added to README for AKS Desktop and managed namespaces

Reviewed changes

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

Show a summary per file
File Description
utils/kubernetes/namespaceUtils.ts New utility for fetching namespace data via K8s API and applying project labels
utils/azure/roleAssignment.ts Extracted shared role assignment logic from CreateAKSProject into reusable utility function
hooks/useNamespaceDiscovery.ts New hook that discovers managed namespaces via Azure Resource Graph with categorization
components/NamespaceSelectionStep.tsx Namespace picker UI with radio selection tables for conversion vs import categories
components/FromNamespaceReviewStep.tsx Review step displaying labels, config, and user assignments before conversion
CreateProjectFromNamespace.tsx Main wizard component orchestrating the 5-step conversion/import flow
index.tsx Route and custom create project registration for new namespace conversion feature
CreateAKSProject.tsx Refactored to use shared assignRolesToNamespace utility, reducing duplication
README.md Added documentation section with links to AKS Desktop and managed namespaces docs
docs/implementation-plan-namespace-to-project.md Comprehensive implementation plan document (800 lines)

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

@gambtho gambtho changed the title project: Add ability to create projects from existing managed namespaces project: Add ability to import and convert namespaces into projects Feb 24, 2026
Copilot AI review requested due to automatic review settings February 25, 2026 00:26
Copy link

Copilot AI left a comment

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 29 out of 29 changed files in this pull request and generated 5 comments.


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

Copilot AI review requested due to automatic review settings February 25, 2026 04:51
Copy link

Copilot AI left a comment

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 28 out of 28 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

plugins/aks-desktop/src/utils/shared/isAksProject.tsx:23

  • The cancel function is not being called in the error callback. According to the codebase conventions, cancelFn must be awaited and called in both success and error callbacks to prevent resource leaks. Add cancelFn.then(it => it()); inside the error callback.
      () => {
        res(false);
      },

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

illume
illume previously requested changes Feb 25, 2026
Copy link
Collaborator

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

Can you please break this down into some smaller commits?

Copilot AI review requested due to automatic review settings February 25, 2026 14:36
Copy link

Copilot AI left a comment

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 27 out of 27 changed files in this pull request and generated 4 comments.


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

@gambtho gambtho requested a review from illume February 25, 2026 14:49
Copilot AI review requested due to automatic review settings February 25, 2026 15:03
Copy link

Copilot AI left a comment

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 27 out of 27 changed files in this pull request and generated 2 comments.


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

Copilot AI review requested due to automatic review settings February 25, 2026 23:01
@gambtho gambtho force-pushed the thgamble/nstoproj branch from 5d82a1c to 5b5ac32 Compare March 5, 2026 22:47
Copy link

Copilot AI left a comment

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 45 out of 46 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (4)

plugins/aks-desktop/src/components/ImportAKSProjects/ImportAKSProjects.tsx:1

  • Keying clusterMap only by clusterName can conflate distinct Azure AKS clusters that share the same name across different resource groups/subscriptions. This can cause incorrect registration metadata (resourceGroup/subscriptionId) to be used for conversion/import. Use a composite key (e.g., ${clusterName}|${subscriptionId}|${resourceGroup} or an ARM ID) to keep clusters distinct.
// Copyright (c) Microsoft Corporation.

plugins/aks-desktop/src/utils/azure/roleAssignment.ts:1

  • The string No user assignments to process looks like a new i18n key, but the locale files added in this PR include No users to assign (and not this exact key). To avoid untranslated UI text, either reuse the existing key (No users to assign) or add this new key to the locale files consistently.
    plugins/aks-desktop/src/hooks/useNamespaceDiscovery.ts:1
  • isAlreadyImported reads/parses localStorage via getClusterSettings for every namespace being mapped/filtered. On clusters with many namespaces, this can add noticeable overhead. Consider caching allowedNamespaces per clusterName for the duration of discover() (e.g., a Map of clusterName -> Set<string>), so each cluster’s settings are parsed once.
    plugins/aks-desktop/src/hooks/useNamespaceDiscovery.ts:1
  • Deduplication uses ${clusterName}/${namespace} as the identity key. If two distinct clusters share the same clusterName (possible across different Azure subscriptions/resource groups) this will incorrectly drop namespaces from the 'regular' set. Prefer a stable unique cluster identifier for managed namespaces (e.g., include subscriptionId/resourceGroup, or store/use ARM resource IDs) when generating dedupe keys.

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

You can also share your feedback on Copilot code review. Take the survey.

@gambtho gambtho force-pushed the thgamble/nstoproj branch from 5b5ac32 to 6391598 Compare March 5, 2026 23:10
Copilot AI review requested due to automatic review settings March 6, 2026 03:57
@gambtho gambtho force-pushed the thgamble/nstoproj branch from 6391598 to 98be059 Compare March 6, 2026 03:57
Copy link

Copilot AI left a comment

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 46 out of 47 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (4)

plugins/aks-desktop/src/utils/azure/roleAssignment.ts:1

  • This introduces a new user-facing i18n key ('No user assignments to process') that doesn’t appear in the updated locale files (which include a similar 'No users to assign'). To avoid untranslated strings, reuse the existing key or add this new key to all locale dictionaries.
    plugins/aks-desktop/src/utils/kubernetes/namespaceUtils.ts:1
  • New behavior is introduced for creating a namespace pre-labeled as a project, but the current namespaceUtils.test.ts only covers fetchNamespaceData and applyProjectLabels. Add tests that assert the post call payload (labels and name) and that the correct cluster name is passed.
    plugins/aks-desktop/src/hooks/useNamespaceDiscovery.ts:1
  • This references window directly, which will throw in non-browser environments (e.g., if the hook is ever executed in a non-jsdom test or SSR-like context). Use globalThis and a typeof window !== 'undefined' guard (or read from globalThis only) to make the helper safe to import/execute outside the browser.
    plugins/aks-desktop/src/hooks/useNamespaceDiscovery.ts:1
  • If cancel() throws or the promise chain rejects, this can surface as an unhandled rejection. Consider adding a .catch(() => {}) (similar to fetchNamespaceData) to ensure cleanup never produces noisy console errors.

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

You can also share your feedback on Copilot code review. Take the survey.

@gambtho gambtho force-pushed the thgamble/nstoproj branch from 98be059 to e44e0bf Compare March 6, 2026 04:24
Copilot AI review requested due to automatic review settings March 9, 2026 21:16
@gambtho gambtho force-pushed the thgamble/nstoproj branch from e44e0bf to 21c2c0d Compare March 9, 2026 21:16
Copy link

Copilot AI left a comment

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 46 out of 47 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

plugins/aks-desktop/src/utils/kubernetes/namespaceUtils.ts:1

  • Error detection for az aks namespace update is case-sensitive and relies on the substring 'ERROR'; this can miss failures that are reported with different casing or formatting (e.g., Error:) and incorrectly treat the operation as success. Prefer checking the command exit status (if runCommandAsync exposes it or rejects on non-zero), or use a case-insensitive match for common error prefixes while still allowing known warning-only stderr output.

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

You can also share your feedback on Copilot code review. Take the survey.

@gambtho gambtho force-pushed the thgamble/nstoproj branch from 21c2c0d to ce7c894 Compare March 9, 2026 21:33
sniok
sniok previously approved these changes Mar 10, 2026
Copy link
Collaborator

@sniok sniok left a comment

Choose a reason for hiding this comment

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

tested and works nice

gambtho added 7 commits March 10, 2026 17:05
Move hardcoded project label strings into utils/constants/projectLabels.ts
and update all consumers (CreateAKSProject, DeleteAKSProject, InfoTab,
Metrics, Scaling, isAksProject). Also fix useClustersConf import path.
Move the inline role assignment loop from CreateAKSProject into a
reusable assignRolesToNamespace() function in utils/azure/roleAssignment.ts.
This will also be used by the namespace import flow.
…ooks

Add helper utilities for the namespace import feature:
- namespaceUtils: fetch namespace data and apply project labels via K8s API
- clusterSettings: read/write per-cluster localStorage settings
- useRegisteredClusters: hook returning registered cluster names
- useNamespaceDiscovery: discovers AKS managed namespaces (via Azure
  Resource Graph) and regular K8s namespaces, categorizing them as
  needing conversion or import

Includes vitest config and tests for all new modules.
Rewrite the import page to use the new useNamespaceDiscovery hook,
supporting both managed namespace import and regular namespace conversion
to projects. Add ConversionDialog for converting unlabeled namespaces.
Update plugin registration text and add documentation links to README.
Add a wizard flow for converting individual namespaces into AKS Desktop
projects. Unlike the bulk ImportAKSProjects flow, this provides a guided
step-by-step experience with networking, compute, and access configuration.

Steps: Select Namespace → Networking → Compute → Access → Review

The wizard discovers managed namespaces via Azure Resource Graph and
supports both conversion (adding project labels) and import (already
labeled but not registered locally). Registered as a custom create
project option in the Headlamp plugin sidebar.
…ments

- Replace Map<string, boolean> with Set<string> for selection state (ImportAKSProjects)
- Remove unused AzureCliWarning component from ImportAKSProjects
- Use i18next plural keys (_one/_other) instead of manual suffix concatenation
- Replace raw <input> with MUI TextField in success dialogs (CreateAKSProject, CreateProjectFromNamespace)
- Clean up timeout promise with clearTimeout in finally block
- Add updateFormData to useEffect dependency array
- Use theme.palette.divider instead of hardcoded border colors (FromNamespaceReviewStep)
- Replace fixed height with minHeight on review cards
- Remove duplicate checkAzureCliAndAksPreview mock from test
- Rename isAksProject.tsx to .ts (no JSX)
- Consolidate dual useMemo into single call (useNamespaceDiscovery)
- Initialize loading state to true (useNamespaceDiscovery)
- Use Pick<DiscoveredNamespace, ...> instead of manual interface (ConversionDialog)
- Add 7 new tests: success overlay, updateManagedNamespace args, back navigation,
  partial role failure, cluster registration error, setClusterSettings, mixed results
Copilot AI review requested due to automatic review settings March 10, 2026 21:08
@gambtho gambtho force-pushed the thgamble/nstoproj branch from ce7c894 to df37fba Compare March 10, 2026 21:08
Copy link

Copilot AI left a comment

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 46 out of 47 changed files in this pull request and generated 1 comment.


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

You can also share your feedback on Copilot code review. Take the survey.

@gambtho gambtho force-pushed the thgamble/nstoproj branch from df37fba to ea1797f Compare March 10, 2026 21:15
@sniok sniok dismissed illume’s stale review March 10, 2026 21:19

all the comments were addressed

@sniok sniok merged commit 583e4d5 into Azure:main Mar 10, 2026
7 checks passed
@illume illume mentioned this pull request Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request p3 low priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants