Skip to content
This repository has been archived by the owner on Jul 9, 2024. It is now read-only.

Feature: allow plugin debugging #39

Merged
merged 2 commits into from
Jun 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/hashicorp/go-argmapper v0.2.0
github.com/hashicorp/go-hclog v0.14.1
github.com/hashicorp/go-multierror v1.1.0
github.com/hashicorp/go-plugin v1.3.0
github.com/hashicorp/go-plugin v1.4.2
github.com/hashicorp/hcl/v2 v2.6.0
github.com/iancoleman/strcase v0.1.2
github.com/kr/pretty v0.2.1 // indirect
Expand Down
5 changes: 2 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,14 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-argmapper v0.2.0 h1:hODvyLdq7akV0n6SbOP47VXZjAX1QrUvAveCA6qXSfQ=
github.com/hashicorp/go-argmapper v0.2.0/go.mod h1:WA3PocIo+40wf4ko3dRdL3DEgxIQB4qaqp+jVccLV1I=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.14.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8=
github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
github.com/hashicorp/go-plugin v1.4.2 h1:yFvG3ufXXpqiMiZx9HLcaK3XbIqQ1WJFR/F1a2CuVw0=
github.com/hashicorp/go-plugin v1.4.2/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o=
github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
Expand Down
124 changes: 122 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package sdk

import (
"context"
"encoding/json"
"fmt"
"github.com/fatih/color"
"github.com/mattn/go-colorable"
"os"
"os/signal"
"runtime"
"strings"
"time"

"github.com/fatih/color"
"github.com/hashicorp/go-argmapper"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin"
"github.com/mattn/go-colorable"

"github.com/hashicorp/waypoint-plugin-sdk/internal-shared/protomappers"
sdkplugin "github.com/hashicorp/waypoint-plugin-sdk/internal/plugin"
Expand Down Expand Up @@ -80,6 +87,7 @@ func Main(opts ...Option) {
),
GRPCServer: plugin.DefaultGRPCServer,
Logger: log,
Test: c.TestConfig,
})
}

Expand All @@ -91,6 +99,13 @@ type config struct {

// Mappers is the list of mapper functions.
Mappers []interface{}

// TestConfig should only be set when the plugin is being tested; it
// will opt out of go-plugin's lifecycle management and other features,
// and will use the supplied configuration options to control the
// plugin's lifecycle and communicate connection information. See the
// go-plugin GoDoc for more information.
TestConfig *plugin.ServeTestConfig
}

// Option modifies config. Zero or more can be passed to Main.
Expand Down Expand Up @@ -123,3 +138,108 @@ func WithComponents(cs ...interface{}) Option {
func WithMappers(ms ...interface{}) Option {
return func(c *config) { c.Mappers = append(c.Mappers, ms...) }
}

// DebugServe starts a plugin server in debug mode; this should only be used
// when the plugin will manage its own lifecycle. It is not recommended for
// normal usage; Serve is the correct function for that.
func DebugServe(ctx context.Context, opts ...Option) (ReattachConfig, <-chan struct{}, error) {
reattachCh := make(chan *plugin.ReattachConfig)
closeCh := make(chan struct{})

opts = append(opts, func(c *config) {
c.TestConfig = &plugin.ServeTestConfig{
Context: ctx,
ReattachConfigCh: reattachCh,
CloseCh: closeCh,
}
})

go Main(opts...)

var config *plugin.ReattachConfig
select {
case config = <-reattachCh:
case <-time.After(2 * time.Second):
return ReattachConfig{}, closeCh, fmt.Errorf("timeout waiting on reattach config")
}

if config == nil {
return ReattachConfig{}, closeCh, fmt.Errorf("nil reattach config received")
}

return ReattachConfig{
Protocol: string(config.Protocol),
ProtocolVersion: config.ProtocolVersion,
Pid: config.Pid,
Test: config.Test,
Addr: ReattachConfigAddr{
Network: config.Addr.Network(),
String: config.Addr.String(),
},
}, closeCh, nil
}

// Debug starts a debug server and controls its lifecycle, printing the
// information needed for Waypoint to connect to the plugin to stdout.
// os.Interrupt will be captured and used to stop the server.
func Debug(ctx context.Context, pluginAddr string, opts ...Option) error {
ctx, cancel := context.WithCancel(ctx)
// Ctrl-C will stop the server
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
defer func() {
signal.Stop(sigCh)
cancel()
}()
config, closeCh, err := DebugServe(ctx, opts...)
if err != nil {
return fmt.Errorf("Error launching debug server: %w", err)
}
go func() {
select {
case <-sigCh:
cancel()
case <-ctx.Done():
}
}()
reattachBytes, err := json.Marshal(map[string]ReattachConfig{
pluginAddr: config,
})
if err != nil {
return fmt.Errorf("Error building reattach string: %w", err)
}

reattachStr := string(reattachBytes)

fmt.Printf("Plugin started, to attach Waypoint set the WP_REATTACH_PLUGINS env var:\n\n")
switch runtime.GOOS {
case "windows":
fmt.Printf("\tCommand Prompt:\tset \"WP_REATTACH_PLUGINS=%s\"\n", reattachStr)
fmt.Printf("\tPowerShell:\t$env:WP_REATTACH_PLUGINS='%s'\n", strings.ReplaceAll(reattachStr, `'`, `''`))
case "linux", "darwin":
fmt.Printf("\tWP_REATTACH_PLUGINS='%s'\n", strings.ReplaceAll(reattachStr, `'`, `'"'"'`))
default:
fmt.Println(reattachStr)
}
fmt.Println("")

// wait for the server to be done
<-closeCh
return nil
}

// ReattachConfig holds the information Waypoint needs to be able to attach
// itself to a plugin process, so it can drive the process.
type ReattachConfig struct {
Protocol string
ProtocolVersion int
Pid int
Test bool
Addr ReattachConfigAddr
}

// ReattachConfigAddr is a JSON-encoding friendly version of net.Addr.
type ReattachConfigAddr struct {
Network string
String string
}
1 change: 0 additions & 1 deletion tools/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ import _ "github.com/golang/protobuf/proto"

//go:generate go install github.com/golang/protobuf/protoc-gen-go
import _ "github.com/golang/protobuf/protoc-gen-go"