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  }