consul/troubleshoot/proxy/troubleshoot_proxy.go

101 lines
2.7 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package troubleshoot
import (
"fmt"
"net"
envoy_admin_v3 "github.com/envoyproxy/go-control-plane/envoy/admin/v3"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/troubleshoot/validate"
)
type Troubleshoot struct {
client *api.Client
envoyAddr net.IPAddr
envoyAdminPort string
TroubleshootInfo
}
type TroubleshootInfo struct {
envoyClusters *envoy_admin_v3.Clusters
envoyConfigDump *envoy_admin_v3.ConfigDump
envoyCerts *envoy_admin_v3.Certificates
envoyStats []*envoy_admin_v3.SimpleMetric
}
func NewTroubleshoot(envoyIP *net.IPAddr, envoyPort string) (*Troubleshoot, error) {
cfg := api.DefaultConfig()
c, err := api.NewClient(cfg)
if err != nil {
return nil, err
}
if envoyIP == nil {
return nil, fmt.Errorf("envoy address is empty")
}
return &Troubleshoot{
client: c,
envoyAddr: *envoyIP,
envoyAdminPort: envoyPort,
}, nil
}
func (t *Troubleshoot) RunAllTests(upstreamEnvoyID, upstreamIP string) (validate.Messages, error) {
var allTestMessages validate.Messages
// Get all info from proxy to set up validations.
err := t.GetEnvoyConfigDump()
if err != nil {
return nil, fmt.Errorf("unable to get Envoy config dump: cannot connect to Envoy: %w", err)
}
err = t.getEnvoyClusters()
if err != nil {
return nil, fmt.Errorf("unable to get Envoy clusters: cannot connect to Envoy: %w", err)
}
certs, err := t.getEnvoyCerts()
if err != nil {
return nil, fmt.Errorf("unable to get Envoy certificates: cannot connect to Envoy: %w", err)
}
indexedResources, err := ProxyConfigDumpToIndexedResources(t.envoyConfigDump)
if err != nil {
return nil, fmt.Errorf("unable to index Envoy resources: %w", err)
}
// Validate certs.
messages := t.validateCerts(certs)
allTestMessages = append(allTestMessages, messages...)
if errors := messages.Errors(); len(errors) == 0 {
msg := validate.Message{
Success: true,
Message: "Certificates are valid",
}
allTestMessages = append(allTestMessages, msg)
}
// getStats usage example
messages, err = t.troubleshootStats()
if err != nil {
return nil, fmt.Errorf("unable to get stats: %w", err)
}
allTestMessages = append(allTestMessages, messages...)
// Validate listeners, routes, clusters, endpoints.
messages = Validate(indexedResources, upstreamEnvoyID, upstreamIP, true, t.envoyClusters)
allTestMessages = append(allTestMessages, messages...)
if errors := messages.Errors(); len(errors) == 0 {
msg := validate.Message{
Success: true,
Message: "Upstream resources are valid",
}
allTestMessages = append(allTestMessages, msg)
}
return allTestMessages, nil
}