mirror of https://github.com/hashicorp/consul
Browse Source
* get upstream IPs * separate test data * fix lint issue * fix lint issuepull/14186/head
malizz
2 years ago
committed by
GitHub
5 changed files with 277 additions and 40 deletions
@ -0,0 +1,90 @@ |
|||||||
|
{ |
||||||
|
"name": "outbound_listener:127.0.0.1:15001", |
||||||
|
"address": { |
||||||
|
"socket_address": { |
||||||
|
"address": "127.0.0.1", |
||||||
|
"port_value": 15001 |
||||||
|
} |
||||||
|
}, |
||||||
|
"filter_chains": [ |
||||||
|
{ |
||||||
|
"filter_chain_match": { |
||||||
|
"prefix_ranges": [ |
||||||
|
{ |
||||||
|
"address_prefix": "10.244.0.63", |
||||||
|
"prefix_len": 32 |
||||||
|
}, |
||||||
|
{ |
||||||
|
"address_prefix": "10.244.0.64", |
||||||
|
"prefix_len": 32 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"filters": [ |
||||||
|
{ |
||||||
|
"name": "envoy.filters.network.tcp_proxy", |
||||||
|
"typed_config": { |
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||||
|
"stat_prefix": "upstream.foo.default.default.dc1", |
||||||
|
"cluster": "passthrough~foo.default.dc1.internal.dc1.consul" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"filter_chain_match": { |
||||||
|
"prefix_ranges": [ |
||||||
|
{ |
||||||
|
"address_prefix": "10.96.5.96", |
||||||
|
"prefix_len": 32 |
||||||
|
}, |
||||||
|
{ |
||||||
|
"address_prefix": "240.0.0.1", |
||||||
|
"prefix_len": 32 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"filters": [ |
||||||
|
{ |
||||||
|
"name": "envoy.filters.network.http_connection_manager", |
||||||
|
"typed_config": { |
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", |
||||||
|
"stat_prefix": "upstream.foo.default.default.dc1", |
||||||
|
"route_config": { |
||||||
|
"name": "foo", |
||||||
|
"virtual_hosts": [ |
||||||
|
{ |
||||||
|
"name": "foo.default.default.dc1", |
||||||
|
"domains": [ |
||||||
|
"*" |
||||||
|
], |
||||||
|
"routes": [ |
||||||
|
{ |
||||||
|
"match": { |
||||||
|
"prefix": "/" |
||||||
|
}, |
||||||
|
"route": { |
||||||
|
"cluster": "foo.default.dc1.internal.dc1.consul" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"http_filters": [ |
||||||
|
{ |
||||||
|
"name": "envoy.filters.http.router", |
||||||
|
"typed_config": { |
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" |
||||||
|
} |
||||||
|
} |
||||||
|
], |
||||||
|
"tracing": { |
||||||
|
"random_sampling": {} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,120 @@ |
|||||||
|
package troubleshoot |
||||||
|
|
||||||
|
import ( |
||||||
|
envoy_admin_v3 "github.com/envoyproxy/go-control-plane/envoy/admin/v3" |
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" |
||||||
|
envoy_resource_v3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" |
||||||
|
|
||||||
|
"github.com/hashicorp/consul/envoyextensions/extensioncommon" |
||||||
|
"google.golang.org/protobuf/proto" |
||||||
|
) |
||||||
|
|
||||||
|
type UpstreamIP struct { |
||||||
|
IPs []string |
||||||
|
IsVirtual bool |
||||||
|
ClusterNames map[string]struct{} |
||||||
|
} |
||||||
|
|
||||||
|
func (t *Troubleshoot) GetUpstreams() ([]string, []UpstreamIP, error) { |
||||||
|
|
||||||
|
upstream_envoy_ids := []string{} |
||||||
|
upstream_ips := []UpstreamIP{} |
||||||
|
|
||||||
|
err := t.GetEnvoyConfigDump() |
||||||
|
if err != nil { |
||||||
|
return nil, nil, err |
||||||
|
} |
||||||
|
|
||||||
|
for _, cfg := range t.envoyConfigDump.Configs { |
||||||
|
switch cfg.TypeUrl { |
||||||
|
case listeners: |
||||||
|
lcd := &envoy_admin_v3.ListenersConfigDump{} |
||||||
|
|
||||||
|
err := proto.Unmarshal(cfg.GetValue(), lcd) |
||||||
|
if err != nil { |
||||||
|
return nil, nil, err |
||||||
|
} |
||||||
|
|
||||||
|
for _, listener := range lcd.GetDynamicListeners() { |
||||||
|
|
||||||
|
eid := envoyID(listener.Name) |
||||||
|
|
||||||
|
if eid != "" && eid != "public_listener" && |
||||||
|
eid != "outbound_listener" && eid != "inbound_listener" { |
||||||
|
upstream_envoy_ids = append(upstream_envoy_ids, eid) |
||||||
|
} else if eid == "outbound_listener" { |
||||||
|
l := &envoy_listener_v3.Listener{} |
||||||
|
err = proto.Unmarshal(listener.GetActiveState().GetListener().GetValue(), l) |
||||||
|
if err != nil { |
||||||
|
return nil, nil, err |
||||||
|
} |
||||||
|
|
||||||
|
upstream_ips, err = getUpstreamIPsFromFilterChain(l.GetFilterChains()) |
||||||
|
if err != nil { |
||||||
|
return nil, nil, err |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return upstream_envoy_ids, upstream_ips, nil |
||||||
|
} |
||||||
|
|
||||||
|
func getUpstreamIPsFromFilterChain(filterChains []*envoy_listener_v3.FilterChain) ([]UpstreamIP, error) { |
||||||
|
if filterChains == nil { |
||||||
|
return []UpstreamIP{}, nil |
||||||
|
} |
||||||
|
|
||||||
|
upstreamIPs := []UpstreamIP{} |
||||||
|
for _, fc := range filterChains { |
||||||
|
|
||||||
|
if fc.GetFilters() == nil { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if fc.GetFilterChainMatch() == nil { |
||||||
|
continue |
||||||
|
} |
||||||
|
if fc.GetFilterChainMatch().GetPrefixRanges() == nil { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
cidrs := fc.GetFilterChainMatch().GetPrefixRanges() |
||||||
|
ips := []string{} |
||||||
|
|
||||||
|
for _, cidr := range cidrs { |
||||||
|
ips = append(ips, cidr.AddressPrefix) |
||||||
|
} |
||||||
|
|
||||||
|
for _, filter := range fc.GetFilters() { |
||||||
|
isVirtual := false |
||||||
|
|
||||||
|
if filter.GetTypedConfig() == nil { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
clusterNames := map[string]struct{}{} |
||||||
|
|
||||||
|
if config := envoy_resource_v3.GetHTTPConnectionManager(filter); config != nil { |
||||||
|
isVirtual = true |
||||||
|
|
||||||
|
cfg := config.GetRouteConfig() |
||||||
|
|
||||||
|
clusterNames = extensioncommon.RouteClusterNames(cfg) |
||||||
|
} |
||||||
|
if config := extensioncommon.GetTCPProxy(filter); config != nil { |
||||||
|
if config.GetCluster() != "" { |
||||||
|
clusterNames[config.GetCluster()] = struct{}{} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
upstreamIPs = append(upstreamIPs, UpstreamIP{ |
||||||
|
IPs: ips, |
||||||
|
IsVirtual: isVirtual, |
||||||
|
ClusterNames: clusterNames, |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return upstreamIPs, nil |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
package troubleshoot |
||||||
|
|
||||||
|
import ( |
||||||
|
"io" |
||||||
|
"os" |
||||||
|
"testing" |
||||||
|
|
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" |
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
"google.golang.org/protobuf/encoding/protojson" |
||||||
|
) |
||||||
|
|
||||||
|
func TestGetUpstreamIPsFromFilterChain(t *testing.T) { |
||||||
|
file, err := os.Open("testdata/listeners.json") |
||||||
|
require.NoError(t, err) |
||||||
|
jsonBytes, err := io.ReadAll(file) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
expected := []UpstreamIP{ |
||||||
|
{ |
||||||
|
IPs: []string{ |
||||||
|
"10.244.0.63", |
||||||
|
"10.244.0.64", |
||||||
|
}, |
||||||
|
IsVirtual: false, |
||||||
|
ClusterNames: map[string]struct{}{ |
||||||
|
"passthrough~foo.default.dc1.internal.dc1.consul": {}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
IPs: []string{ |
||||||
|
"10.96.5.96", |
||||||
|
"240.0.0.1", |
||||||
|
}, |
||||||
|
IsVirtual: true, |
||||||
|
ClusterNames: map[string]struct{}{ |
||||||
|
"foo.default.dc1.internal.dc1.consul": {}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
var listener envoy_listener_v3.Listener |
||||||
|
unmarshal := &protojson.UnmarshalOptions{ |
||||||
|
DiscardUnknown: true, |
||||||
|
} |
||||||
|
err = unmarshal.Unmarshal(jsonBytes, &listener) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
upstream_ips, err := getUpstreamIPsFromFilterChain(listener.GetFilterChains()) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.Equal(t, expected, upstream_ips) |
||||||
|
} |
Loading…
Reference in new issue