55 "fmt"
66 "sort"
77 "strings"
8+ "unicode"
89
910 "github.com/spf13/cobra"
1011 corev1 "k8s.io/api/core/v1"
@@ -118,15 +119,18 @@ func runList(cmd *cobra.Command, opts *listOptions) error {
118119 return util .PrintYAML (cmd .OutOrStdout (), & instList )
119120 }
120121
121- // List deployments — build map deploymentUID → *WorkloadDeployment.
122+ // List deployments — build map deploymentName → *WorkloadDeployment.
123+ // Keyed by name (not UID) because the WorkloadDeploymentUIDLabel on an
124+ // Instance carries the edge/Karmada WD UID, which differs from the
125+ // project-cluster WD UID. The WD name is identical across all planes.
122126 var deployList computev1alpha.WorkloadDeploymentList
123127 if err := c .List (ctx , & deployList , client .InNamespace (util .ResourceNamespace )); err != nil {
124128 return fmt .Errorf ("listing deployments: %w" , err )
125129 }
126130 deploymentMap := make (map [string ]* computev1alpha.WorkloadDeployment , len (deployList .Items ))
127131 for i := range deployList .Items {
128132 d := & deployList .Items [i ]
129- deploymentMap [string ( d . UID ) ] = d
133+ deploymentMap [d . Name ] = d
130134 }
131135
132136 // List workloads — build map workloadUID → name.
@@ -142,18 +146,52 @@ func runList(cmd *cobra.Command, opts *listOptions) error {
142146 // Build rows.
143147 var rows []instanceRow
144148 for _ , inst := range instList .Items {
145- depUID := inst .Labels [computev1alpha .WorkloadDeploymentUIDLabel ]
146149 wlUID := inst .Labels [computev1alpha .WorkloadUIDLabel ]
147150
148151 city := "unknown"
149152 wlName := workloadMap [wlUID ]
150153 if wlName == "" {
151154 wlName = "orphaned"
152155 }
153- if dep , ok := deploymentMap [depUID ]; ok {
154- city = dep .Spec .CityCode
155- if dep .Spec .WorkloadRef .Name != "" {
156- wlName = dep .Spec .WorkloadRef .Name
156+
157+ // Prefer self-describing labels stamped at creation time (fast path —
158+ // no join needed). Fall back to the WorkloadDeployment join for older
159+ // instances that predate the labels.
160+ labelCity := inst .Labels [computev1alpha .CityCodeLabel ]
161+ labelWLName := inst .Labels [computev1alpha .WorkloadNameLabel ]
162+
163+ if labelCity != "" && labelWLName != "" {
164+ // Both labels present: no join needed.
165+ city = labelCity
166+ wlName = labelWLName
167+ } else {
168+ // At least one label absent — fall back to WorkloadDeployment lookup.
169+ // Prefer the explicit WorkloadDeploymentNameLabel; fall back to
170+ // deriving the WD name from the Instance name for existing instances
171+ // that predate the label.
172+ depName := inst .Labels [computev1alpha .WorkloadDeploymentNameLabel ]
173+ if depName == "" {
174+ depName = wdNameFromInstanceName (inst .Name )
175+ }
176+ if dep , ok := deploymentMap [depName ]; ok {
177+ if labelCity != "" {
178+ city = labelCity
179+ } else {
180+ city = dep .Spec .CityCode
181+ }
182+ if labelWLName != "" {
183+ wlName = labelWLName
184+ } else if dep .Spec .WorkloadRef .Name != "" {
185+ wlName = dep .Spec .WorkloadRef .Name
186+ }
187+ } else {
188+ // Deployment not found — use whatever labels we do have.
189+ if labelCity != "" {
190+ city = labelCity
191+ }
192+ if labelWLName != "" {
193+ wlName = labelWLName
194+ }
157195 }
158196 }
159197
@@ -278,20 +316,61 @@ func runDescribe(cmd *cobra.Command, args []string) error {
278316 return fmt .Errorf ("getting instance: %w" , err )
279317 }
280318
281- // Look up deployment.
282- deploymentUID := inst .Labels [computev1alpha .WorkloadDeploymentUIDLabel ]
319+ // Resolve CITY, WORKLOAD, and PLACEMENT. Prefer self-describing labels
320+ // stamped at creation time (no join needed). Fall back to a
321+ // WorkloadDeployment Get when any of the labels are absent, so that older
322+ // instances that predate the stamp still resolve correctly.
283323 workloadName := "orphaned"
284324 city := "unknown"
285325 placementName := ""
286326
287- if deploymentUID != "" {
288- depSelector := labels .SelectorFromSet (labels.Set {computev1alpha .WorkloadDeploymentUIDLabel : deploymentUID })
289- var depList computev1alpha.WorkloadDeploymentList
290- if err := c .List (ctx , & depList , client .InNamespace (util .ResourceNamespace ), client.MatchingLabelsSelector {Selector : depSelector }); err == nil && len (depList .Items ) > 0 {
291- dep := depList .Items [0 ]
292- city = dep .Spec .CityCode
293- placementName = dep .Spec .PlacementName
294- workloadName = dep .Spec .WorkloadRef .Name
327+ labelCity := inst .Labels [computev1alpha .CityCodeLabel ]
328+ labelWLName := inst .Labels [computev1alpha .WorkloadNameLabel ]
329+ labelPlacement := inst .Labels [computev1alpha .PlacementNameLabel ]
330+
331+ if labelCity != "" && labelWLName != "" && labelPlacement != "" {
332+ // All three labels present: no join needed.
333+ city = labelCity
334+ workloadName = labelWLName
335+ placementName = labelPlacement
336+ } else {
337+ // At least one label absent — fall back to WorkloadDeployment Get.
338+ // Prefer the WorkloadDeploymentNameLabel; fall back to deriving the WD
339+ // name from the Instance name for existing instances that lack the label.
340+ depName := inst .Labels [computev1alpha .WorkloadDeploymentNameLabel ]
341+ if depName == "" {
342+ depName = wdNameFromInstanceName (inst .Name )
343+ }
344+ if depName != "" {
345+ var dep computev1alpha.WorkloadDeployment
346+ if err := c .Get (ctx , types.NamespacedName {Namespace : util .ResourceNamespace , Name : depName }, & dep ); err == nil {
347+ if labelCity != "" {
348+ city = labelCity
349+ } else {
350+ city = dep .Spec .CityCode
351+ }
352+ if labelPlacement != "" {
353+ placementName = labelPlacement
354+ } else {
355+ placementName = dep .Spec .PlacementName
356+ }
357+ if labelWLName != "" {
358+ workloadName = labelWLName
359+ } else {
360+ workloadName = dep .Spec .WorkloadRef .Name
361+ }
362+ } else {
363+ // WD Get failed — use whatever labels we do have.
364+ if labelCity != "" {
365+ city = labelCity
366+ }
367+ if labelWLName != "" {
368+ workloadName = labelWLName
369+ }
370+ if labelPlacement != "" {
371+ placementName = labelPlacement
372+ }
373+ }
295374 }
296375 }
297376
@@ -385,6 +464,32 @@ func networkSummary(ifaces []computev1alpha.InstanceNetworkInterfaceStatus) stri
385464 return fmt .Sprintf ("External: %s Internal: %s" , extIP , intIP )
386465}
387466
467+ // wdNameFromInstanceName derives the WorkloadDeployment name from an Instance
468+ // name by stripping the trailing "-<ordinal>" suffix. Instance names follow the
469+ // convention "<wd-name>-<ordinal>" (e.g. "my-api-default-dfw-0" → "my-api-default-dfw").
470+ // This is used as a fallback when WorkloadDeploymentNameLabel is absent on older
471+ // instances that predate that label.
472+ //
473+ // If the name has no trailing numeric segment (not a standard instance name),
474+ // the original name is returned unchanged so callers can handle it gracefully.
475+ func wdNameFromInstanceName (instanceName string ) string {
476+ idx := strings .LastIndex (instanceName , "-" )
477+ if idx < 0 {
478+ return instanceName
479+ }
480+ suffix := instanceName [idx + 1 :]
481+ // The suffix must be entirely numeric digits to qualify as an ordinal.
482+ for _ , r := range suffix {
483+ if ! unicode .IsDigit (r ) {
484+ return instanceName
485+ }
486+ }
487+ if suffix == "" {
488+ return instanceName
489+ }
490+ return instanceName [:idx ]
491+ }
492+
388493// formatEnvVar renders a single EnvVar for display.
389494func formatEnvVar (e corev1.EnvVar ) string {
390495 if e .ValueFrom != nil {
0 commit comments