istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/config/analysis/analyzers/util/in_mesh.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 util 16 17 import ( 18 appsv1 "k8s.io/api/apps/v1" 19 v1 "k8s.io/api/core/v1" 20 21 "istio.io/api/label" 22 "istio.io/istio/pkg/config/analysis" 23 "istio.io/istio/pkg/config/constants" 24 "istio.io/istio/pkg/config/resource" 25 "istio.io/istio/pkg/config/schema/gvk" 26 "istio.io/istio/pkg/slices" 27 ) 28 29 // DeploymentInMesh returns true if deployment is in the service mesh (has sidecar) 30 func DeploymentInMesh(r *resource.Instance, c analysis.Context) bool { 31 d := r.Message.(*appsv1.DeploymentSpec) 32 return inMesh(d.Template.Annotations, d.Template.Labels, 33 resource.Namespace(r.Metadata.FullName.Namespace.String()), d.Template.Spec.Containers, c) 34 } 35 36 // PodInMesh returns true if a Pod is in the service mesh (has sidecar) 37 func PodInMesh(r *resource.Instance, c analysis.Context) bool { 38 p := r.Message.(*v1.PodSpec) 39 return inMesh(r.Metadata.Annotations, r.Metadata.Labels, 40 r.Metadata.FullName.Namespace, append(slices.Clone(p.Containers), p.InitContainers...), c) 41 } 42 43 // PodInAmbientMode returns true if a Pod is in the service mesh with the ambient mode 44 func PodInAmbientMode(r *resource.Instance) bool { 45 if r == nil { 46 return false 47 } 48 49 return r.Metadata.Annotations[constants.AmbientRedirection] == constants.AmbientRedirectionEnabled 50 } 51 52 // NamespaceInAmbientMode returns true if a Namespace is configured as a ambient namespace. 53 func NamespaceInAmbientMode(r *resource.Instance) bool { 54 if r == nil { 55 return false 56 } 57 // If there is a sidecar injection label, then we assume the namespace is not in ambient mode 58 if r.Metadata.Labels[InjectionLabelName] == InjectionLabelEnableValue { 59 return false 60 } 61 if v, ok := r.Metadata.Labels[label.IoIstioRev.Name]; ok && v != "" { 62 return false 63 } 64 return r.Metadata.Labels[constants.DataplaneModeLabel] == constants.DataplaneModeAmbient 65 } 66 67 func inMesh(annos, labels map[string]string, namespace resource.Namespace, containers []v1.Container, c analysis.Context) bool { 68 // If pod has the sidecar container set, then, the pod is in the mesh 69 if hasIstioProxy(containers) { 70 return true 71 } 72 73 // If Pod has labels, return the injection label value 74 if piv, ok := getPodSidecarInjectionStatus(labels); ok { 75 return piv 76 } 77 78 // If Pod has annotation, return the injection annotation value 79 if piv, ok := getPodSidecarInjectionStatus(annos); ok { 80 return piv 81 } 82 83 // In case the annotation is not present but there is a auto-injection label on the namespace, 84 // return the auto-injection label status 85 if niv, nivok := getNamesSidecarInjectionStatus(namespace, c); nivok { 86 return niv 87 } 88 89 return false 90 } 91 92 // getPodSidecarInjectionStatus returns two booleans: enabled and ok. 93 // enabled is true when deployment d PodSpec has either the label/annotation 'sidecar.istio.io/inject: "true"' 94 // ok is true when the PodSpec doesn't have the 'sidecar.istio.io/inject' label/annotation present. 95 func getPodSidecarInjectionStatus(metadata map[string]string) (enabled bool, ok bool) { 96 v, ok := metadata[label.SidecarInject.Name] 97 return v == "true", ok 98 } 99 100 // autoInjectionEnabled returns two booleans: enabled and ok. 101 // enabled is true when namespace ns has 'istio-injection' label set to 'enabled' 102 // ok is true when the namespace doesn't have the label 'istio-injection' 103 func getNamesSidecarInjectionStatus(ns resource.Namespace, c analysis.Context) (enabled bool, ok bool) { 104 enabled, ok = false, false 105 106 namespace := c.Find(gvk.Namespace, resource.NewFullName("", resource.LocalName(ns))) 107 if namespace != nil { 108 enabled, ok = namespace.Metadata.Labels[InjectionLabelName] == InjectionLabelEnableValue, true 109 } 110 111 return enabled, ok 112 } 113 114 func hasIstioProxy(containers []v1.Container) bool { 115 proxyImage := "" 116 for _, container := range containers { 117 if container.Name == IstioProxyName { 118 proxyImage = container.Image 119 break 120 } 121 } 122 123 return proxyImage != "" 124 }