-
Notifications
You must be signed in to change notification settings - Fork 4.4k
/
troubleshoot_upstreams.go
132 lines (110 loc) · 3.74 KB
/
troubleshoot_upstreams.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package upstreams
import (
"flag"
"fmt"
"net"
"os"
"strconv"
"strings"
"github.com/hashicorp/consul/command/cli"
"github.com/hashicorp/consul/command/flags"
troubleshoot "github.com/hashicorp/consul/troubleshoot/proxy"
)
func New(ui cli.Ui) *cmd {
c := &cmd{UI: ui}
c.init()
return c
}
type cmd struct {
UI cli.Ui
flags *flag.FlagSet
http *flags.HTTPFlags
help string
// flags
envoyAdminEndpoint string
}
func (c *cmd) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
defaultEnvoyAdminEndpoint := "localhost:19000"
if envoyAdminEndpoint := os.Getenv("ENVOY_ADMIN_ENDPOINT"); envoyAdminEndpoint != "" {
defaultEnvoyAdminEndpoint = envoyAdminEndpoint
}
c.flags.StringVar(&c.envoyAdminEndpoint, "envoy-admin-endpoint", defaultEnvoyAdminEndpoint, "The address:port that envoy's admin endpoint is on.")
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
c.help = flags.Usage(help, c.flags)
}
func (c *cmd) Run(args []string) int {
if err := c.flags.Parse(args); err != nil {
c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err))
return 1
}
adminAddr, adminPort, err := net.SplitHostPort(c.envoyAdminEndpoint)
if err != nil {
c.UI.Error("Invalid Envoy Admin endpoint: " + err.Error())
return 1
}
// Envoy requires IP addresses to bind too when using static so resolve DNS or
// localhost here.
adminBindIP, err := net.ResolveIPAddr("ip", adminAddr)
if err != nil {
c.UI.Error("Failed to resolve envoy admin endpoint: " + err.Error())
c.UI.Error("Please make sure Envoy's Admin API is enabled.")
return 1
}
t, err := troubleshoot.NewTroubleshoot(adminBindIP, adminPort)
if err != nil {
c.UI.Error("error generating troubleshoot client: " + err.Error())
return 1
}
envoyIDs, upstreamIPs, err := t.GetUpstreams()
if err != nil {
c.UI.Error("error calling GetUpstreams: " + err.Error())
return 1
}
c.UI.HeaderOutput(fmt.Sprintf("Upstreams (explicit upstreams only) (%v)", len(envoyIDs)))
for _, u := range envoyIDs {
c.UI.UnchangedOutput(u)
}
c.UI.HeaderOutput(fmt.Sprintf("Upstream IPs (transparent proxy only) (%v)", len(upstreamIPs)))
tbl := cli.NewTable("IPs ", "Virtual ", "Cluster Names")
for _, u := range upstreamIPs {
tbl.AddRow([]string{formatIPs(u.IPs), strconv.FormatBool(u.IsVirtual), formatClusterNames(u.ClusterNames)}, []string{})
}
c.UI.Table(tbl)
c.UI.UnchangedOutput("\nIf you cannot find the upstream address or cluster for a transparent proxy upstream:")
c.UI.UnchangedOutput("-> Check intentions: Transparent proxy upstreams are configured based on intentions. Make sure you " +
"have configured intentions to allow traffic to your upstream.")
c.UI.UnchangedOutput("-> To check that the right cluster is being dialed, run a DNS lookup " +
"for the upstream you are dialing. For example, run `dig backend.svc.consul` to return the IP address for the `backend` service. If the address you get from that is missing " +
"from the upstream IPs, it means that your proxy may be misconfigured.")
return 0
}
func (c *cmd) Synopsis() string {
return synopsis
}
func (c *cmd) Help() string {
return c.help
}
const (
synopsis = "Get upstream envoy identifiers for the current envoy instance"
help = `
Usage: consul troubleshoot upstreams [options]
Connects to local Envoy and lists upstream service envoy identifiers.
This command is used in combination with
'consul troubleshoot proxy' to diagnose issues in Consul service mesh.
Examples:
$ consul troubleshoot upstreams
`
)
func formatIPs(ips []string) string {
return strings.Join(ips, ", ")
}
func formatClusterNames(names map[string]struct{}) string {
var out []string
for k := range names {
out = append(out, k)
}
return strings.Join(out, ", ")
}