cmd/nodeadm/debug/debug.go (89 lines of code) (raw):
package debug
import (
"context"
"fmt"
"os"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/smithy-go/logging"
"github.com/integrii/flaggy"
"go.uber.org/zap"
"github.com/aws/eks-hybrid/internal/api"
"github.com/aws/eks-hybrid/internal/aws/sts"
"github.com/aws/eks-hybrid/internal/cli"
"github.com/aws/eks-hybrid/internal/configprovider"
"github.com/aws/eks-hybrid/internal/creds"
"github.com/aws/eks-hybrid/internal/errors"
"github.com/aws/eks-hybrid/internal/kubelet"
"github.com/aws/eks-hybrid/internal/kubernetes"
"github.com/aws/eks-hybrid/internal/logger"
"github.com/aws/eks-hybrid/internal/node"
"github.com/aws/eks-hybrid/internal/validation"
)
const debugHelpText = `Examples:
# Debug using a local config file
nodeadm debug --config-source file://nodeConfig.yaml
Documentation:
https://docs.aws.amazon.com/eks/latest/userguide/hybrid-nodes-nodeadm.html#_debug`
func NewCommand() cli.Command {
debug := debug{}
debug.cmd = flaggy.NewSubcommand("debug")
debug.cmd.String(&debug.nodeConfigSource, "c", "config-source", "Source of node configuration. The format is a URI with supported schemes: [file, imds].")
debug.cmd.Bool(&debug.noColor, "", "no-color", "If set, suppresses color output.")
debug.cmd.Description = "Debug the node registration process"
debug.cmd.AdditionalHelpPrepend = debugHelpText
return &debug
}
type debug struct {
cmd *flaggy.Subcommand
nodeConfigSource string
noColor bool
}
func (c *debug) Flaggy() *flaggy.Subcommand {
return c.cmd
}
func (c *debug) Run(log *zap.Logger, opts *cli.GlobalOptions) error {
ctx := context.Background()
ctx = logger.NewContext(ctx, log)
if c.nodeConfigSource == "" {
flaggy.ShowHelpAndExit("--config-source is a required flag. The format is a URI with supported schemes: [file, imds]." +
" For example on hybrid nodes --config-source file://nodeConfig.yaml")
}
provider, err := configprovider.BuildConfigProvider(c.nodeConfigSource)
if err != nil {
return err
}
nodeConfig, err := provider.Provide()
if err != nil {
return err
}
awsConfig, err := creds.ReadConfig(ctx, nodeConfig, config.WithLogger(logging.Nop{}))
if err != nil {
return err
}
printer := validation.NewPrinterWithStdCapture("stderr", c.noColor)
if err := printer.Init(); err != nil {
return err
}
defer printer.Close()
// We want to capture stderr and let the printer control it.
// When the AWS SDK calls the credentials_process for IAM Roles Anywhere
// or when the k8s client-go calls the aws-iam-authenticator binary, those processes
// output to stderr and those logs are not returned to the caller in the go error.
// In order to not have interfere with the printer logs or get lost,
// we just override the global stderr and restore after we are done running validations.
originalStderr := os.Stderr
defer func() { os.Stderr = originalStderr }()
os.Stderr = printer.File
runner := validation.NewRunner[*api.NodeConfig](printer)
apiServerValidator := node.NewAPIServerValidator(kubelet.New())
runner.Register(creds.Validations(awsConfig, nodeConfig)...)
runner.Register(
validation.New("aws-auth", sts.NewAuthenticationValidator(awsConfig).Run),
runner.UntilError(
validation.New("k8s-endpoint-network", kubernetes.NewAccessValidator(awsConfig).Run),
validation.New("k8s-authentication", apiServerValidator.MakeAuthenticatedRequest),
validation.New("k8s-identity", apiServerValidator.CheckIdentity),
validation.New("k8s-vpc-network", apiServerValidator.CheckVPCEndpointAccess),
),
)
if err := runner.Sequentially(ctx, nodeConfig); err != nil {
fmt.Println("")
fmt.Println("Issues found during validation. Please follow the remediation advice above.")
// Errors are already presented by the printer
// so we just need to exit with a non-zero status code
return errors.NewSilent(err)
}
return nil
}