|
7 | 7 | "bytes" |
8 | 8 | "crypto/sha256" |
9 | 9 | "encoding/hex" |
| 10 | + "encoding/json" |
10 | 11 | "fmt" |
11 | 12 | "log" |
12 | 13 | "maps" |
@@ -154,10 +155,24 @@ func buildIncomingKubeconfig(items []v1alpha1.ClusterKubeconfig) (*clientcmdapi. |
154 | 155 |
|
155 | 156 | if len(ckc.Spec.Kubeconfig.Clusters) > 0 { |
156 | 157 | clusterItem := ckc.Spec.Kubeconfig.Clusters[0] |
| 158 | + |
157 | 159 | kubeconfig.Clusters[clusterItem.Name] = &clientcmdapi.Cluster{ |
158 | 160 | Server: clusterItem.Cluster.Server, |
159 | 161 | CertificateAuthorityData: clusterItem.Cluster.CertificateAuthorityData, |
160 | 162 | } |
| 163 | + |
| 164 | + // Add/overwrite a "labels" named extension with the labels from the ClusterKubeconfig metadata. |
| 165 | + if len(ckc.Labels) > 0 { |
| 166 | + labelsJSON, err := json.Marshal(ckc.Labels) |
| 167 | + if err != nil { |
| 168 | + return nil, fmt.Errorf("failed to marshal labels for cluster %q: %w", clusterItem.Name, err) |
| 169 | + } |
| 170 | + if kubeconfig.Clusters[clusterItem.Name].Extensions == nil { |
| 171 | + kubeconfig.Clusters[clusterItem.Name].Extensions = map[string]runtime.Object{} |
| 172 | + } |
| 173 | + kubeconfig.Clusters[clusterItem.Name].Extensions["labels"] = &runtime.Unknown{Raw: labelsJSON} |
| 174 | + } |
| 175 | + |
161 | 176 | } |
162 | 177 | } |
163 | 178 |
|
@@ -267,9 +282,10 @@ func mergeKubeconfig(localConfig *clientcmdapi.Config, serverConfig *clientcmdap |
267 | 282 | // Add the managed cluster from serverConfig to localConfig |
268 | 283 | localConfig.Clusters[managedName] = serverCluster |
269 | 284 | } else { |
270 | | - // Check if Server or CertificateAuthorityData has changed |
| 285 | + // Check if Server, CertificateAuthorityData or the labels extension has changed |
271 | 286 | if localCluster.Server != serverCluster.Server || |
272 | | - !bytes.Equal(localCluster.CertificateAuthorityData, serverCluster.CertificateAuthorityData) { |
| 287 | + !bytes.Equal(localCluster.CertificateAuthorityData, serverCluster.CertificateAuthorityData) || |
| 288 | + !labelsExtensionEqual(localCluster.Extensions, serverCluster.Extensions) { |
273 | 289 | localConfig.Clusters[managedName] = serverCluster |
274 | 290 | } |
275 | 291 | } |
@@ -468,6 +484,34 @@ func mergeAuthInfo(serverAuth, localAuth *clientcmdapi.AuthInfo) *clientcmdapi.A |
468 | 484 | return mergedAuth |
469 | 485 | } |
470 | 486 |
|
| 487 | +// labelsExtensionEqual returns true if the \"labels\" named extension is equal in both maps. |
| 488 | +func labelsExtensionEqual(a, b map[string]runtime.Object) bool { |
| 489 | + ar := extensionRaw(a, "labels") |
| 490 | + br := extensionRaw(b, "labels") |
| 491 | + return bytes.Equal(ar, br) |
| 492 | +} |
| 493 | + |
| 494 | +// extensionRaw extracts the raw JSON bytes for the given extension name, if present. |
| 495 | +func extensionRaw(m map[string]runtime.Object, name string) []byte { |
| 496 | + if m == nil { |
| 497 | + return nil |
| 498 | + } |
| 499 | + obj, ok := m[name] |
| 500 | + if !ok || obj == nil { |
| 501 | + return nil |
| 502 | + } |
| 503 | + switch t := obj.(type) { |
| 504 | + case *runtime.Unknown: |
| 505 | + return bytes.TrimSpace(t.Raw) |
| 506 | + default: |
| 507 | + b, err := json.Marshal(t) |
| 508 | + if err != nil { |
| 509 | + return nil |
| 510 | + } |
| 511 | + return bytes.TrimSpace(b) |
| 512 | + } |
| 513 | +} |
| 514 | + |
471 | 515 | func configWithContext(context, kubeconfigPath string) (*rest.Config, error) { |
472 | 516 | return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( |
473 | 517 | &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath}, |
|
0 commit comments