Skip to content

Commit bede0a0

Browse files
authoredMar 21, 2023
Add X-Ray daemon (#14)
1 parent 6fbdf2e commit bede0a0

File tree

7 files changed

+397
-48
lines changed

7 files changed

+397
-48
lines changed
 

‎cmd/localstack/awsutil.go

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package main
88
import (
99
"context"
1010
"fmt"
11-
"github.com/jessevdk/go-flags"
1211
log "github.com/sirupsen/logrus"
1312
"go.amzn.com/lambda/interop"
1413
"go.amzn.com/lambda/rapidcore"
@@ -27,29 +26,12 @@ const (
2726
runtimeBootstrap = "/var/runtime/bootstrap"
2827
)
2928

30-
type options struct {
31-
LogLevel string `long:"log-level" default:"info" description:"log level"`
32-
InitCachingEnabled bool `long:"enable-init-caching" description:"Enable support for Init Caching"`
33-
}
34-
35-
func getCLIArgs() (options, []string) {
36-
var opts options
37-
parser := flags.NewParser(&opts, flags.IgnoreUnknown)
38-
args, err := parser.ParseArgs(os.Args)
39-
40-
if err != nil {
41-
log.WithError(err).Fatal("Failed to parse command line arguments:", os.Args)
42-
}
43-
44-
return opts, args
45-
}
46-
4729
func isBootstrapFileExist(filePath string) bool {
4830
file, err := os.Stat(filePath)
4931
return !os.IsNotExist(err) && !file.IsDir()
5032
}
5133

52-
func getBootstrap(args []string, opts options) (*rapidcore.Bootstrap, string) {
34+
func getBootstrap(args []string) (*rapidcore.Bootstrap, string) {
5335
var bootstrapLookupCmd []string
5436
var handler string
5537
currentWorkingDir := "/var/task" // default value
@@ -148,7 +130,7 @@ func resetListener(changeChannel <-chan bool, server *CustomInteropServer) {
148130

149131
func RunDNSRewriter(opts *LsOpts, ctx context.Context) {
150132
if opts.EnableDnsServer != "1" {
151-
log.Debugln("Dns server disabled")
133+
log.Debugln("DNS server disabled.")
152134
return
153135
}
154136
dnsForwarder, err := NewDnsForwarder(opts.LocalstackIP)
@@ -160,7 +142,7 @@ func RunDNSRewriter(opts *LsOpts, ctx context.Context) {
160142
dnsForwarder.Start()
161143

162144
<-ctx.Done()
163-
log.Debugln("Shutting down dns server")
145+
log.Debugln("DNS server stopped")
164146
}
165147

166148
func RunHotReloadingListener(server *CustomInteropServer, targetPaths []string, ctx context.Context) {
@@ -234,11 +216,11 @@ func InitHandler(sandbox Sandbox, functionVersion string, timeout int64) (time.T
234216
// pass to rapid
235217
sandbox.Init(&interop.Init{
236218
Handler: GetenvWithDefault("AWS_LAMBDA_FUNCTION_HANDLER", os.Getenv("_HANDLER")),
237-
CorrelationID: "initCorrelationID",
219+
CorrelationID: "initCorrelationID", // TODO
238220
AwsKey: os.Getenv("AWS_ACCESS_KEY_ID"),
239221
AwsSecret: os.Getenv("AWS_SECRET_ACCESS_KEY"),
240222
AwsSession: os.Getenv("AWS_SESSION_TOKEN"),
241-
XRayDaemonAddress: "0.0.0.0:0", // TODO
223+
XRayDaemonAddress: GetenvWithDefault("AWS_XRAY_DAEMON_ADDRESS", "127.0.0.1:2000"),
242224
FunctionName: GetenvWithDefault("AWS_LAMBDA_FUNCTION_NAME", "test_function"),
243225
FunctionVersion: functionVersion,
244226

‎cmd/localstack/custom_interop.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@ func (l *LocalStackAdapter) SendStatus(status LocalStackStatus) error {
4444
return nil
4545
}
4646

47+
// The InvokeRequest is sent by LocalStack to trigger an invocation
4748
type InvokeRequest struct {
4849
InvokeId string `json:"invoke-id"`
4950
InvokedFunctionArn string `json:"invoked-function-arn"`
5051
Payload string `json:"payload"`
52+
TraceId string `json:"trace-id"`
5153
}
5254

55+
// The ErrorResponse is sent TO LocalStack when encountering an error
5356
type ErrorResponse struct {
5457
ErrorMessage string `json:"errorMessage"`
5558
ErrorType string `json:"errorType,omitempty"`
@@ -95,10 +98,8 @@ func NewCustomInteropServer(lsOpts *LsOpts, delegate rapidcore.InteropServer, lo
9598
Payload: strings.NewReader(invokeR.Payload), // r.Body,
9699
NeedDebugLogs: true,
97100
CorrelationID: "invokeCorrelationID",
98-
// TODO: should we use the env _X_AMZN_TRACE_ID here or get the value from the request headers from the direct invoke?
99-
// for now we just set a "real" static value
100-
TraceID: "Root=1-53cfd31b-192638fa13e39d2c2bcea001;Parent=365fb4b15f2e3987;Sampled=0", // r.Header.Get("X-Amzn-Trace-Id"),
101-
//TraceID: GetEnvOrDie("_X_AMZN_TRACE_ID"), // r.Header.Get("X-Amzn-Trace-Id"),
101+
102+
TraceID: invokeR.TraceId,
102103
// TODO: set correct segment ID from request
103104
//LambdaSegmentID: "LambdaSegmentID", // r.Header.Get("X-Amzn-Segment-Id"),
104105
//CognitoIdentityID: "",

‎cmd/localstack/main.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ type LsOpts struct {
2424
HotReloadingPaths []string
2525
EnableDnsServer string
2626
LocalstackIP string
27+
InitLogLevel string
28+
EdgePort string
2729
}
2830

2931
func GetEnvOrDie(env string) string {
@@ -36,12 +38,15 @@ func GetEnvOrDie(env string) string {
3638

3739
func InitLsOpts() *LsOpts {
3840
return &LsOpts{
41+
// required
3942
RuntimeEndpoint: GetEnvOrDie("LOCALSTACK_RUNTIME_ENDPOINT"),
4043
RuntimeId: GetEnvOrDie("LOCALSTACK_RUNTIME_ID"),
4144
// optional with default
4245
InteropPort: GetenvWithDefault("LOCALSTACK_INTEROP_PORT", "9563"),
4346
InitTracingPort: GetenvWithDefault("LOCALSTACK_RUNTIME_TRACING_PORT", "9564"),
4447
User: GetenvWithDefault("LOCALSTACK_USER", "sbx_user1051"),
48+
InitLogLevel: GetenvWithDefault("LOCALSTACK_INIT_LOG_LEVEL", "debug"),
49+
EdgePort: GetenvWithDefault("EDGE_PORT", "4566"),
4550
// optional or empty
4651
CodeArchives: os.Getenv("LOCALSTACK_CODE_ARCHIVES"),
4752
HotReloadingPaths: strings.Split(GetenvWithDefault("LOCALSTACK_HOT_RELOADING_PATHS", ""), ","),
@@ -62,6 +67,7 @@ func UnsetLsEnvs() {
6267
"LOCALSTACK_CODE_ARCHIVES",
6368
"LOCALSTACK_HOT_RELOADING_PATHS",
6469
"LOCALSTACK_ENABLE_DNS_SERVER",
70+
"LOCALSTACK_INIT_LOG_LEVEL",
6571
// Docker container ID
6672
"HOSTNAME",
6773
// User
@@ -78,22 +84,33 @@ func main() {
7884
// we're setting this to the same value as in the official RIE
7985
debug.SetGCPercent(33)
8086

87+
// configuration parsing
8188
lsOpts := InitLsOpts()
8289
UnsetLsEnvs()
8390

84-
// set up logging (logrus)
85-
//log.SetFormatter(&log.JSONFormatter{})
86-
//log.SetLevel(log.TraceLevel)
87-
log.SetLevel(log.DebugLevel)
91+
// set up logging
8892
log.SetReportCaller(true)
93+
switch lsOpts.InitLogLevel {
94+
case "debug":
95+
log.SetLevel(log.DebugLevel)
96+
case "trace":
97+
log.SetFormatter(&log.JSONFormatter{})
98+
log.SetLevel(log.TraceLevel)
99+
default:
100+
log.Fatal("Invalid value for LOCALSTACK_INIT_LOG_LEVEL")
101+
}
102+
103+
// enable dns server
104+
dnsServerContext, stopDnsServer := context.WithCancel(context.Background())
105+
go RunDNSRewriter(lsOpts, dnsServerContext)
89106

90107
// download code archive if env variable is set
91108
if err := DownloadCodeArchives(lsOpts.CodeArchives); err != nil {
92109
log.Fatal("Failed to download code archives")
93110
}
94-
// enable dns server
95-
dnsServerContext, stopDnsServer := context.WithCancel(context.Background())
96-
go RunDNSRewriter(lsOpts, dnsServerContext)
111+
112+
// parse CLI args
113+
bootstrap, handler := getBootstrap(os.Args)
97114

98115
// Switch to non-root user and drop root privileges
99116
if IsRootUser() && lsOpts.User != "" {
@@ -108,23 +125,36 @@ func main() {
108125
UserLogger().Debugln("Process running as non-root user.")
109126
}
110127

111-
// parse CLI args
112-
opts, args := getCLIArgs()
113-
bootstrap, handler := getBootstrap(args, opts)
114128
logCollector := NewLogCollector()
129+
130+
// file watcher for hot-reloading
115131
fileWatcherContext, cancelFileWatcher := context.WithCancel(context.Background())
132+
133+
// build sandbox
116134
sandbox := rapidcore.
117135
NewSandboxBuilder(bootstrap).
136+
//SetTracer(tracer).
118137
AddShutdownFunc(func() {
119-
log.Debugln("Closing contexts")
138+
log.Debugln("Stopping file watcher")
120139
cancelFileWatcher()
140+
log.Debugln("Stopping DNS server")
121141
stopDnsServer()
122142
}).
123-
AddShutdownFunc(func() { os.Exit(0) }).
124143
SetExtensionsFlag(true).
125144
SetInitCachingFlag(true).
126145
SetTailLogOutput(logCollector)
127146

147+
// xray daemon
148+
xrayConfig := initConfig("http://" + lsOpts.LocalstackIP + ":" + lsOpts.EdgePort)
149+
d := initDaemon(xrayConfig)
150+
sandbox.AddShutdownFunc(func() {
151+
log.Debugln("Shutting down xray daemon")
152+
d.stop()
153+
log.Debugln("Flushing segments in xray daemon")
154+
d.close()
155+
})
156+
runDaemon(d) // async
157+
128158
defaultInterop := sandbox.InteropServer()
129159
interopServer := NewCustomInteropServer(lsOpts, defaultInterop, logCollector)
130160
sandbox.SetInteropServer(interopServer)
@@ -136,7 +166,7 @@ func main() {
136166
go sandbox.Create()
137167

138168
// get timeout
139-
invokeTimeoutEnv := GetEnvOrDie("AWS_LAMBDA_FUNCTION_TIMEOUT")
169+
invokeTimeoutEnv := GetEnvOrDie("AWS_LAMBDA_FUNCTION_TIMEOUT") // TODO: collect all AWS_* env parsing
140170
invokeTimeoutSeconds, err := strconv.Atoi(invokeTimeoutEnv)
141171
if err != nil {
142172
log.Fatalln(err)

‎cmd/localstack/xraydaemon.go

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
// The implementation is based on the open source AWS xray daemon https://github.com/aws/aws-xray-daemon (cmd/tracing/daemon.go)
2+
// It has been adapted for the use as a library and not as a separate executable.
3+
// The config is set directly in code instead of loading it from a config file
4+
5+
package main
6+
7+
import (
8+
"encoding/json"
9+
"io"
10+
"math"
11+
"net"
12+
"os"
13+
"sync/atomic"
14+
"time"
15+
16+
"github.com/aws/aws-xray-daemon/pkg/bufferpool"
17+
"github.com/aws/aws-xray-daemon/pkg/cfg"
18+
"github.com/aws/aws-xray-daemon/pkg/conn"
19+
"github.com/aws/aws-xray-daemon/pkg/logger"
20+
"github.com/aws/aws-xray-daemon/pkg/processor"
21+
"github.com/aws/aws-xray-daemon/pkg/proxy"
22+
"github.com/aws/aws-xray-daemon/pkg/ringbuffer"
23+
"github.com/aws/aws-xray-daemon/pkg/socketconn"
24+
"github.com/aws/aws-xray-daemon/pkg/socketconn/udp"
25+
"github.com/aws/aws-xray-daemon/pkg/telemetry"
26+
"github.com/aws/aws-xray-daemon/pkg/tracesegment"
27+
"github.com/aws/aws-xray-daemon/pkg/util"
28+
29+
"github.com/aws/aws-sdk-go/aws"
30+
log "github.com/cihub/seelog"
31+
"github.com/shirou/gopsutil/mem"
32+
)
33+
34+
const protocolSeparator = "\n"
35+
36+
// Log Rotation Size is 50 MB
37+
const logRotationSize int64 = 50 * 1024 * 1024
38+
39+
var noMetadata = true
40+
41+
var logFile string
42+
var logLevel string
43+
44+
// Daemon reads trace segments from X-Ray daemon address and
45+
// send to X-Ray service.
46+
type Daemon struct {
47+
receiverCount int
48+
processorCount int
49+
receiveBufferSize int
50+
51+
// Boolean channel, set to true if error is received reading from Socket.
52+
done chan bool
53+
54+
// Ring buffer, used to stored segments received.
55+
std *ringbuffer.RingBuffer
56+
57+
// Counter for segments read by daemon.
58+
count uint64
59+
60+
// Instance of socket connection.
61+
sock socketconn.SocketConn
62+
63+
// Reference to buffer pool.
64+
pool *bufferpool.BufferPool
65+
66+
// Reference to Processor.
67+
processor *processor.Processor
68+
69+
// HTTP Proxy server
70+
server *proxy.Server
71+
}
72+
73+
func initConfig(endpoint string) *cfg.Config {
74+
xrayConfig := cfg.DefaultConfig()
75+
xrayConfig.Socket.UDPAddress = "127.0.0.1:2000"
76+
xrayConfig.Socket.TCPAddress = "127.0.0.1:2000"
77+
xrayConfig.Endpoint = endpoint
78+
xrayConfig.NoVerifySSL = util.Bool(true) // obvious
79+
xrayConfig.LocalMode = util.Bool(true) // skip EC2 metadata check
80+
xrayConfig.Region = GetEnvOrDie("AWS_REGION")
81+
xrayConfig.Logging.LogLevel = "info"
82+
//xrayConfig.TotalBufferSizeMB
83+
//xrayConfig.RoleARN = roleARN
84+
85+
return xrayConfig
86+
}
87+
88+
func initDaemon(config *cfg.Config) *Daemon {
89+
if logFile != "" {
90+
var fileWriter io.Writer
91+
if *config.Logging.LogRotation {
92+
// Empty Archive path as code does not archive logs
93+
apath := ""
94+
maxSize := logRotationSize
95+
// Keep one rolled over log file around
96+
maxRolls := 1
97+
archiveExplode := false
98+
fileWriter, _ = log.NewRollingFileWriterSize(logFile, 0, apath, maxSize, maxRolls, 0, archiveExplode)
99+
} else {
100+
fileWriter, _ = log.NewFileWriter(logFile)
101+
}
102+
logger.LoadLogConfig(fileWriter, config, logLevel)
103+
} else {
104+
newWriter, _ := log.NewConsoleWriter()
105+
logger.LoadLogConfig(newWriter, config, logLevel)
106+
}
107+
defer log.Flush()
108+
109+
log.Infof("Initializing AWS X-Ray daemon %v", cfg.Version)
110+
111+
parameterConfig := cfg.ParameterConfigValue
112+
parameterConfig.Processor.BatchSize = 10
113+
parameterConfig.Processor.IdleTimeoutMillisecond = 1000
114+
receiveBufferSize := parameterConfig.Socket.BufferSizeKB * 1024
115+
116+
var sock socketconn.SocketConn
117+
118+
sock = udp.New(config.Socket.UDPAddress)
119+
120+
memoryLimit := evaluateBufferMemory(0)
121+
log.Infof("Using buffer memory limit of %v MB", memoryLimit)
122+
buffers, err := bufferpool.GetPoolBufferCount(memoryLimit, receiveBufferSize)
123+
if err != nil {
124+
log.Errorf("%v", err)
125+
os.Exit(1)
126+
}
127+
log.Infof("%v segment buffers allocated", buffers)
128+
bufferPool := bufferpool.Init(buffers, receiveBufferSize)
129+
std := ringbuffer.New(buffers, bufferPool)
130+
if config.Endpoint != "" {
131+
log.Debugf("Using Endpoint read from Config file: %s", config.Endpoint)
132+
}
133+
awsConfig, session := conn.GetAWSConfigSession(&conn.Conn{}, config, config.RoleARN, config.Region, noMetadata)
134+
log.Infof("Using region: %v", aws.StringValue(awsConfig.Region))
135+
136+
log.Debugf("ARN of the AWS resource running the daemon: %v", config.ResourceARN)
137+
telemetry.Init(awsConfig, session, config.ResourceARN, noMetadata)
138+
139+
// If calculated number of buffer is lower than our default, use calculated one. Otherwise, use default value.
140+
parameterConfig.Processor.BatchSize = util.GetMinIntValue(parameterConfig.Processor.BatchSize, buffers)
141+
142+
// Create proxy http server
143+
server, err := proxy.NewServer(config, awsConfig, session)
144+
if err != nil {
145+
log.Errorf("Unable to start http proxy server: %v", err)
146+
os.Exit(1)
147+
}
148+
processorCount := 2
149+
150+
daemon := &Daemon{
151+
receiverCount: parameterConfig.ReceiverRoutines,
152+
processorCount: processorCount,
153+
receiveBufferSize: receiveBufferSize,
154+
done: make(chan bool),
155+
std: std,
156+
pool: bufferPool,
157+
count: 0,
158+
sock: sock,
159+
server: server,
160+
processor: processor.New(awsConfig, session, processorCount, std, bufferPool, parameterConfig),
161+
}
162+
163+
return daemon
164+
}
165+
166+
func runDaemon(daemon *Daemon) {
167+
// Start http server for proxying requests to xray
168+
go daemon.server.Serve()
169+
170+
for i := 0; i < daemon.receiverCount; i++ {
171+
go daemon.poll()
172+
}
173+
}
174+
175+
func (d *Daemon) close() {
176+
for i := 0; i < d.receiverCount; i++ {
177+
<-d.done
178+
}
179+
// Signal routines to finish
180+
// This will push telemetry and customer segments in parallel
181+
d.std.Close()
182+
telemetry.T.Quit <- true
183+
184+
<-d.processor.Done
185+
<-telemetry.T.Done
186+
187+
log.Debugf("Trace segment: received: %d, truncated: %d, processed: %d", atomic.LoadUint64(&d.count), d.std.TruncatedCount(), d.processor.ProcessedCount())
188+
log.Debugf("Shutdown finished. Current epoch in nanoseconds: %v", time.Now().UnixNano())
189+
}
190+
191+
func (d *Daemon) stop() {
192+
d.sock.Close()
193+
d.server.Close()
194+
}
195+
196+
// Returns number of bytes read from socket connection.
197+
func (d *Daemon) read(buf *[]byte) int {
198+
bufVal := *buf
199+
rlen, err := d.sock.Read(bufVal)
200+
switch err := err.(type) {
201+
case net.Error:
202+
if !err.Temporary() {
203+
d.done <- true
204+
return -1
205+
}
206+
log.Errorf("daemon: net: err: %v", err)
207+
return 0
208+
case error:
209+
log.Errorf("daemon: socket: err: %v", err)
210+
return 0
211+
}
212+
return rlen
213+
}
214+
215+
func (d *Daemon) poll() {
216+
separator := []byte(protocolSeparator)
217+
fallBackBuffer := make([]byte, d.receiveBufferSize)
218+
splitBuf := make([][]byte, 2)
219+
220+
for {
221+
bufPointer := d.pool.Get()
222+
fallbackPointerUsed := false
223+
if bufPointer == nil {
224+
log.Debug("Pool does not have any buffer.")
225+
bufPointer = &fallBackBuffer
226+
fallbackPointerUsed = true
227+
}
228+
rlen := d.read(bufPointer)
229+
if rlen > 0 {
230+
telemetry.T.SegmentReceived(1)
231+
}
232+
if rlen == 0 {
233+
if !fallbackPointerUsed {
234+
d.pool.Return(bufPointer)
235+
}
236+
continue
237+
}
238+
if fallbackPointerUsed {
239+
log.Warn("Segment dropped. Consider increasing memory limit")
240+
telemetry.T.SegmentSpillover(1)
241+
continue
242+
} else if rlen == -1 {
243+
return
244+
}
245+
246+
buf := *bufPointer
247+
bufMessage := buf[0:rlen]
248+
249+
slices := util.SplitHeaderBody(&bufMessage, &separator, &splitBuf)
250+
if len(slices[1]) == 0 {
251+
log.Warnf("Missing header or segment: %s", string(slices[0]))
252+
d.pool.Return(bufPointer)
253+
telemetry.T.SegmentRejected(1)
254+
continue
255+
}
256+
257+
header := slices[0]
258+
payload := slices[1]
259+
headerInfo := tracesegment.Header{}
260+
json.Unmarshal(header, &headerInfo)
261+
262+
switch headerInfo.IsValid() {
263+
case true:
264+
default:
265+
log.Warnf("Invalid header: %s", string(header))
266+
d.pool.Return(bufPointer)
267+
telemetry.T.SegmentRejected(1)
268+
continue
269+
}
270+
271+
ts := &tracesegment.TraceSegment{
272+
Raw: &payload,
273+
PoolBuf: bufPointer,
274+
}
275+
276+
atomic.AddUint64(&d.count, 1)
277+
d.std.Send(ts)
278+
}
279+
}
280+
281+
func evaluateBufferMemory(cliBufferMemory int) int {
282+
var bufferMemoryMB int
283+
if cliBufferMemory > 0 {
284+
bufferMemoryMB = cliBufferMemory
285+
} else {
286+
vm, err := mem.VirtualMemory()
287+
if err != nil {
288+
log.Errorf("%v", err)
289+
os.Exit(1)
290+
}
291+
bufferMemoryLimitPercentageOfTotal := 0.01
292+
totalBytes := vm.Total
293+
bufferMemoryMB = int(math.Floor(bufferMemoryLimitPercentageOfTotal * float64(totalBytes) / float64(1024*1024)))
294+
}
295+
if bufferMemoryMB < 3 {
296+
log.Error("Not enough Buffers Memory Allocated. Min Buffers Memory required: 3 MB.")
297+
os.Exit(1)
298+
}
299+
return bufferMemoryMB
300+
}

‎debugging/init/var/rapid/entrypoint.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ LAMBDA_INIT_DELVE_PORT="${LAMBDA_INIT_DELVE_PORT:-40000}"
55
# Run init without delve debugger
66
#exec /var/rapid/init
77

8+
# Run init with delve debugger
89
exec /var/rapid/dlv --listen=:${LAMBDA_INIT_DELVE_PORT} --headless=true --api-version=2 --accept-multiclient exec /var/rapid/init

‎go.mod

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,34 @@ go 1.18
44

55
require (
66
github.com/aws/aws-lambda-go v1.20.0
7+
github.com/aws/aws-sdk-go v1.44.62
8+
github.com/aws/aws-xray-daemon v0.0.0-20230202010956-acaf06e9a638
9+
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575
710
github.com/fsnotify/fsnotify v1.6.0
811
github.com/go-chi/chi v4.1.2+incompatible
912
github.com/go-chi/render v1.0.1
1013
github.com/google/uuid v1.1.2
1114
github.com/jessevdk/go-flags v1.4.0
1215
github.com/miekg/dns v1.1.50
16+
github.com/shirou/gopsutil v2.19.10+incompatible
1317
github.com/sirupsen/logrus v1.6.0
1418
github.com/stretchr/testify v1.6.1
15-
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
19+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
1620
golang.org/x/sys v0.1.0
1721
)
1822

1923
require (
24+
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
2025
github.com/davecgh/go-spew v1.1.1 // indirect
26+
github.com/go-ole/go-ole v1.2.4 // indirect
27+
github.com/jmespath/go-jmespath v0.4.0 // indirect
2128
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
2229
github.com/pmezard/go-difflib v1.0.0 // indirect
2330
github.com/stretchr/objx v0.1.0 // indirect
24-
golang.org/x/mod v0.4.2 // indirect
31+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
2532
golang.org/x/net v0.1.0 // indirect
26-
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
27-
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
33+
golang.org/x/text v0.4.0 // indirect
34+
golang.org/x/tools v0.1.12 // indirect
35+
gopkg.in/yaml.v2 v2.2.8 // indirect
2836
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
2937
)

‎go.sum

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2+
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
3+
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
24
github.com/aws/aws-lambda-go v1.20.0 h1:ZSweJx/Hy9BoIDXKBEh16vbHH0t0dehnF8MKpMiOWc0=
35
github.com/aws/aws-lambda-go v1.20.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU=
6+
github.com/aws/aws-sdk-go v1.44.62 h1:N8qOPnBhl2ZCIFiqyB640Xt5CeX9D8CEVhG/Vj7jGJU=
7+
github.com/aws/aws-sdk-go v1.44.62/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
8+
github.com/aws/aws-xray-daemon v0.0.0-20230202010956-acaf06e9a638 h1:G0C87W0m2uyh3uHV24Q60JJx+AyJ3//gJjalvSizXhc=
9+
github.com/aws/aws-xray-daemon v0.0.0-20230202010956-acaf06e9a638/go.mod h1:glwf7zqf0NzGozJscRs0/xC+CpTU4DyMN4V9eXxD2Co=
10+
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=
11+
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
412
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
513
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
614
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -12,17 +20,26 @@ github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyN
1220
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
1321
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
1422
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
23+
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
24+
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
1525
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
1626
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1727
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
1828
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
29+
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
30+
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
31+
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
32+
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
1933
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
2034
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
2135
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
2236
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
37+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
2338
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2439
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2540
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
41+
github.com/shirou/gopsutil v2.19.10+incompatible h1:lA4Pi29JEVIQIgATSeftHSY0rMGI9CLrl2ZvDLiahto=
42+
github.com/shirou/gopsutil v2.19.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
2643
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
2744
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
2845
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -35,44 +52,54 @@ github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2
3552
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
3653
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3754
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
38-
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
3955
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
56+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
57+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
4058
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
4159
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
4260
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
4361
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
62+
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
4463
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
4564
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
4665
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
47-
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
4866
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
67+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
68+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4969
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
5070
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5171
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5272
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5373
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5474
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5575
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
76+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5677
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
78+
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5779
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5880
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
5981
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6082
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
83+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
6184
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
6285
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
6386
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
87+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
6488
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
89+
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
6590
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
6691
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
67-
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
6892
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
93+
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
94+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
6995
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
7096
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
71-
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
7297
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
7398
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
7499
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
75100
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
101+
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
102+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
76103
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
77104
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
78105
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)
Please sign in to comment.