istio.io/istio@v0.0.0-20240520182934-d79c90f27776/istioctl/pkg/writer/ztunnel/configdump/connections.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 "cmp" 19 "encoding/json" 20 "fmt" 21 "net" 22 "strings" 23 24 "sigs.k8s.io/yaml" 25 26 "istio.io/istio/pkg/maps" 27 "istio.io/istio/pkg/slices" 28 ) 29 30 type ConnectionsFilter struct { 31 Namespace string 32 Direction string 33 Raw bool 34 } 35 36 func (c *ConfigWriter) PrintConnectionsDump(filter ConnectionsFilter, outputFormat string) error { 37 d := c.ztunnelDump 38 workloads := maps.Values(d.WorkloadState) 39 workloads = slices.SortFunc(workloads, func(a, b WorkloadState) int { 40 if r := cmp.Compare(a.Info.Namespace, b.Info.Namespace); r != 0 { 41 return r 42 } 43 return cmp.Compare(a.Info.Namespace, b.Info.Namespace) 44 }) 45 workloads = slices.FilterInPlace(workloads, func(state WorkloadState) bool { 46 if filter.Namespace != "" && filter.Namespace != state.Info.Namespace { 47 return false 48 } 49 return true 50 }) 51 out, err := json.MarshalIndent(workloads, "", " ") 52 if err != nil { 53 return fmt.Errorf("failed to marshal workloads: %v", err) 54 } 55 if outputFormat == "yaml" { 56 if out, err = yaml.JSONToYAML(out); err != nil { 57 return err 58 } 59 } 60 fmt.Fprintln(c.Stdout, string(out)) 61 return nil 62 } 63 64 func (c *ConfigWriter) PrintConnectionsSummary(filter ConnectionsFilter) error { 65 w := c.tabwriter() 66 d := c.ztunnelDump 67 serviceNames := map[string]string{} 68 workloadNames := map[string]string{} 69 for netIP, s := range d.Services { 70 _, ip, _ := strings.Cut(netIP, "/") 71 serviceNames[ip] = s.Hostname 72 } 73 for netIP, s := range d.Workloads { 74 _, ip, _ := strings.Cut(netIP, "/") 75 workloadNames[ip] = s.Name + "." + s.Namespace 76 } 77 lookupIP := func(addr string) string { 78 if filter.Raw { 79 return addr 80 } 81 ip, port, _ := net.SplitHostPort(addr) 82 if s, f := serviceNames[ip]; f { 83 return net.JoinHostPort(s, port) 84 } 85 if w, f := workloadNames[ip]; f { 86 return net.JoinHostPort(w, port) 87 } 88 return addr 89 } 90 fmt.Fprintln(w, "WORKLOAD\tDIRECTION\tLOCAL\tREMOTE\tREMOTE TARGET") 91 workloads := maps.Values(d.WorkloadState) 92 workloads = slices.SortFunc(workloads, func(a, b WorkloadState) int { 93 if r := cmp.Compare(a.Info.Namespace, b.Info.Namespace); r != 0 { 94 return r 95 } 96 return cmp.Compare(a.Info.Namespace, b.Info.Namespace) 97 }) 98 for _, wl := range workloads { 99 if filter.Namespace != "" && filter.Namespace != wl.Info.Namespace { 100 continue 101 } 102 name := fmt.Sprintf("%s.%s", wl.Info.Name, wl.Info.Namespace) 103 if filter.Direction != "outbound" { 104 for _, c := range wl.Connections.Inbound { 105 fmt.Fprintf(w, "%v\tInbound\t%v\t%v\t%v\n", name, lookupIP(c.ActualDst), lookupIP(c.Src), c.OriginalDst) 106 } 107 } 108 if filter.Direction != "inbound" { 109 for _, c := range wl.Connections.Outbound { 110 fmt.Fprintf(w, "%v\tOutbound\t%v\t%v\t%v\n", name, lookupIP(c.Src), lookupIP(c.ActualDst), lookupIP(c.OriginalDst)) 111 } 112 } 113 } 114 return w.Flush() 115 }