π Duplicate Code Detected: Near-Identical NodePoolDetailTab Components Across AKS, EKS, and GKE
Analysis of commit 3331497
Assignee: @copilot
Summary
Three Vue components β NodePoolDetailTab.vue in the AKS, EKS, and GKE packages β are structurally nearly identical (44 lines each, 132 total). They share the same component definition, props, fetch lifecycle, components registration, and <template>. The only differences are the provider-specific Kubernetes node label key, config path, and description format string used inside the getNodeGroup method.
Duplication Details
Pattern: Structurally identical Vue component with only provider-specific string differences
-
Severity: Medium
-
Occurrences: 3 files (~44 lines each, ~38 shared lines)
-
Locations:
pkg/aks/components/NodePoolDetailTab.vue (lines 1β44)
pkg/eks/components/NodePoolDetailTab.vue (lines 1β44)
pkg/gke/components/NodePoolDetailTab.vue (lines 1β44)
-
Code Sample (identical template β all 3 files):
<template>
<Loading v-if="$fetchState.pending" />
<MgmtNodeList
v-else
:resource="resource"
v-bind="$attrs"
:get-node-group="getNodeGroup"
/>
</template>
- Differences (getNodeGroup method only):
// AKS
const poolName = node?.status?.nodeLabels?.['kubernetes.azure.com/agentpool'] || '';
const poolSpec = (this.resource?.mgmt?.spec?.aksConfig?.nodePools || []).find((pool) => pool.name === poolName);
const description = poolSpec ? `${ poolSpec?.mode } β ${ node?.status?.nodeLabels?.['topology.kubernetes.io/region'] } β ${ poolSpec?.vmSize }` : '';
// EKS
const poolName = node?.status?.nodeLabels?.['eks.amazonaws.com/nodegroup'] || '';
const poolSpec = (this.resource?.mgmt?.spec?.eksConfig?.nodeGroups || []).find((pool) => pool.nodegroupName === poolName);
const description = poolSpec ? `${ node?.status?.nodeLabels?.['topology.kubernetes.io/region'] } β ${ poolSpec?.instanceType }` : '';
// GKE
const poolName = node?.status?.nodeLabels?.['cloud.google.com/gke-nodepool'] || '';
const poolSpec = (this.resource?.mgmt?.spec?.gkeConfig?.nodePools || []).find((pool) => pool.name === poolName);
const description = poolSpec ? `${ node?.status?.nodeLabels?.['topology.kubernetes.io/region'] } β ${ poolSpec?.config?.machineType }` : '';
Impact Analysis
- Maintainability: Any structural change to this component (new prop, modified
fetch lifecycle, template update) must be applied in 3 separate files.
- Bug Risk: A fix applied to one provider's tab may not be applied to others, leading to inconsistent behavior for users.
- Code Bloat: ~38 lines of identical code duplicated 3 times = ~76 extra lines.
Refactoring Recommendations
-
Extract a shared base component and pass provider-specific logic via props
- Create:
shell/components/MgmtNodePoolDetailTab.vue
- The shared component accepts a
getNodeGroup prop (Function) and handles rendering
- The three packages keep thin wrapper components that only implement
getNodeGroup and delegate rendering to the shared component
- Estimated effort: 2β3 hours
- Benefits: Single place to maintain the component skeleton; structural changes propagate to all providers automatically
-
Alternatively, use a composable for the shared lifecycle
- Extract
fetch() and component registration into a shared composable
- Each provider component uses the composable and only defines
getNodeGroup
Implementation Checklist
Analysis Metadata
- Analyzed Files: 3 (
pkg/aks/components/NodePoolDetailTab.vue, pkg/eks/components/NodePoolDetailTab.vue, pkg/gke/components/NodePoolDetailTab.vue)
- Detection Method: Semantic code analysis
- Commit: 3331497
- Analysis Date: 2026-07-03
Generated by Duplicate Code Detector Β· β 961.5K Β· β·
π Duplicate Code Detected: Near-Identical NodePoolDetailTab Components Across AKS, EKS, and GKE
Analysis of commit 3331497
Assignee:
@copilotSummary
Three Vue components β
NodePoolDetailTab.vuein the AKS, EKS, and GKE packages β are structurally nearly identical (44 lines each, 132 total). They share the same component definition,props,fetchlifecycle,componentsregistration, and<template>. The only differences are the provider-specific Kubernetes node label key, config path, and description format string used inside thegetNodeGroupmethod.Duplication Details
Pattern: Structurally identical Vue component with only provider-specific string differences
Severity: Medium
Occurrences: 3 files (~44 lines each, ~38 shared lines)
Locations:
pkg/aks/components/NodePoolDetailTab.vue(lines 1β44)pkg/eks/components/NodePoolDetailTab.vue(lines 1β44)pkg/gke/components/NodePoolDetailTab.vue(lines 1β44)Code Sample (identical template β all 3 files):
Impact Analysis
fetchlifecycle, template update) must be applied in 3 separate files.Refactoring Recommendations
Extract a shared base component and pass provider-specific logic via props
shell/components/MgmtNodePoolDetailTab.vuegetNodeGroupprop (Function) and handles renderinggetNodeGroupand delegate rendering to the shared componentAlternatively, use a composable for the shared lifecycle
fetch()and component registration into a shared composablegetNodeGroupImplementation Checklist
Analysis Metadata
pkg/aks/components/NodePoolDetailTab.vue,pkg/eks/components/NodePoolDetailTab.vue,pkg/gke/components/NodePoolDetailTab.vue)