istio.io/istio@v0.0.0-20240520182934-d79c90f27776/istioctl/pkg/writer/ztunnel/configdump/workload.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 configdump 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "sort" 21 "strings" 22 23 "sigs.k8s.io/yaml" 24 ) 25 26 // WorkloadFilter is used to pass filter information into workload based config writer print functions 27 type WorkloadFilter struct { 28 Address string 29 Node string 30 Verbose bool 31 Namespace string 32 } 33 34 // Verify returns true if the passed workload matches the filter fields 35 func (wf *WorkloadFilter) Verify(workload *ZtunnelWorkload) bool { 36 if wf.Address == "" && wf.Node == "" && wf.Namespace == "" { 37 return true 38 } 39 40 if wf.Namespace != "" { 41 if !strings.EqualFold(workload.Namespace, wf.Namespace) { 42 return false 43 } 44 } 45 46 if wf.Address != "" { 47 var find bool 48 for _, ip := range workload.WorkloadIPs { 49 if strings.EqualFold(ip, wf.Address) { 50 find = true 51 break 52 } 53 } 54 if !find { 55 return false 56 } 57 } 58 if wf.Node != "" && !strings.EqualFold(workload.Node, wf.Node) { 59 return false 60 } 61 return true 62 } 63 64 // PrintWorkloadSummary prints a summary of the relevant listeners in the config dump to the ConfigWriter stdout 65 func (c *ConfigWriter) PrintWorkloadSummary(filter WorkloadFilter) error { 66 w := c.tabwriter() 67 zDump := c.ztunnelDump 68 69 verifiedWorkloads := make([]*ZtunnelWorkload, 0, len(zDump.Workloads)) 70 for _, wl := range zDump.Workloads { 71 if filter.Verify(wl) { 72 verifiedWorkloads = append(verifiedWorkloads, wl) 73 } 74 } 75 76 // Sort by name, node 77 sort.Slice(verifiedWorkloads, func(i, j int) bool { 78 in := verifiedWorkloads[i].Namespace + "." + verifiedWorkloads[i].Name 79 jn := verifiedWorkloads[j].Namespace + "." + verifiedWorkloads[j].Name 80 if in != jn { 81 return in < jn 82 } 83 iNode := verifiedWorkloads[i].Node 84 jNode := verifiedWorkloads[j].Node 85 return iNode < jNode 86 }) 87 88 if filter.Verbose { 89 fmt.Fprintln(w, "NAMESPACE\tPOD NAME\tIP\tNODE\tWAYPOINT\tPROTOCOL") 90 } else { 91 fmt.Fprintln(w, "NAMESPACE\tPOD NAME\tIP\tNODE") 92 } 93 94 for _, wl := range verifiedWorkloads { 95 var ip string 96 if len(wl.WorkloadIPs) > 0 { 97 ip = wl.WorkloadIPs[0] 98 } 99 if filter.Verbose { 100 waypoint := waypointName(wl, zDump.Services) 101 fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\n", 102 wl.Namespace, wl.Name, ip, wl.Node, waypoint, wl.Protocol) 103 } else { 104 fmt.Fprintf(w, "%v\t%v\t%v\t%v\n", wl.Namespace, wl.Name, ip, wl.Node) 105 } 106 } 107 return w.Flush() 108 } 109 110 // PrintWorkloadDump prints the relevant workloads in the config dump to the ConfigWriter stdout 111 func (c *ConfigWriter) PrintWorkloadDump(filter WorkloadFilter, outputFormat string) error { 112 zDump := c.ztunnelDump 113 filteredWorkloads := []*ZtunnelWorkload{} 114 for _, workload := range zDump.Workloads { 115 if filter.Verify(workload) { 116 filteredWorkloads = append(filteredWorkloads, workload) 117 } 118 } 119 out, err := json.MarshalIndent(filteredWorkloads, "", " ") 120 if err != nil { 121 return fmt.Errorf("failed to marshal workloads: %v", err) 122 } 123 if outputFormat == "yaml" { 124 if out, err = yaml.JSONToYAML(out); err != nil { 125 return err 126 } 127 } 128 fmt.Fprintln(c.Stdout, string(out)) 129 return nil 130 } 131 132 func waypointName(wl *ZtunnelWorkload, services map[string]*ZtunnelService) string { 133 if wl.Waypoint == nil { 134 return "None" 135 } 136 137 if svc, ok := services[wl.Waypoint.Destination]; ok { 138 return svc.Name 139 } 140 141 return "NA" // Shouldn't normally reach here 142 } 143 144 func serviceWaypointName(svc *ZtunnelService, services map[string]*ZtunnelService) string { 145 if svc.Waypoint == nil { 146 return "None" 147 } 148 149 if svc, ok := services[svc.Waypoint.Destination]; ok { 150 return svc.Name 151 } 152 153 return "NA" // Shouldn't normally reach here 154 }