istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/util/k8s.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 "context" 19 "fmt" 20 "strconv" 21 22 "github.com/prometheus/prometheus/util/strutil" 23 v1 "k8s.io/api/core/v1" 24 "k8s.io/apimachinery/pkg/api/errors" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime/schema" 27 "k8s.io/client-go/kubernetes" 28 29 "istio.io/api/label" 30 iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" 31 "istio.io/istio/pkg/config/constants" 32 "istio.io/istio/pkg/kube" 33 ) 34 35 // GKString differs from default representation of GroupKind 36 func GKString(gvk schema.GroupKind) string { 37 return fmt.Sprintf("%s/%s", gvk.Group, gvk.Kind) 38 } 39 40 // ValidateIOPCAConfig validates if the IstioOperator CA configs are applicable to the K8s cluster 41 func ValidateIOPCAConfig(client kube.Client, iop *iopv1alpha1.IstioOperator) error { 42 globalI := iop.Spec.Values.AsMap()["global"] 43 global, ok := globalI.(map[string]any) 44 if !ok { 45 // This means no explicit global configuration. Still okay 46 return nil 47 } 48 ca, ok := global["pilotCertProvider"].(string) 49 if !ok { 50 // This means the default pilotCertProvider is being used 51 return nil 52 } 53 if ca == "kubernetes" { 54 ver, err := client.GetKubernetesVersion() 55 if err != nil { 56 return fmt.Errorf("failed to determine support for K8s legacy signer. Use the --force flag to ignore this: %v", err) 57 } 58 59 if kube.IsAtLeastVersion(client, 22) { 60 return fmt.Errorf("configuration PILOT_CERT_PROVIDER=%s not supported in Kubernetes %v."+ 61 "Please pick another value for PILOT_CERT_PROVIDER", ca, ver.String()) 62 } 63 } 64 return nil 65 } 66 67 // CreateNamespace creates a namespace using the given k8s interface. 68 func CreateNamespace(cs kubernetes.Interface, namespace string, network string, dryRun bool) error { 69 if dryRun { 70 scope.Infof("Not applying Namespace %s because of dry run.", namespace) 71 return nil 72 } 73 if namespace == "" { 74 // Setup default namespace 75 namespace = constants.IstioSystemNamespace 76 } 77 // check if the namespace already exists. If yes, do nothing. If no, create a new one. 78 if _, err := cs.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}); err != nil { 79 if errors.IsNotFound(err) { 80 ns := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{ 81 Name: namespace, 82 Labels: map[string]string{}, 83 }} 84 if network != "" { 85 ns.Labels[label.TopologyNetwork.Name] = network 86 } 87 _, err := cs.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{}) 88 if err != nil { 89 return fmt.Errorf("failed to create namespace %v: %v", namespace, err) 90 } 91 92 return nil 93 } 94 95 return fmt.Errorf("failed to check if namespace %v exists: %v", namespace, err) 96 } 97 98 return nil 99 } 100 101 func PrometheusPathAndPort(pod *v1.Pod) (string, int, error) { 102 path := "/metrics" 103 port := 9090 104 for key, val := range pod.ObjectMeta.Annotations { 105 switch strutil.SanitizeLabelName(key) { 106 case "prometheus_io_port": 107 p, err := strconv.Atoi(val) 108 if err != nil { 109 return "", 0, fmt.Errorf("failed to parse port from annotation: %v", err) 110 } 111 112 port = p 113 case "prometheus_io_path": 114 path = val 115 } 116 } 117 118 return path, port, nil 119 }