-
Notifications
You must be signed in to change notification settings - Fork 238
/
Copy pathdebug.go
102 lines (89 loc) · 2.59 KB
/
debug.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
package plugin
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"os/signal"
"time"
"github.com/hashicorp/go-plugin"
)
// ReattachConfig holds the information Terraform needs to be able to attach
// itself to a provider process, so it can drive the process.
type ReattachConfig struct {
Protocol string
Pid int
Test bool
Addr ReattachConfigAddr
}
// ReattachConfigAddr is a JSON-encoding friendly version of net.Addr.
type ReattachConfigAddr struct {
Network string
String string
}
// DebugServe starts a plugin server in debug mode; this should only be used
// when the provider 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 *ServeOpts) (ReattachConfig, <-chan struct{}, error) {
reattachCh := make(chan *plugin.ReattachConfig)
closeCh := make(chan struct{})
opts.TestConfig = &plugin.ServeTestConfig{
Context: ctx,
ReattachConfigCh: reattachCh,
CloseCh: closeCh,
}
go Serve(opts)
var config *plugin.ReattachConfig
select {
case config = <-reattachCh:
case <-time.After(2 * time.Second):
return ReattachConfig{}, closeCh, errors.New("timeout waiting on reattach config")
}
if config == nil {
return ReattachConfig{}, closeCh, errors.New("nil reattach config received")
}
return ReattachConfig{
Protocol: string(config.Protocol),
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 Terraform to connect to the provider to stdout.
// os.Interrupt will be captured and used to stop the server.
func Debug(ctx context.Context, providerAddr string, opts *ServeOpts) 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():
}
}()
reattachStr, err := json.Marshal(map[string]ReattachConfig{
providerAddr: config,
})
if err != nil {
return fmt.Errorf("Error building reattach string: %w", err)
}
fmt.Printf("Provider server started; to attach Terraform, set TF_REATTACH_PROVIDERS to the following:\n%s\n", string(reattachStr))
// wait for the server to be done
<-closeCh
return nil
}