// 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
}