istio.io/istio@v0.0.0-20240520182934-d79c90f27776/istioctl/pkg/tag/revision.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 tag 16 17 import ( 18 "context" 19 "fmt" 20 21 admitv1 "k8s.io/api/admissionregistration/v1" 22 corev1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 25 "istio.io/api/label" 26 iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" 27 "istio.io/istio/pkg/kube" 28 ) 29 30 // PodFilteredInfo represents a small subset of fields from 31 // Pod object in Kubernetes. Exposed for integration test 32 type PodFilteredInfo struct { 33 Namespace string `json:"namespace"` 34 Name string `json:"name"` 35 Address string `json:"address"` 36 Status corev1.PodPhase `json:"status"` 37 Age string `json:"age"` 38 } 39 40 // IstioOperatorCRInfo represents a tiny subset of fields from 41 // IstioOperator CR. This structure is used for displaying data. 42 // Exposed for integration test 43 type IstioOperatorCRInfo struct { 44 IOP *iopv1alpha1.IstioOperator `json:"-"` 45 Namespace string `json:"namespace"` 46 Name string `json:"name"` 47 Profile string `json:"profile"` 48 Components []string `json:"components,omitempty"` 49 Customizations []IopDiff `json:"customizations,omitempty"` 50 } 51 52 type IopDiff struct { 53 Path string `json:"path"` 54 Value string `json:"value"` 55 } 56 57 // MutatingWebhookConfigInfo represents a tiny subset of fields from 58 // MutatingWebhookConfiguration kubernetes object. This is exposed for 59 // integration tests only 60 type MutatingWebhookConfigInfo struct { 61 Name string `json:"name"` 62 Revision string `json:"revision"` 63 Tag string `json:"tag,omitempty"` 64 } 65 66 // NsInfo represents namespace related information like pods running there. 67 // It is used to display data and is exposed for integration tests. 68 type NsInfo struct { 69 Name string `json:"name,omitempty"` 70 Pods []*PodFilteredInfo `json:"pods,omitempty"` 71 } 72 73 // RevisionDescription is used to display revision related information. 74 // This is exposed for integration tests. 75 type RevisionDescription struct { 76 IstioOperatorCRs []*IstioOperatorCRInfo `json:"istio_operator_crs,omitempty"` 77 Webhooks []*MutatingWebhookConfigInfo `json:"webhooks,omitempty"` 78 ControlPlanePods []*PodFilteredInfo `json:"control_plane_pods,omitempty"` 79 IngressGatewayPods []*PodFilteredInfo `json:"ingess_gateways,omitempty"` 80 EgressGatewayPods []*PodFilteredInfo `json:"egress_gateways,omitempty"` 81 NamespaceSummary map[string]*NsInfo `json:"namespace_summary,omitempty"` 82 } 83 84 func ListRevisionDescriptions(client kube.CLIClient) (map[string]*RevisionDescription, error) { 85 revisions := map[string]*RevisionDescription{} 86 87 // Get a list of control planes which are installed in remote clusters 88 // In this case, it is possible that they only have webhooks installed. 89 webhooks, err := Webhooks(context.Background(), client) 90 if err != nil { 91 return nil, fmt.Errorf("error while listing mutating webhooks: %v", err) 92 } 93 for _, hook := range webhooks { 94 rev := renderWithDefault(hook.GetLabels()[label.IoIstioRev.Name], DefaultRevisionName) 95 tagLabel := hook.GetLabels()[IstioTagLabel] 96 ri, revPresent := revisions[rev] 97 if revPresent { 98 if tagLabel != "" { 99 ri.Webhooks = append(ri.Webhooks, &MutatingWebhookConfigInfo{ 100 Name: hook.Name, 101 Revision: rev, 102 Tag: tagLabel, 103 }) 104 } 105 } else { 106 revisions[rev] = &RevisionDescription{ 107 IstioOperatorCRs: []*IstioOperatorCRInfo{}, 108 Webhooks: []*MutatingWebhookConfigInfo{{Name: hook.Name, Revision: rev, Tag: tagLabel}}, 109 } 110 } 111 } 112 113 return revisions, nil 114 } 115 116 func Webhooks(ctx context.Context, client kube.CLIClient) ([]admitv1.MutatingWebhookConfiguration, error) { 117 hooks, err := client.Kube().AdmissionregistrationV1().MutatingWebhookConfigurations().List(ctx, metav1.ListOptions{}) 118 if err != nil { 119 return []admitv1.MutatingWebhookConfiguration{}, err 120 } 121 return hooks.Items, nil 122 } 123 124 func renderWithDefault(s, def string) string { 125 if s != "" { 126 return s 127 } 128 return def 129 }