istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/config/mesh/kubemesh/watcher.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package kubemesh 16 17 import ( 18 "fmt" 19 20 v1 "k8s.io/api/core/v1" 21 22 meshconfig "istio.io/api/mesh/v1alpha1" 23 "istio.io/istio/pkg/config/mesh" 24 "istio.io/istio/pkg/kube" 25 "istio.io/istio/pkg/kube/watcher/configmapwatcher" 26 "istio.io/istio/pkg/log" 27 ) 28 29 // NewConfigMapWatcher creates a new Watcher for changes to the given ConfigMap. 30 func NewConfigMapWatcher(client kube.Client, namespace, name, key string, multiWatch bool, stop <-chan struct{}) *mesh.MultiWatcher { 31 w := mesh.NewMultiWatcher(mesh.DefaultMeshConfig()) 32 c := configmapwatcher.NewController(client, namespace, name, func(cm *v1.ConfigMap) { 33 meshNetworks, err := ReadNetworksConfigMap(cm, "meshNetworks") 34 if err != nil { 35 // Keep the last known config in case there's a misconfiguration issue. 36 log.Errorf("failed to read meshNetworks config from ConfigMap: %v", err) 37 return 38 } 39 if meshNetworks != nil { 40 w.SetNetworks(meshNetworks) 41 } 42 if multiWatch { 43 meshConfig := meshConfigMapData(cm, key) 44 w.HandleMeshConfigData(meshConfig) 45 return 46 } 47 // Original behavior - just per-revision config 48 meshConfig, err := ReadConfigMap(cm, key) 49 if err != nil { 50 // Keep the last known config in case there's a misconfiguration issue. 51 log.Errorf("failed to read mesh config from ConfigMap: %v", err) 52 return 53 } 54 w.HandleMeshConfig(meshConfig) 55 }) 56 57 go c.Run(stop) 58 59 // Ensure the ConfigMap is initially loaded if present. 60 if !client.WaitForCacheSync("configmap watcher", stop, c.HasSynced) { 61 log.Error("failed to wait for cache sync") 62 } 63 return w 64 } 65 66 func AddUserMeshConfig(client kube.Client, watcher mesh.Watcher, namespace, key, userMeshConfig string, stop <-chan struct{}) { 67 c := configmapwatcher.NewController(client, namespace, userMeshConfig, func(cm *v1.ConfigMap) { 68 meshConfig := meshConfigMapData(cm, key) 69 watcher.HandleUserMeshConfig(meshConfig) 70 }) 71 72 go c.Run(stop) 73 if !client.WaitForCacheSync("user mesh config", stop, c.HasSynced) { 74 log.Error("failed to wait for cache sync") 75 } 76 } 77 78 func meshConfigMapData(cm *v1.ConfigMap, key string) string { 79 if cm == nil { 80 return "" 81 } 82 83 cfgYaml, exists := cm.Data[key] 84 if !exists { 85 return "" 86 } 87 88 return cfgYaml 89 } 90 91 func ReadConfigMap(cm *v1.ConfigMap, key string) (*meshconfig.MeshConfig, error) { 92 if cm == nil { 93 log.Info("no ConfigMap found, using default MeshConfig config") 94 return mesh.DefaultMeshConfig(), nil 95 } 96 97 cfgYaml, exists := cm.Data[key] 98 if !exists { 99 return nil, fmt.Errorf("missing ConfigMap key %q", key) 100 } 101 102 meshConfig, err := mesh.ApplyMeshConfigDefaults(cfgYaml) 103 if err != nil { 104 return nil, fmt.Errorf("failed reading MeshConfig config: %v. YAML:\n%s", err, cfgYaml) 105 } 106 107 log.Info("Loaded MeshConfig config from Kubernetes API server.") 108 return meshConfig, nil 109 } 110 111 func ReadNetworksConfigMap(cm *v1.ConfigMap, key string) (*meshconfig.MeshNetworks, error) { 112 if cm == nil { 113 log.Info("no ConfigMap found, using existing MeshNetworks config") 114 return nil, nil 115 } 116 117 cfgYaml, exists := cm.Data[key] 118 if !exists { 119 return nil, nil 120 } 121 122 meshNetworks, err := mesh.ParseMeshNetworks(cfgYaml) 123 if err != nil { 124 return nil, fmt.Errorf("failed reading MeshNetworks config: %v. YAML:\n%s", err, cfgYaml) 125 } 126 127 log.Info("Loaded MeshNetworks config from Kubernetes API server.") 128 return meshNetworks, nil 129 }