Skip to content

[duplicate-code] Duplicate Code: Near-Identical NodePoolDetailTab Components Across AKS, EKS, and GKEΒ #131

Description

@github-actions

πŸ” 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

  1. 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
  2. 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

  • Review duplication findings
  • Prioritize refactoring tasks
  • Create refactoring plan
  • Implement changes
  • Update tests
  • Verify no functionality broken

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 Β· β—·

  • expires on Jul 5, 2026, 9:40 PM UTC

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions