diff --git a/generator/test_case_generator.go b/generator/test_case_generator.go index a219652c8..af13f06cc 100644 --- a/generator/test_case_generator.go +++ b/generator/test_case_generator.go @@ -64,7 +64,8 @@ var testTypeToTestConfig = map[string][]testConfig{ {testDir: "./test/collection_interval"}, {testDir: "./test/metric_dimension"}, {testDir: "./test/restart"}, - {testDir: "./test/multi_config"}, + {testDir: "./test/xray"}, + {testDir: "./test/otlp"}, { testDir: "./test/acceptance", targets: map[string]map[string]struct{}{"os": {"ubuntu-20.04": {}}}, @@ -105,13 +106,11 @@ var testTypeToTestConfig = map[string][]testConfig{ */ "ec2_mac": { {testDir: "../../../test/feature/mac"}, - {testDir: "../../../test/run_as_user"}, }, "ec2_windows": { {testDir: "../../../test/feature/windows"}, {testDir: "../../../test/restart"}, {testDir: "../../../test/acceptance"}, - {testDir: "../../../test/multi_config"}, // assume role test doesn't add much value, and it already being tested with linux //{testDir: "../../../test/assume_role"}, }, diff --git a/go.mod b/go.mod index 05051c083..7d9cd75fd 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( collectd.org v0.5.0 github.com/DataDog/datadog-go v4.8.3+incompatible github.com/aws/aws-sdk-go v1.44.262 - github.com/aws/aws-sdk-go-v2 v1.19.1 + github.com/aws/aws-sdk-go-v2 v1.19.0 github.com/aws/aws-sdk-go-v2/config v1.18.10 github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.10.0 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.21 @@ -22,26 +22,33 @@ require ( github.com/aws/aws-sdk-go-v2/service/ecs v1.23.2 github.com/aws/aws-sdk-go-v2/service/s3 v1.30.1 github.com/aws/aws-sdk-go-v2/service/ssm v1.33.0 - github.com/aws/aws-sdk-go-v2/service/xray v1.16.15 - github.com/cenkalti/backoff/v4 v4.2.0 + github.com/aws/aws-sdk-go-v2/service/xray v1.16.14 + github.com/aws/aws-xray-sdk-go v1.8.1 + github.com/cenkalti/backoff/v4 v4.2.1 github.com/google/uuid v1.3.0 github.com/mitchellh/mapstructure v1.5.0 github.com/prozz/aws-embedded-metrics-golang v1.2.0 github.com/qri-io/jsonschema v0.2.1 github.com/shirou/gopsutil/v3 v3.23.3 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 + go.opentelemetry.io/contrib/propagators/aws v1.17.0 + go.opentelemetry.io/otel v1.16.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 + go.opentelemetry.io/otel/sdk v1.16.0 + go.opentelemetry.io/otel/trace v1.16.0 go.uber.org/multierr v1.9.0 golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 - golang.org/x/sys v0.6.0 + golang.org/x/sys v0.8.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/Microsoft/go-winio v0.6.0 // indirect + github.com/andybalholm/brotli v1.0.4 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.10 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.28 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.18 // indirect github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.13.20 // indirect @@ -55,17 +62,34 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.18.2 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/klauspost/compress v1.15.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/qri-io/jsonpointer v0.1.1 // indirect github.com/shoenig/go-m1cpu v0.1.4 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.34.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/mod v0.6.0 // indirect - golang.org/x/tools v0.2.0 // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.6.0 // indirect + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect + google.golang.org/grpc v1.55.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect ) diff --git a/go.sum b/go.sum index 74c317a7b..b664d244a 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,47 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aws/aws-sdk-go v1.44.262 h1:gyXpcJptWoNkK+DiAiaBltlreoWKQXjAIh6FRh60F+I= github.com/aws/aws-sdk-go v1.44.262/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= @@ -9,8 +49,8 @@ github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1 github.com/aws/aws-sdk-go-v2 v1.17.3/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.17.4/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2 v1.19.1 h1:STs0lbbpXu3byTPcnRLghs2DH0yk9qKDo27TyyJSKsM= -github.com/aws/aws-sdk-go-v2 v1.19.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= +github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= github.com/aws/aws-sdk-go-v2/config v1.18.10 h1:Znce11DWswdh+5kOsIp+QaNfY9igp1QUN+fZHCKmeCI= @@ -28,15 +68,15 @@ github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42 github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27/go.mod h1:a1/UpzeyBBerajpnP5nGZa9mGzsBn5cOKxm6NWQsvoI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28/go.mod h1:3lwChorpIM/BhImY/hy+Z6jekmN92cXGPI1QJasVPYY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 h1:kbk81RlPoC6e4co7cQx2FAvH9TgbzxIqCqiosAFiB+w= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36/go.mod h1:T8Jsn/uNL/AFOXrVYQ1YQaN1r9gN34JU1855/Lyjv+o= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19/go.mod h1:6Q0546uHDp421okhmmGfbxzq2hBqbXFNpi4k+Q1JnQA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21/go.mod h1:+Gxn8jYn5k9ebfHEqlhrMirFjSW0v0C9fI+KN5vk2kE= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22/go.mod h1:EqK7gVrIGAHyZItrD1D8B0ilgwMD1GiWAmbU4u/JHNk= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 h1:lMl8S5SB8jNCB+Sty2Em4lnu3IJytceHQd7qbmfqKL0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30/go.mod h1:v3GSCnFxbHzt9dlWBqvA1K1f9lmWuf4ztupZBCAIVs4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.28 h1:KeTxcGdNnQudb46oOl4d90f2I33DF/c6q3RnZAmvQdQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.28/go.mod h1:yRZVr/iT0AqyHeep00SZ4YfBAKojXz08w3XMBscdi0c= github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.18 h1:H/mF2LNWwX00lD6FlYfKpLLZgUW7oIzCBkig78x4Xok= @@ -78,48 +118,155 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.0 h1:Jfly6mRxk2ZOSlbCvZfKNS7T github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.0/go.mod h1:TZSH7xLO7+phDtViY/KUp9WGCJMQkLJ/VpgkTFd5gh8= github.com/aws/aws-sdk-go-v2/service/sts v1.18.2 h1:J/4wIaGInCEYCGhTSruxCxeoA5cy91a+JT7cHFKFSHQ= github.com/aws/aws-sdk-go-v2/service/sts v1.18.2/go.mod h1:+lGbb3+1ugwKrNTWcf2RT05Xmp543B06zDFTwiTLp7I= -github.com/aws/aws-sdk-go-v2/service/xray v1.16.15 h1:wpFgy/pHHhe+GJ6JX1DiXU7g/FW6E1lFQWVZAhIig3U= -github.com/aws/aws-sdk-go-v2/service/xray v1.16.15/go.mod h1:6n4KNI08QuLLxpmRzr4kHFBiLYrc02OTIz8cnDOm3Dc= +github.com/aws/aws-sdk-go-v2/service/xray v1.16.14 h1:wXpQ34XT8FXq7hH14OnwtHRVHFQjJRn72Fg6ClnC1fg= +github.com/aws/aws-sdk-go-v2/service/xray v1.16.14/go.mod h1:WPm8vBkEqJO6ykQhpNco10+rohJEo0VbjyZ+/sehjq0= +github.com/aws/aws-xray-sdk-go v1.8.1 h1:O4pXV+hnCskaamGsZnFpzHyAmgPGusBMN6i7nnsy0Fo= +github.com/aws/aws-xray-sdk-go v1.8.1/go.mod h1:wMmVYzej3sykAttNBkXQHK/+clAPWTOrPiajEk7Cp3A= github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/collectd/go-collectd v0.5.0 h1:dDXnD+hkw7f3XPNtQm1feda+dGZtzTNWXZID+w0Npxk= github.com/collectd/go-collectd v0.5.0/go.mod h1:xQe/Em/Q9IrN5ifWOvK5ZP2vMIB4KlsIA550yYzhkpY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kinbiko/jsonassert v1.0.1 h1:8gdLmUaPWuxk2TzQSofKRqatFH6zwTF6AsUH4bugJYY= github.com/kinbiko/jsonassert v1.0.1/go.mod h1:QRwBwiAsrcJpjw+L+Q4WS8psLxuUY+HylVZS/4j74TM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prozz/aws-embedded-metrics-golang v1.2.0 h1:b/LFb8J9LbgANow/9nYZE3M3bkb457/dj0zAB3hPyvo= github.com/prozz/aws-embedded-metrics-golang v1.2.0/go.mod h1:MXOqF9cJCEHjj77LWq7NWK44/AOyaFzwmcAYqR3057M= github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA= github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0= github.com/qri-io/jsonschema v0.2.1/go.mod h1:g7DPkiOsK1xv6T/Ao5scXRkd+yTFygcANPBaaqW+VrI= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= @@ -128,69 +275,367 @@ github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVboz github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= +github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/contrib/propagators/aws v1.17.0 h1:IX8d7l2uRw61BlmZBOTQFaK+y22j6vytMVTs9wFrO+c= +go.opentelemetry.io/contrib/propagators/aws v1.17.0/go.mod h1:pAlCYRWff4uGqRXOVn3WP8pDZ5E0K56bEoG7a1VSL4k= +go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= +go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= +go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= +go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/terraform/ec2/mac/main.tf b/terraform/ec2/mac/main.tf index 90183c0f4..1ecdc5b83 100644 --- a/terraform/ec2/mac/main.tf +++ b/terraform/ec2/mac/main.tf @@ -136,31 +136,6 @@ resource "null_resource" "integration_test" { } -resource "null_resource" "integration_test_run" { - connection { - type = "ssh" - user = var.user - private_key = local.private_key_content - host = aws_instance.cwagent.public_ip - } - - #Run sanity check and integration test - provisioner "remote-exec" { - inline = [ - "echo prepare environment", - "export AWS_REGION=${var.region}", - "echo run integration test", - "cd ~/amazon-cloudwatch-agent-test", - "go test ${var.test_dir} -p 1 -timeout 1h -computeType=EC2 -bucket=${var.s3_bucket} -cwaCommitSha=${var.cwa_github_sha} -instanceId=${aws_instance.cwagent.id} -v" - ] - } - - depends_on = [ - null_resource.integration_test, - null_resource.integration_test_wait, - ] -} - data "aws_ami" "latest" { most_recent = true diff --git a/terraform/eks/daemon/emf/main.tf b/terraform/eks/daemon/emf/main.tf index e1bcfb305..28b8247de 100644 --- a/terraform/eks/daemon/emf/main.tf +++ b/terraform/eks/daemon/emf/main.tf @@ -337,7 +337,7 @@ resource "kubernetes_daemonset" "service" { command = [ "/bin/sh", "-c", - "while true; do CURRENT_TIME=\"$(date +%s%3N)\"; TIMESTAMP=\"$(($CURRENT_TIME *1000))\"; echo '{\"_aws\":{\"Timestamp\":'\"$${TIMESTAMP}\"',\"LogGroupName\":\"EMFEKSLogGroup\",\"CloudWatchMetrics\":[{\"Namespace\":\"EMFEKSNameSpace\",\"Dimensions\":[[\"Type\",\"ClusterName\"]],\"Metrics\":[{\"Name\":\"EMFCounter\",\"Unit\":\"Count\"}]}]},\"Type\":\"Counter\",\"EMFCounter\":5, \"ClusterName\": \"${aws_eks_cluster.this.name}\"}}' | socat -v -t 0 - UDP:0.0.0.0:25888; sleep 60; done" + "while true; do CURRENT_TIME=\"$(date +%s%3N)\"; TIMESTAMP=\"$(($CURRENT_TIME *1000))\"; echo '{\"_aws\":{\"Timestamp\":'\"$${TIMESTAMP}\"',\"LogGroupName\":\"EMFEKSLogGroup\",\"CloudWatchMetrics\":[{\"Namespace\":\"EMFEKSNameSpace\",\"Dimensions\":[[\"Type\",\"ClusterName\"]],\"Metrics\":[{\"Name\":\"EMFCounter\",\"Unit\":\"Count\"}]}]},\"Type\":\"Counter\",\"EMFCounter\":5, \"ClusterName\": \"${aws_eks_cluster.this.name}\"}' | socat -v -t 0 - UDP:0.0.0.0:25888; sleep 60; done" ] env { name = "HOST_IP" diff --git a/terraform/eks/daemon/emf/variables.tf b/terraform/eks/daemon/emf/variables.tf index 015d9b940..41afe484a 100644 --- a/terraform/eks/daemon/emf/variables.tf +++ b/terraform/eks/daemon/emf/variables.tf @@ -23,7 +23,7 @@ variable "cwagent_image_tag" { variable "k8s_version" { type = string - default = "1.24" + default = "1.27" } variable "ami_type" { diff --git a/test/cloudwatchlogs/publish_logs_test.go b/test/cloudwatchlogs/publish_logs_test.go index 7cc7fcef5..c931380da 100644 --- a/test/cloudwatchlogs/publish_logs_test.go +++ b/test/cloudwatchlogs/publish_logs_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" "github.com/stretchr/testify/assert" "github.com/aws/amazon-cloudwatch-agent-test/environment" @@ -99,11 +100,15 @@ func TestWriteLogsToCloudWatch(t *testing.T) { end := time.Now() // check CWL to ensure we got the expected number of logs in the log stream - ok, err := awsservice.ValidateLogs(instanceId, instanceId, &start, &end, func(logs []string) bool { - return param.numExpectedLogs == len(logs) - }) + err = awsservice.ValidateLogs( + instanceId, + instanceId, + &start, + &end, + awsservice.AssertLogsCount(param.numExpectedLogs), + awsservice.AssertNoDuplicateLogs(), + ) assert.NoError(t, err) - assert.True(t, ok) }) } } @@ -151,23 +156,24 @@ func TestRotatingLogsDoesNotSkipLines(t *testing.T) { end := time.Now() - ok, err := awsservice.ValidateLogs(logGroup, logStream, &start, &end, func(logs []string) bool { - if len(logs) != len(lines) { - return false - } - - for i := 0; i < len(logs); i++ { - expected := strings.ReplaceAll(lines[i], "'", "\"") - actual := strings.ReplaceAll(logs[i], "'", "\"") - if expected != actual { - return false + err := awsservice.ValidateLogs( + logGroup, + logStream, + &start, + &end, + awsservice.AssertLogsCount(len(lines)), + func(events []types.OutputLogEvent) error { + for i := 0; i < len(events); i++ { + expected := strings.ReplaceAll(lines[i], "'", "\"") + actual := strings.ReplaceAll(*events[i].Message, "'", "\"") + if expected != actual { + return fmt.Errorf("actual log event %q does not match the expected %q", actual, expected) + } } - } - - return true - }) + return nil + }, + ) assert.NoError(t, err) - assert.True(t, ok) } func writeLogs(t *testing.T, f *os.File, iterations int) { diff --git a/test/ecs/ecs_metadata/ecs_metadata_test.go b/test/ecs/ecs_metadata/ecs_metadata_test.go index 49f1c19cd..738e9020a 100644 --- a/test/ecs/ecs_metadata/ecs_metadata_test.go +++ b/test/ecs/ecs_metadata/ecs_metadata_test.go @@ -7,12 +7,12 @@ import ( _ "embed" "flag" "fmt" + "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" "log" "strings" "testing" "time" - "github.com/qri-io/jsonschema" "github.com/stretchr/testify/assert" "github.com/aws/amazon-cloudwatch-agent-test/util/awsservice" @@ -36,8 +36,6 @@ var clusterName = flag.String("clusterName", "", "Please provide the os preferen var schema string func TestValidatingCloudWatchLogs(t *testing.T) { - rs := jsonschema.Must(schema) - start := time.Now() logGroupName := fmt.Sprintf(ECSLogGroupNameFormat, *clusterName) @@ -57,25 +55,25 @@ func TestValidatingCloudWatchLogs(t *testing.T) { end := time.Now() - ok, err := awsservice.ValidateLogs(logGroupName, LogStreamName, &start, &end, func(logs []string) bool { - if len(logs) < 1 { - return false - } - for _, l := range logs { - if !awsservice.MatchEMFLogWithSchema(l, rs, func(s string) bool { - ok := true - if strings.Contains(l, "CloudWatchMetrics") { - ok = ok && strings.Contains(l, "\"Namespace\":\"ECS/ContainerInsights/Prometheus\"") + err := awsservice.ValidateLogs( + logGroupName, + LogStreamName, + &start, + &end, + awsservice.AssertLogsNotEmpty(), + awsservice.AssertPerLog( + awsservice.AssertLogSchema(awsservice.WithSchema(schema)), + func(event types.OutputLogEvent) error { + if strings.Contains(*event.Message, "CloudWatchMetrics") && + !strings.Contains(*event.Message, "\"Namespace\":\"ECS/ContainerInsights/Prometheus\"") { + return fmt.Errorf("emf log found for non ECS/ContainerInsights/Prometheus namespace: %s", *event.Message) } - return ok && strings.Contains(l, "\"job\":\"prometheus-redis\"") - }) { - return false - } - } - return true - }) + return nil + }, + awsservice.AssertLogContainsSubstring("\"job\":\"prometheus-redis\""), + ), + ) assert.NoError(t, err) - assert.True(t, ok) break } diff --git a/test/fluent/fluent_test.go b/test/fluent/fluent_test.go index 2acceb5cb..ab42d2c13 100644 --- a/test/fluent/fluent_test.go +++ b/test/fluent/fluent_test.go @@ -11,6 +11,8 @@ import ( "testing" "time" + "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" + "github.com/aws/amazon-cloudwatch-agent-test/environment" "github.com/aws/amazon-cloudwatch-agent-test/util/awsservice" ) @@ -43,41 +45,47 @@ func TestFluentLogs(t *testing.T) { now := time.Now() for group, fieldsArr := range logGroupToKey { - group := fmt.Sprintf("/aws/containerinsights/%s/%s", env.EKSClusterName, group) + group = fmt.Sprintf("/aws/containerinsights/%s/%s", env.EKSClusterName, group) if !awsservice.IsLogGroupExists(group) { t.Fatalf("fluent log group doesn't exsit: %s", group) } streams := awsservice.GetLogStreams(group) - if len(streams) < 1 { + if len(streams) == 0 { t.Fatalf("fluent log streams are empty for log group: %s", group) } - ok, err := awsservice.ValidateLogs(group, *(streams[0].LogStreamName), nil, &now, func(logs []string) bool { - if len(logs) < 1 { - return false - } - - // only 1 log message gets validate - // log message must include expected fields, and there could be more than 1 set of expected fields per log group - var found = false - for _, fields := range fieldsArr { - match := 0 - for _, field := range fields { - if strings.Contains(logs[0], "\""+field+"\"") { - match += 1 + err := awsservice.ValidateLogs( + group, + *(streams[0].LogStreamName), + nil, + &now, + awsservice.AssertLogsNotEmpty(), + func(events []types.OutputLogEvent) error { + // only 1 log message gets validated + // log message must include expected fields, and there could be more than 1 set of expected fields per log group + var found bool + for _, fields := range fieldsArr { + var match int + for _, field := range fields { + if strings.Contains(*events[0].Message, "\""+field+"\"") { + match += 1 + } + } + if match == len(fields) { + found = true + break } } - if match == len(fields) { - found = true - break + if !found { + return fmt.Errorf("fluent log entry doesn't include expected message fields: %s", *events[0].Message) } - } - return found - }) + return nil + }, + ) - if err != nil || !ok { - t.Fatalf("fluent log entry doesn't include expected message fields for logGroup: %s", group) + if err != nil { + t.Fatalf("failed validation for log group %s: %v", group, err) } } diff --git a/test/metric_value_benchmark/container_insights_test.go b/test/metric_value_benchmark/container_insights_test.go index b7b9f6942..61a04921b 100644 --- a/test/metric_value_benchmark/container_insights_test.go +++ b/test/metric_value_benchmark/container_insights_test.go @@ -8,11 +8,9 @@ package metric_value_benchmark import ( _ "embed" "fmt" - "strings" + "log" "time" - "github.com/qri-io/jsonschema" - "github.com/aws/amazon-cloudwatch-agent-test/environment" "github.com/aws/amazon-cloudwatch-agent-test/test/metric" "github.com/aws/amazon-cloudwatch-agent-test/test/metric/dimension" @@ -113,8 +111,6 @@ func validateLogsForContainerInsights(e *environment.MetaData) status.TestResult Status: status.FAILED, } - rs := jsonschema.Must(emfContainerInsightsSchema) - now := time.Now() group := fmt.Sprintf("/aws/ecs/containerinsights/%s/performance", e.EcsClusterName) @@ -125,26 +121,21 @@ func validateLogsForContainerInsights(e *environment.MetaData) status.TestResult } for _, container := range containers { - validateLogContents := func(s string) bool { - return strings.Contains(s, fmt.Sprintf("\"ContainerInstanceId\":\"%s\"", container.ContainerInstanceId)) - } - - var ok bool stream := fmt.Sprintf("NodeTelemetry-%s", container.ContainerInstanceId) - ok, err = awsservice.ValidateLogs(group, stream, nil, &now, func(logs []string) bool { - if len(logs) < 1 { - return false - } - - for _, l := range logs { - if !awsservice.MatchEMFLogWithSchema(l, rs, validateLogContents) { - return false - } - } - return true - }) - - if err != nil || !ok { + err = awsservice.ValidateLogs( + group, + stream, + nil, + &now, + awsservice.AssertLogsNotEmpty(), + awsservice.AssertPerLog( + awsservice.AssertLogSchema(awsservice.WithSchema(emfContainerInsightsSchema)), + awsservice.AssertLogContainsSubstring(fmt.Sprintf("\"ContainerInstanceId\":\"%s\"", container.ContainerInstanceId)), + ), + ) + + if err != nil { + log.Printf("log validation (%s/%s) for container (%s) failed: %v", group, stream, container.ContainerInstanceId, err) return testResult } } diff --git a/test/metric_value_benchmark/eks_daemonset_test.go b/test/metric_value_benchmark/eks_daemonset_test.go index fef50f0ad..35e4298a7 100644 --- a/test/metric_value_benchmark/eks_daemonset_test.go +++ b/test/metric_value_benchmark/eks_daemonset_test.go @@ -7,13 +7,12 @@ package metric_value_benchmark import ( "encoding/json" + "errors" "fmt" "log" - "strings" "time" "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" - "github.com/qri-io/jsonschema" "golang.org/x/exp/slices" "github.com/aws/amazon-cloudwatch-agent-test/environment" @@ -127,42 +126,34 @@ func (e *EKSDaemonTestRunner) validateLogs(env *environment.MetaData) status.Tes } for _, instance := range eKSInstances { - validateLogContents := func(s string) bool { - return strings.Contains(s, fmt.Sprintf("\"ClusterName\":\"%s\"", env.EKSClusterName)) - } - - var ok bool stream := *instance.InstanceName - ok, err = awsservice.ValidateLogs(group, stream, nil, &now, func(logs []string) bool { - if len(logs) < 1 { - log.Println(fmt.Sprintf("failed to get logs for instance: %s", stream)) - return false - } + err = awsservice.ValidateLogs( + group, + stream, + nil, + &now, + awsservice.AssertLogsNotEmpty(), + awsservice.AssertPerLog( + awsservice.AssertLogSchema(func(message string) (string, error) { + var eksClusterType awsservice.EKSClusterType + innerErr := json.Unmarshal([]byte(message), &eksClusterType) + if innerErr != nil { + return "", fmt.Errorf("failed to unmarshal log file: %w", innerErr) + } + + log.Printf("eksClusterType is: %s", eksClusterType.Type) + jsonSchema, ok := eks_resources.EksClusterValidationMap[eksClusterType.Type] + if !ok { + return "", errors.New("invalid cluster type provided") + } + return jsonSchema, nil + }), + awsservice.AssertLogContainsSubstring(fmt.Sprintf("\"ClusterName\":\"%s\"", env.EKSClusterName)), + ), + ) - for _, l := range logs { - var eksClusterType awsservice.EKSClusterType - err := json.Unmarshal([]byte(l), &eksClusterType) - if err != nil { - log.Println("failed to unmarshal log file") - } - - log.Println(fmt.Sprintf("eksClusterType is: %s", eksClusterType.Type)) - jsonSchema, ok := eks_resources.EksClusterValidationMap[eksClusterType.Type] - if !ok { - log.Println("invalid cluster type provided") - return false - } - rs := jsonschema.Must(jsonSchema) - - if !awsservice.MatchEMFLogWithSchema(l, rs, validateLogContents) { - log.Println("failed to match log with schema") - return false - } - } - return true - }) - - if err != nil || !ok { + if err != nil { + log.Printf("log validation (%s/%s) failed: %v", group, stream, err) return testResult } } @@ -208,7 +199,6 @@ func (e *EKSDaemonTestRunner) GetMeasuredMetrics() []string { "pod_memory_utilization_over_pod_limit", "pod_network_rx_bytes", "pod_network_tx_bytes", - "pod_number_of_container_restarts", "service_number_of_running_pods", } } diff --git a/test/metric_value_benchmark/emf_test.go b/test/metric_value_benchmark/emf_test.go index 32e32efed..a69a785c0 100644 --- a/test/metric_value_benchmark/emf_test.go +++ b/test/metric_value_benchmark/emf_test.go @@ -7,18 +7,16 @@ package metric_value_benchmark import ( _ "embed" - "strings" + "log" "time" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/qri-io/jsonschema" - "github.com/aws/amazon-cloudwatch-agent-test/test/metric" "github.com/aws/amazon-cloudwatch-agent-test/test/metric/dimension" "github.com/aws/amazon-cloudwatch-agent-test/test/status" "github.com/aws/amazon-cloudwatch-agent-test/test/test_runner" "github.com/aws/amazon-cloudwatch-agent-test/util/awsservice" "github.com/aws/amazon-cloudwatch-agent-test/util/common" + "github.com/aws/aws-sdk-go-v2/aws" ) type EMFTestRunner struct { @@ -116,27 +114,20 @@ func validateEMFLogs(group, stream string) status.TestResult { Status: status.FAILED, } - rs := jsonschema.Must(emfMetricValueBenchmarkSchema) - - validateLogContents := func(s string) bool { - return strings.Contains(s, "\"EMFCounter\":5") - } - now := time.Now() - ok, err := awsservice.ValidateLogs(group, stream, nil, &now, func(logs []string) bool { - if len(logs) < 1 { - return false - } - - for _, l := range logs { - if !awsservice.MatchEMFLogWithSchema(l, rs, validateLogContents) { - return false - } - } - return true - }) - - if err != nil || !ok { + err := awsservice.ValidateLogs( + group, + stream, + nil, + &now, + awsservice.AssertLogsNotEmpty(), + awsservice.AssertPerLog( + awsservice.AssertLogSchema(awsservice.WithSchema(emfMetricValueBenchmarkSchema)), + awsservice.AssertLogContainsSubstring("\"EMFCounter\":5"), + ), + ) + if err != nil { + log.Printf("log validation (%s/%s) failed: %v", group, stream, err) return testResult } diff --git a/test/metrics_number_dimension/metrics_number_dimension_test.go b/test/metrics_number_dimension/metrics_number_dimension_test.go index c1bee083a..c05e21256 100644 --- a/test/metrics_number_dimension/metrics_number_dimension_test.go +++ b/test/metrics_number_dimension/metrics_number_dimension_test.go @@ -96,7 +96,7 @@ func TestNumberMetricDimension(t *testing.T) { // test for cloud watch metrics dimensionFilter := buildDimensionFilterList(parameter.numberDimensionsInCW) - awsservice.ValidateMetricWithTest(t, parameter.metricName, namespace, dimensionFilter) + awsservice.ValidateMetricWithTest(t, parameter.metricName, namespace, dimensionFilter, 5, 20*time.Second) }) } } diff --git a/test/metrics_number_dimension/resources/10_dimension/config.json b/test/metrics_number_dimension/resources/10_dimension/config.json index acd1f545f..35045eec0 100644 --- a/test/metrics_number_dimension/resources/10_dimension/config.json +++ b/test/metrics_number_dimension/resources/10_dimension/config.json @@ -1,11 +1,12 @@ { "agent": { - "metrics_collection_interval": 60, + "metrics_collection_interval": 10, "run_as_user": "root", "debug": true, "logfile": "" }, "metrics": { + "force_flush_interval": 10, "namespace": "MetricNumberDimensionTest", "append_dimensions": { "InstanceId": "${aws:InstanceId}" @@ -15,7 +16,7 @@ "measurement": [ "mem_used_percent" ], - "metrics_collection_interval": 60, + "metrics_collection_interval": 10, "append_dimensions": { "append0": "Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus non mauris malesuada mattis ex eget porttitor purus Suspendisse potenti Praesent vel sollicitudin ipsum Quisque luctus pretium lorem non faucibus Ut vel quam dui Nunc fermentum condimentum consectetur Morbi tellus mauris tristique tincidunt elit consectetur hendrerit placerat dui In nulla erat finibus eget erat a hendrerit sodales urna In sapien purus auctor sit amet congue ut congue eget nisi Vivamus sed neque ut ligula lobortis accumsan quis id metus In feugiat velit et leo mattis non fringilla dui elementum Proin a nisi ac sapien vulputate consequat Vestibulum eu tellus mi Integer consectetur efficiturappend0", "append1": "Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus non mauris malesuada mattis ex eget porttitor purus Suspendisse potenti Praesent vel sollicitudin ipsum Quisque luctus pretium lorem non faucibus Ut vel quam dui Nunc fermentum condimentum consectetur Morbi tellus mauris tristique tincidunt elit consectetur hendrerit placerat dui In nulla erat finibus eget erat a hendrerit sodales urna In sapien purus auctor sit amet congue ut congue eget nisi Vivamus sed neque ut ligula lobortis accumsan quis id metus In feugiat velit et leo mattis non fringilla dui elementum Proin a nisi ac sapien vulputate consequat Vestibulum eu tellus mi Integer consectetur efficiturappend1", diff --git a/test/metrics_number_dimension/resources/30_dimension/config.json b/test/metrics_number_dimension/resources/30_dimension/config.json index 8a50fc6f5..3a2f09bc2 100644 --- a/test/metrics_number_dimension/resources/30_dimension/config.json +++ b/test/metrics_number_dimension/resources/30_dimension/config.json @@ -1,11 +1,12 @@ { "agent": { - "metrics_collection_interval": 60, + "metrics_collection_interval": 10, "run_as_user": "root", "debug": true, "logfile": "" }, "metrics": { + "force_flush_interval": 10, "namespace": "MetricNumberDimensionTest", "append_dimensions": { "InstanceId": "${aws:InstanceId}" @@ -15,7 +16,7 @@ "measurement": [ "mem_used_percent" ], - "metrics_collection_interval": 60, + "metrics_collection_interval": 10, "append_dimensions": { "append0": "Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus non mauris malesuada mattis ex eget porttitor purus Suspendisse potenti Praesent vel sollicitudin ipsum Quisque luctus pretium lorem non faucibus Ut vel quam dui Nunc fermentum condimentum consectetur Morbi tellus mauris tristique tincidunt elit consectetur hendrerit placerat dui In nulla erat finibus eget erat a hendrerit sodales urna In sapien purus auctor sit amet congue ut congue eget nisi Vivamus sed neque ut ligula lobortis accumsan quis id metus In feugiat velit et leo mattis non fringilla dui elementum Proin a nisi ac sapien vulputate consequat Vestibulum eu tellus mi Integer consectetur efficiturappend0", "append1": "Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus non mauris malesuada mattis ex eget porttitor purus Suspendisse potenti Praesent vel sollicitudin ipsum Quisque luctus pretium lorem non faucibus Ut vel quam dui Nunc fermentum condimentum consectetur Morbi tellus mauris tristique tincidunt elit consectetur hendrerit placerat dui In nulla erat finibus eget erat a hendrerit sodales urna In sapien purus auctor sit amet congue ut congue eget nisi Vivamus sed neque ut ligula lobortis accumsan quis id metus In feugiat velit et leo mattis non fringilla dui elementum Proin a nisi ac sapien vulputate consequat Vestibulum eu tellus mi Integer consectetur efficiturappend1", diff --git a/test/metrics_number_dimension/resources/35_dimension/config.json b/test/metrics_number_dimension/resources/35_dimension/config.json index bb8618dc4..2da9f6f6b 100644 --- a/test/metrics_number_dimension/resources/35_dimension/config.json +++ b/test/metrics_number_dimension/resources/35_dimension/config.json @@ -1,11 +1,12 @@ { "agent": { - "metrics_collection_interval": 60, + "metrics_collection_interval": 10, "run_as_user": "root", "debug": true, "logfile": "" }, "metrics": { + "force_flush_interval": 10, "namespace": "MetricNumberDimensionTest", "append_dimensions": { "InstanceId": "${aws:InstanceId}" @@ -15,7 +16,7 @@ "measurement": [ "mem_used_percent" ], - "metrics_collection_interval": 60, + "metrics_collection_interval": 10, "append_dimensions": { "append0": "Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus non mauris malesuada mattis ex eget porttitor purus Suspendisse potenti Praesent vel sollicitudin ipsum Quisque luctus pretium lorem non faucibus Ut vel quam dui Nunc fermentum condimentum consectetur Morbi tellus mauris tristique tincidunt elit consectetur hendrerit placerat dui In nulla erat finibus eget erat a hendrerit sodales urna In sapien purus auctor sit amet congue ut congue eget nisi Vivamus sed neque ut ligula lobortis accumsan quis id metus In feugiat velit et leo mattis non fringilla dui elementum Proin a nisi ac sapien vulputate consequat Vestibulum eu tellus mi Integer consectetur efficiturappend0", "append1": "Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus non mauris malesuada mattis ex eget porttitor purus Suspendisse potenti Praesent vel sollicitudin ipsum Quisque luctus pretium lorem non faucibus Ut vel quam dui Nunc fermentum condimentum consectetur Morbi tellus mauris tristique tincidunt elit consectetur hendrerit placerat dui In nulla erat finibus eget erat a hendrerit sodales urna In sapien purus auctor sit amet congue ut congue eget nisi Vivamus sed neque ut ligula lobortis accumsan quis id metus In feugiat velit et leo mattis non fringilla dui elementum Proin a nisi ac sapien vulputate consequat Vestibulum eu tellus mi Integer consectetur efficiturappend1", diff --git a/test/multi_config/multi_config_test.go b/test/multi_config/multi_config_test.go deleted file mode 100644 index 518b0aea1..000000000 --- a/test/multi_config/multi_config_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package multi_config - -import ( - "log" - "testing" - "time" - - "github.com/aws/amazon-cloudwatch-agent-test/environment" - "github.com/aws/amazon-cloudwatch-agent-test/util/common" -) - -func init() { - environment.RegisterEnvironmentMetaDataFlags() -} - -func AppendConfigs(config []string, configOutputPath string) { - for index, agentConfig := range config { - common.CopyFile(agentConfig, configOutputPath) - - log.Printf(configOutputPath) - if index == 0 { - common.StartAgent(configOutputPath, true, false) - } else { - common.StartAgentWithMultiConfig(configOutputPath, true, false) - } - time.Sleep(10 * time.Second) - } -} - -func TestMultipleConfig(t *testing.T) { - err := Validate() - if err != nil { - t.Fatalf("append-config validation failed: %s", err) - } -} diff --git a/test/multi_config/multi_config_unix_test.go b/test/multi_config/multi_config_unix_test.go deleted file mode 100644 index f9e3e56df..000000000 --- a/test/multi_config/multi_config_unix_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: MIT - -//go:build !windows - -package multi_config - -import ( - "log" - "time" - - "github.com/aws/amazon-cloudwatch-agent-test/util/awsservice" - "github.com/aws/amazon-cloudwatch-agent-test/util/common" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" -) - -const ( - configOutputPath = "/opt/aws/amazon-cloudwatch-agent/bin/config.json" - namespace = "MultiConfigTest" -) - -// Let the agent run for 2 minutes. This will give agent enough time to call server -const agentRuntime = 2 * time.Minute - -func Validate() error { - - agentConfigurations := []string{"resources/linux/LinuxCpuOnlyConfig.json", "resources/linux/LinuxMemoryOnlyConfig.json", "resources/linux/LinuxDiskOnlyConfig.json"} - - AppendConfigs(agentConfigurations, configOutputPath) - - time.Sleep(agentRuntime) - log.Printf("Agent has been running for : %s", agentRuntime.String()) - common.StopAgent() - - // test for cloud watch metrics - ec2InstanceId := awsservice.GetInstanceId() - expectedDimensions := []types.DimensionFilter{ - types.DimensionFilter{ - Name: aws.String("InstanceId"), - Value: aws.String(ec2InstanceId), - }, - } - - expectedMetrics := []string{"mem_used_percent", "cpu_time_active_userdata", "disk_free"} - for _, expectedMetric := range expectedMetrics { - err := awsservice.ValidateMetric(expectedMetric, namespace, expectedDimensions) - if err != nil { - log.Printf("CloudWatch Agent apped config not working : %v", err) - return err - } - } - return nil -} diff --git a/test/multi_config/multi_config_windows_test.go b/test/multi_config/multi_config_windows_test.go deleted file mode 100644 index 009512eac..000000000 --- a/test/multi_config/multi_config_windows_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: MIT - -//go:build windows -// +build windows - -package multi_config - -import ( - "log" - "time" - - "github.com/aws/amazon-cloudwatch-agent-test/util/awsservice" - "github.com/aws/amazon-cloudwatch-agent-test/util/common" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" -) - -const ( - configOutputPath = "C:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\config.json" - namespace = "MultiConfigWindowsTest" - agentRuntime = 2 * time.Minute -) - -func Validate() error { - agentConfigurations := []string{"resources/windows/WindowsCompleteConfig.json", "resources/windows/WindowsMemoryOnlyConfig.json"} - - AppendConfigs(agentConfigurations, configOutputPath) - - time.Sleep(agentRuntime) - log.Printf("Agent has been running for : %s", agentRuntime.String()) - err := common.StopAgent() - if err != nil { - log.Printf("Stopping agent failed: %v", err) - return err - } - - // test for cloud watch metrics - ec2InstanceId := awsservice.GetInstanceId() - expectedDimensions := []types.DimensionFilter{ - types.DimensionFilter{ - Name: aws.String("InstanceId"), - Value: aws.String(ec2InstanceId), - }, - } - - expectedMetrics := []string{"% Committed Bytes In Use", "% InterruptTime", "% Disk Time"} - for _, expectedMetric := range expectedMetrics { - err = awsservice.ValidateMetric(expectedMetric, namespace, expectedDimensions) - } - if err != nil { - log.Printf("CloudWatch Agent apped config not working : %v", err) - return err - } - return nil -} diff --git a/test/multi_config/resources/linux/LinuxCpuOnlyConfig.json b/test/multi_config/resources/linux/LinuxCpuOnlyConfig.json deleted file mode 100644 index 5c21b1ac0..000000000 --- a/test/multi_config/resources/linux/LinuxCpuOnlyConfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "metrics": { - "namespace": "MultiConfigTest", - "append_dimensions": { - "InstanceId": "${aws:InstanceId}" - }, - "metrics_collected": { - "cpu": { - "measurement": [ - {"name": "time_active", "rename":"cpu_time_active_userdata"} - ], - "metrics_collection_interval": 15 - } - }, - "force_flush_interval": 5 - } -} \ No newline at end of file diff --git a/test/multi_config/resources/linux/LinuxDiskOnlyConfig.json b/test/multi_config/resources/linux/LinuxDiskOnlyConfig.json deleted file mode 100644 index 36fae21be..000000000 --- a/test/multi_config/resources/linux/LinuxDiskOnlyConfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "agent": { - "metrics_collection_interval": 10, - "run_as_user": "root", - "debug": true, - "logfile": "" - }, - "metrics": { - "namespace": "MultiConfigTest", - "append_dimensions": { - "InstanceId": "${aws:InstanceId}" - }, - "aggregation_dimensions": [ - [ - "InstanceId" - ] - ], - "metrics_collected": { - "disk": { - "resources": [ - "*" - ], - "measurement": [ - "free" - ], - "drop_device": true - } - }, - "force_flush_interval": 5 - } -} \ No newline at end of file diff --git a/test/multi_config/resources/linux/LinuxMemoryOnlyConfig.json b/test/multi_config/resources/linux/LinuxMemoryOnlyConfig.json deleted file mode 100644 index d9722ea30..000000000 --- a/test/multi_config/resources/linux/LinuxMemoryOnlyConfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "metrics": { - "namespace": "MultiConfigTest", - "metrics_collected": { - "mem": { - "measurement": [ - {"name":"used_percent", "rename": "memory"} - ] - } - }, - "append_dimensions": { - "InstanceId": "${aws:InstanceId}" - } - } -} \ No newline at end of file diff --git a/test/multi_config/resources/windows/WindowsCompleteConfig.json b/test/multi_config/resources/windows/WindowsCompleteConfig.json deleted file mode 100644 index 78b6b460c..000000000 --- a/test/multi_config/resources/windows/WindowsCompleteConfig.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "agent": { - "metrics_collection_interval": 60, - "logfile": "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log" - }, - "metrics": { - "metrics_collected": { - "Processor": { - "measurement": [ - "% Idle Time", - "% InterruptTime", - "% User Time", - "% Processor Time" - ], - "resources": [ - "*" - ], - "metrics_collection_interval": 1 - }, - "LogicalDisk": { - "measurement": [ - "% Free Space" - ], - "resources": [ - "*" - ] - }, - "PhysicalDisk": { - "measurement": [ - "% Disk Time", - "Disk Write Bytes/sec", - "Disk Read Bytes/sec", - "Disk Writes/sec", - "Disk Reads/sec" - ], - "resources": [ - "*" - ] - }, - "Network Interface": { - "measurement": [ - "Bytes Sent/sec", - "Bytes Received/sec", - "Packets Sent/sec", - "Packets Received/sec" - ], - "resources": [ - "*" - ] - }, - "TCPv4": { - "measurement": [ - "Connections Established" - ] - }, - "TCPv6": { - "measurement": [ - "Connections Established" - ] - }, - "Paging File": { - "measurement": [ - "% Usage" - ], - "resources": [ - "*" - ] - }, - "procstat": [ - { - "measurement": [ - "cpu_time", "cpu_time_guest", "cpu_time_guest_nice", "cpu_time_idle", "cpu_time_iowait", "cpu_time_irq", "cpu_time_nice", "cpu_time_soft_irq", "cpu_time_steal", "cpu_time_system", "cpu_time_user", "cpu_usage", - "involuntary_context_switches", "memory_data", "memory_locked", "memory_rss", "memory_stack", "memory_swap", "memory_vms", - "nice_priority", "num_fds", "num_threads", "pid", "read_bytes", "read_count", "realtime_priority", - "rlimit_cpu_time_hard", "rlimit_cpu_time_soft", "rlimit_file_locks_hard", "rlimit_file_locks_soft", "rlimit_memory_data_hard", "rlimit_memory_data_soft", "rlimit_memory_locked_hard", "rlimit_memory_locked_soft", - "rlimit_memory_rss_hard", "rlimit_memory_rss_soft", "rlimit_memory_stack_hard", "rlimit_memory_stack_soft", "rlimit_memory_vms_hard", "rlimit_memory_vms_soft", "rlimit_nice_priority_hard", "rlimit_nice_priority_soft", "rlimit_num_fds_hard", "rlimit_num_fds_soft", - "rlimit_realtime_priority_hard", "rlimit_realtime_priority_soft", "rlimit_signals_pending_hard", "rlimit_signals_pending_soft", - "signals_pending", "voluntary_context_switches", "write_bytes", "write_count", - "pid_count" - ], - "pattern": "%watch%" - } - ] - }, - "append_dimensions": { - "ImageId": "${aws:ImageId}", - "InstanceId": "${aws:InstanceId}", - "InstanceType": "${aws:InstanceType}", - "AutoScalingGroupName": "${aws:AutoScalingGroupName}" - }, - "aggregation_dimensions" : [["ImageId"], ["InstanceId", "InstanceType"], ["InvalidTag"],[]] - }, - "logs": { - "logs_collected": { - "files": { - "collect_list": [ - { - "file_path": "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log", - "log_group_name": "amazon-cloudwatch-agent.log" - } - ] - }, - "windows_events": { - "collect_list": [ - { - "event_name": "System", - "event_levels": [ - "INFORMATION", - "ERROR", - "WARNING" - ], - "log_group_name": "System" - }, - { - "event_name": "Application", - "event_levels": [ - "INFORMATION", - "ERROR", - "WARNING" - ], - "log_group_name": "Application" - } - ] - } - } - } -} \ No newline at end of file diff --git a/test/multi_config/resources/windows/WindowsMemoryOnlyConfig.json b/test/multi_config/resources/windows/WindowsMemoryOnlyConfig.json deleted file mode 100644 index ff3980a8e..000000000 --- a/test/multi_config/resources/windows/WindowsMemoryOnlyConfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "agent": { - "logfile": "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log" - }, - "metrics": { - "metrics_collected": { - "Memory": { - "measurement": [ - "% Committed Bytes In Use" - ] - } - }, - "append_dimensions": { - "InstanceId": "${aws:InstanceId}" - } - } -} \ No newline at end of file diff --git a/test/otlp/generator.go b/test/otlp/generator.go new file mode 100644 index 000000000..d530f2910 --- /dev/null +++ b/test/otlp/generator.go @@ -0,0 +1,135 @@ +package otlp + +import ( + "context" + "errors" + "time" + + "github.com/aws/amazon-cloudwatch-agent-test/util/common" + "go.opentelemetry.io/contrib/propagators/aws/xray" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + "go.opentelemetry.io/otel/trace" + "golang.org/x/exp/maps" +) + +var generatorError = errors.New("Generator error") + +const ( + serviceName = "load-generator" + attributeKeyAwsXrayAnnotations = "aws.xray.annotations" +) + +type OtlpTracesGenerator struct { + common.TraceGenerator + common.TraceGeneratorInterface +} + +func (g *OtlpTracesGenerator) StartSendingTraces(ctx context.Context) error { + client, shutdown, err := setupClient(ctx) + if err != nil { + return err + } + defer shutdown(ctx) + ticker := time.NewTicker(g.Cfg.Interval) + for { + select { + case <-g.Done: + ticker.Stop() + return client.ForceFlush(ctx) + case <-ticker.C: + if err = g.Generate(ctx); err != nil { + return err + } + } + } +} +func (g *OtlpTracesGenerator) StopSendingTraces() { + close(g.Done) +} +func newLoadGenerator(cfg *common.TraceGeneratorConfig) *OtlpTracesGenerator { + return &OtlpTracesGenerator{ + TraceGenerator: common.TraceGenerator{ + Cfg: cfg, + Done: make(chan struct{}), + SegmentsGenerationCount: 0, + SegmentsEndedCount: 0, + }, + } +} +func (g *OtlpTracesGenerator) Generate(ctx context.Context) error { + tracer := otel.Tracer("tracer") + g.SegmentsGenerationCount++ + _, span := tracer.Start(ctx, "example-span", trace.WithSpanKind(trace.SpanKindServer)) + defer func() { + span.End() + g.SegmentsEndedCount++ + }() + + if len(g.Cfg.Annotations) > 0 { + span.SetAttributes(attribute.StringSlice(attributeKeyAwsXrayAnnotations, maps.Keys(g.Cfg.Annotations))) + } + span.SetAttributes(g.Cfg.Attributes...) + return nil +} + +func (g *OtlpTracesGenerator) GetSegmentCount() (int, int) { + return g.SegmentsGenerationCount, g.SegmentsEndedCount +} + +func (g *OtlpTracesGenerator) GetAgentConfigPath() string { + return g.AgentConfigPath +} +func (g *OtlpTracesGenerator) GetAgentRuntime() time.Duration { + return g.AgentRuntime +} +func (g *OtlpTracesGenerator) GetName() string { + return g.Name +} +func (g *OtlpTracesGenerator) GetGeneratorConfig() *common.TraceGeneratorConfig { + return g.Cfg +} + +func setupClient(ctx context.Context) (*sdktrace.TracerProvider, func(context.Context) error, error) { + res := resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceName(serviceName), + ) + + tp, err := setupTraceProvider(ctx, res) + if err != nil { + return nil, nil, err + } + + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(xray.Propagator{}) + + return tp, func(context.Context) (err error) { + timeoutCtx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + + err = tp.Shutdown(timeoutCtx) + if err != nil { + return err + } + return nil + }, nil +} + +func setupTraceProvider(ctx context.Context, res *resource.Resource) (*sdktrace.TracerProvider, error) { + exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure()) + if err != nil { + return nil, err + } + + return sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(res), + sdktrace.WithIDGenerator(xray.NewIDGenerator()), + ), nil +} diff --git a/test/otlp/resources/otlp-config.json b/test/otlp/resources/otlp-config.json new file mode 100644 index 000000000..1f179f995 --- /dev/null +++ b/test/otlp/resources/otlp-config.json @@ -0,0 +1,8 @@ +{ + "traces": { + "traces_collected": { + "otlp": { + } + } + } +} \ No newline at end of file diff --git a/test/otlp/trace_test.go b/test/otlp/trace_test.go new file mode 100644 index 000000000..cae894eae --- /dev/null +++ b/test/otlp/trace_test.go @@ -0,0 +1,69 @@ +package otlp + +import ( + "path/filepath" + "testing" + "time" + + "github.com/aws/amazon-cloudwatch-agent-test/environment" + "github.com/aws/amazon-cloudwatch-agent-test/util/common" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/attribute" +) + +const ( + agentRuntime = 5 * time.Minute + loadGeneratorInterval = 5 * time.Second + testSegmentCount = 20 +) + +func init() { + environment.RegisterEnvironmentMetaDataFlags() +} + +func TestTraces(t *testing.T) { + env := environment.GetEnvironmentMetaData() + testCases := map[string]struct { + agentConfigPath string + generatorConfig *common.TraceGeneratorConfig + }{ + "WithOTLP/Simple": { + agentConfigPath: filepath.Join("resources", "otlp-config.json"), + generatorConfig: &common.TraceGeneratorConfig{ + Interval: loadGeneratorInterval, + Annotations: map[string]interface{}{ + "test_type": "simple_otlp", + "instance_id": env.InstanceId, + "commit_sha": env.CwaCommitSha, + }, + Metadata: map[string]map[string]interface{}{ + "default": { + "custom_key": "custom_value", + }, + }, + Attributes: []attribute.KeyValue{ + attribute.String("custom_key", "custom_value"), + attribute.String("test_type", "simple_otlp"), + attribute.String("instance_id", env.InstanceId), + attribute.String("commit_sha", env.CwaCommitSha), + }, + }, + }, + } + t.Logf("Sanity check: number of test cases:%d", len(testCases)) + for name, testCase := range testCases { + + t.Run(name, func(t *testing.T) { + + OtlpTestCfg := common.TraceTestConfig{ + Generator: newLoadGenerator(testCase.generatorConfig), + Name: name, + AgentConfigPath: testCase.agentConfigPath, + AgentRuntime: agentRuntime, + } + err := common.TraceTest(t, OtlpTestCfg) + require.NoError(t, err, "TraceTest failed because %s", err) + + }) + } +} diff --git a/test/xray/generator.go b/test/xray/generator.go new file mode 100644 index 000000000..450af0b1e --- /dev/null +++ b/test/xray/generator.go @@ -0,0 +1,103 @@ +package xray + +import ( + "context" + "errors" + "log" + "os" + "path" + "time" + "github.com/aws/amazon-cloudwatch-agent-test/util/common" + "github.com/aws/aws-xray-sdk-go/strategy/sampling" + "github.com/aws/aws-xray-sdk-go/xray" + "github.com/aws/aws-xray-sdk-go/xraylog" +) + +var generatorError = errors.New("Generator error") +type XrayTracesGenerator struct { + common.TraceGenerator + common.TraceGeneratorInterface +} + +func (g *XrayTracesGenerator) StartSendingTraces(ctx context.Context) error { + ticker := time.NewTicker(g.Cfg.Interval) + for { + select { + case <-g.Done: + ticker.Stop() + return nil + case <-ticker.C: + if err := g.Generate(ctx); err != nil { + return err + } + } + } +} +func (g *XrayTracesGenerator) StopSendingTraces() { + close(g.Done) +} +func newLoadGenerator(cfg *common.TraceGeneratorConfig) *XrayTracesGenerator { + s, err := sampling.NewLocalizedStrategyFromFilePath( + path.Join("resources", "sampling-rule.json")) + if err != nil { + log.Fatalf("Couldn't apply sampling rule : %s", err) + } + xray.Configure(xray.Config{SamplingStrategy: s}) + xray.SetLogger(xraylog.NewDefaultLogger(os.Stdout, xraylog.LogLevelWarn)) + return &XrayTracesGenerator{ + TraceGenerator: common.TraceGenerator{ + Cfg: cfg, + Done: make(chan struct{}), + SegmentsGenerationCount: 0, + SegmentsEndedCount: 0, + }, + } +} +func (g *XrayTracesGenerator) Generate(ctx context.Context) error { + rootCtx, root := xray.BeginSegment(ctx, "load-generator") + g.SegmentsGenerationCount++ + defer func() { + root.Close(nil) + g.SegmentsEndedCount++ + }() + + for key, value := range g.Cfg.Annotations { + if err := root.AddAnnotation(key, value); err != nil { + return err + } + } + + for namespace, metadata := range g.Cfg.Metadata { + for key, value := range metadata { + if err := root.AddMetadataToNamespace(namespace, key, value); err != nil { + return err + } + } + } + + _, subSeg := xray.BeginSubsegment(rootCtx, "with-error") + defer subSeg.Close(nil) + + if err := subSeg.AddError(generatorError); err != nil { + return err + } + + return nil +} + +func (g *XrayTracesGenerator) GetSegmentCount() (int, int) { + return g.SegmentsGenerationCount, g.SegmentsEndedCount +} + +func (g *XrayTracesGenerator) GetAgentConfigPath() string { + return g.AgentConfigPath +} +func (g *XrayTracesGenerator) GetAgentRuntime() time.Duration { + return g.AgentRuntime +} +func (g *XrayTracesGenerator) GetName() string { + return g.Name +} +func (g *XrayTracesGenerator) GetGeneratorConfig() *common.TraceGeneratorConfig { + return g.Cfg +} diff --git a/test/xray/resources/sampling-rule.json b/test/xray/resources/sampling-rule.json new file mode 100644 index 000000000..72d46496e --- /dev/null +++ b/test/xray/resources/sampling-rule.json @@ -0,0 +1,17 @@ +{ + "version": 2, + "rules": [ + { + "description": "debug", + "host": "*", + "http_method": "*", + "url_path": "*", + "fixed_target": 0, + "rate": 1.0 + } + ], + "default": { + "fixed_target": 1, + "rate": 1.0 + } + } \ No newline at end of file diff --git a/test/xray/resources/xray-config.json b/test/xray/resources/xray-config.json new file mode 100644 index 000000000..75be23507 --- /dev/null +++ b/test/xray/resources/xray-config.json @@ -0,0 +1,11 @@ +{ + "agent":{ + "debug":true + }, + "traces": { + "traces_collected": { + "xray": { + } + } + } +} \ No newline at end of file diff --git a/test/xray/trace_test.go b/test/xray/trace_test.go new file mode 100644 index 000000000..73f803b02 --- /dev/null +++ b/test/xray/trace_test.go @@ -0,0 +1,67 @@ +package xray + +import ( + "path/filepath" + "testing" + "time" + + "github.com/aws/amazon-cloudwatch-agent-test/environment" + "github.com/aws/amazon-cloudwatch-agent-test/util/common" + "github.com/stretchr/testify/require" +) + +const ( + agentRuntime = 1 * time.Minute + loadGeneratorInterval = 6 * time.Second +) + +// WARNING: If you increase number of segments generated +// You might see that the xray is dropping segments +// To overcome this please update the sampling-rule such that the "rate" is higher. +func init() { + environment.RegisterEnvironmentMetaDataFlags() +} + +func TestTraces(t *testing.T) { + env := environment.GetEnvironmentMetaData() + testCases := map[string]struct { + agentConfigPath string + generatorConfig *common.TraceGeneratorConfig + }{ + "WithXray/Simple": { + agentConfigPath: filepath.Join("resources", "xray-config.json"), + generatorConfig: &common.TraceGeneratorConfig{ + Interval: loadGeneratorInterval, + Annotations: map[string]interface{}{ + "test_type": "simple_xray", + "instance_id": env.InstanceId, + "commit_sha": env.CwaCommitSha, + }, + Metadata: map[string]map[string]interface{}{ + "default": { + "nested": map[string]interface{}{ + "key": "value", + }, + }, + "custom_namespace": { + "custom_key": "custom_value", + }, + }, + }, + }, + } + for name, testCase := range testCases { + + t.Run(name, func(t *testing.T) { + XrayTestCfg := common.TraceTestConfig{ + Generator: newLoadGenerator(testCase.generatorConfig), + Name: name, + AgentConfigPath: testCase.agentConfigPath, + AgentRuntime: agentRuntime, + } + err := common.TraceTest(t, XrayTestCfg) + require.NoError(t, err, "TraceTest failed because %s", err) + + }) + } +} diff --git a/util/awsservice/cloudwatchlogs.go b/util/awsservice/cloudwatchlogs.go index 18523d842..1b0c56e62 100644 --- a/util/awsservice/cloudwatchlogs.go +++ b/util/awsservice/cloudwatchlogs.go @@ -6,7 +6,9 @@ package awsservice import ( "context" "errors" + "fmt" "log" + "strings" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -51,21 +53,26 @@ func DeleteLogGroup(logGroupName string) { // ValidateLogs queries a given LogGroup/LogStream combination given the start and end times, and executes an // arbitrary validator function on the found logs. -func ValidateLogs(logGroup, logStream string, since, until *time.Time, validator func(logs []string) bool) (bool, error) { - log.Printf("Checking %s/%s\n", logGroup, logStream) +func ValidateLogs(logGroup, logStream string, since, until *time.Time, validators ...LogEventsValidator) error { + log.Printf("Checking %s/%s", logGroup, logStream) - foundLogs, err := getLogsSince(logGroup, logStream, since, until) + events, err := getLogsSince(logGroup, logStream, since, until) if err != nil { - return false, err + return err } - return validator(foundLogs), nil + for _, validator := range validators { + if err = validator(events); err != nil { + return err + } + } + return nil } // getLogsSince makes GetLogEvents API calls, paginates through the results for the given time frame, and returns // the raw log strings -func getLogsSince(logGroup, logStream string, since, until *time.Time) ([]string, error) { - foundLogs := make([]string, 0) +func getLogsSince(logGroup, logStream string, since, until *time.Time) ([]types.OutputLogEvent, error) { + var events []types.OutputLogEvent // https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_GetLogEvents.html // GetLogEvents can return an empty result while still having more log events on a subsequent page, @@ -103,22 +110,22 @@ func getLogsSince(logGroup, logStream string, since, until *time.Time) ([]string } // if the error is not a ResourceNotFoundException, we should fail here. - return foundLogs, err + return events, err } for _, e := range output.Events { - foundLogs = append(foundLogs, *e.Message) + events = append(events, e) } if nextToken != nil && output.NextForwardToken != nil && *output.NextForwardToken == *nextToken { // From the docs: If you have reached the end of the stream, it returns the same token you passed in. - log.Printf("Done paginating log events for %s/%s and found %d logs", logGroup, logStream, len(foundLogs)) + log.Printf("Done paginating log events for %s/%s and found %d logs", logGroup, logStream, len(events)) break } nextToken = output.NextForwardToken } - return foundLogs, nil + return events, nil } // IsLogGroupExists confirms whether the logGroupName exists or not @@ -161,15 +168,96 @@ func GetLogStreams(logGroupName string) []types.LogStream { return []types.LogStream{} } -func MatchEMFLogWithSchema(logEntry string, s *jsonschema.Schema, logValidator func(string) bool) bool { - keyErrors, e := s.ValidateBytes(context.Background(), []byte(logEntry)) - if e != nil { - log.Println("failed to execute schema validator:", e) - return false - } else if len(keyErrors) > 0 { - log.Printf("failed schema validation: %v\n", keyErrors) - return false +type LogEventValidator func(event types.OutputLogEvent) error + +type LogEventsValidator func(events []types.OutputLogEvent) error + +type SchemaRetriever func(message string) (string, error) + +func WithSchema(schema string) SchemaRetriever { + return func(_ string) (string, error) { + return schema, nil } +} - return logValidator(logEntry) +func AssertLogSchema(schemaRetriever SchemaRetriever) LogEventValidator { + return func(event types.OutputLogEvent) error { + message := *event.Message + if schemaRetriever == nil { + return errors.New("nil schema retriever") + } + schema, err := schemaRetriever(*event.Message) + if err != nil { + return fmt.Errorf("unable to retrieve schema: %w", err) + } + keyErrors, err := jsonschema.Must(schema).ValidateBytes(context.Background(), []byte(message)) + if err != nil { + return fmt.Errorf("failed to execute schema validator: %w", err) + } else if len(keyErrors) > 0 { + return fmt.Errorf("failed schema validation: %v | schema: %s | log: %s", keyErrors, schema, message) + } + return nil + } +} + +func AssertLogContainsSubstring(substr string) LogEventValidator { + return func(event types.OutputLogEvent) error { + if !strings.Contains(*event.Message, substr) { + return fmt.Errorf("log event message missing substring (%s): %s", substr, *event.Message) + } + return nil + } +} + +// AssertPerLog runs each validator on each of the log events. Fails fast. +func AssertPerLog(validators ...LogEventValidator) LogEventsValidator { + return func(events []types.OutputLogEvent) error { + for _, event := range events { + for _, validator := range validators { + if err := validator(event); err != nil { + return err + } + } + } + return nil + } +} + +func AssertLogsNotEmpty() LogEventsValidator { + return func(events []types.OutputLogEvent) error { + if len(events) == 0 { + return errors.New("no log events") + } + return nil + } +} + +func AssertLogsCount(count int) LogEventsValidator { + return func(events []types.OutputLogEvent) error { + if len(events) != count { + return fmt.Errorf("actual log events count (%v) does not match expected (%v)", len(events), count) + } + return nil + } +} + +func AssertNoDuplicateLogs() LogEventsValidator { + return func(events []types.OutputLogEvent) error { + byTimestamp := make(map[int64]map[string]struct{}) + for _, event := range events { + message := *event.Message + timestamp := *event.Timestamp + messages, ok := byTimestamp[timestamp] + if !ok { + messages = map[string]struct{}{} + byTimestamp[timestamp] = messages + } + _, ok = messages[message] + if ok { + return fmt.Errorf("duplicate message found at %v | message: %s", time.UnixMilli(timestamp), message) + } + messages[message] = struct{}{} + } + return nil + } } diff --git a/util/awsservice/cloudwatchmetrics.go b/util/awsservice/cloudwatchmetrics.go index b2d17f203..998dd7961 100644 --- a/util/awsservice/cloudwatchmetrics.go +++ b/util/awsservice/cloudwatchmetrics.go @@ -57,10 +57,18 @@ func ValidateMetric(metricName, namespace string, dimensionsFilter []types.Dimen } // ValidateMetrics takes the metric name, metric dimension and corresponding namespace that contains the metric -func ValidateMetricWithTest(t *testing.T, metricName, namespace string, dimensionsFilter []types.DimensionFilter) { - err := ValidateMetric(metricName, namespace, dimensionsFilter) +func ValidateMetricWithTest(t *testing.T, metricName, namespace string, dimensionsFilter []types.DimensionFilter, retries int, retryTime time.Duration) { + var err error + for i := 0; i < retries; i++ { + err = ValidateMetric(metricName, namespace, dimensionsFilter) + if err == nil { + return + } + log.Printf("could not validate metrics try : %d of %d error %v", i+1, retries, err) + time.Sleep(retryTime) + } if err != nil { - t.Errorf(err.Error()) + t.Errorf("could not validate metrics") } } diff --git a/util/awsservice/xray.go b/util/awsservice/xray.go new file mode 100644 index 000000000..8c22fb871 --- /dev/null +++ b/util/awsservice/xray.go @@ -0,0 +1,92 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT + +package awsservice + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/xray" + "github.com/aws/aws-sdk-go-v2/service/xray/types" +) + +const ( + // BatchGetTraces has a max trace ID size of 5. + batchGetTraceSizes = 5 +) + +func FilterExpression(annotations map[string]interface{}) string { + var expression string + for key, value := range annotations { + result, err := json.Marshal(value) + if err != nil { + continue + } + if len(expression) != 0 { + expression += " AND " + } + expression += fmt.Sprintf("annotation.%s = %s", key, result) + } + return expression +} + +func GetTraceIDs(startTime time.Time, endTime time.Time, filter string) ([]string, error) { + var traceIDs []string + input := &xray.GetTraceSummariesInput{StartTime: aws.Time(startTime), EndTime: aws.Time(endTime), FilterExpression: aws.String(filter)} + for { + output, err := XrayClient.GetTraceSummaries(context.Background(), input) + if err != nil { + return nil, err + } + for _, summary := range output.TraceSummaries { + traceIDs = append(traceIDs, *summary.Id) + } + if output.NextToken == nil { + break + } + input.NextToken = output.NextToken + } + return traceIDs, nil +} + +func GetSegments(traceIDs []string) ([]types.Segment, error) { + var segments []types.Segment + traces, err := GetBatchTraces(traceIDs) + if err != nil { + return nil, err + } + for _, trace := range traces { + segments = append(segments, trace.Segments...) + } + return segments, nil +} + +func GetBatchTraces(traceIDs []string) ([]types.Trace, error) { + var traces []types.Trace + length := len(traceIDs) + for i := 0; i < length; i += batchGetTraceSizes { + j := i + batchGetTraceSizes + if j > length { + j = length + } + input := &xray.BatchGetTracesInput{TraceIds: traceIDs[i:j]} + for { + output, err := XrayClient.BatchGetTraces(context.Background(), input) + if err != nil { + return nil, err + } + for _, trace := range output.Traces { + traces = append(traces, trace) + } + if output.NextToken == nil { + break + } + input.NextToken = output.NextToken + } + } + return traces, nil +} diff --git a/util/common/agent_util_unix.go b/util/common/agent_util_unix.go index 64f364cd9..03c9a7287 100644 --- a/util/common/agent_util_unix.go +++ b/util/common/agent_util_unix.go @@ -6,13 +6,15 @@ package common import ( + "bytes" "fmt" - "github.com/aws/amazon-cloudwatch-agent-test/environment" "log" "os/exec" "path/filepath" "strings" "time" + + "github.com/aws/amazon-cloudwatch-agent-test/environment" ) const ( @@ -41,10 +43,14 @@ func CopyFile(pathIn string, pathOut string) { } log.Printf("File %s abs path %s", pathIn, pathInAbs) - out, err := exec.Command("bash", "-c", "sudo cp "+pathInAbs+" "+pathOut).Output() - + cmd := exec.Command("bash", "-c", "sudo cp "+pathInAbs+" "+pathOut) + var out bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + err = cmd.Run() if err != nil { - log.Fatal(fmt.Sprint(err) + string(out)) + log.Fatalf("Error : %s | Error Code: %s | Out: %s", fmt.Sprint(err), stderr.String(), out.String()) } log.Printf("File : %s copied to : %s", pathIn, pathOut) @@ -121,26 +127,6 @@ func InstallAgent(installerFilePath string) error { return err } -func StartAgentWithMultiConfig(configOutputPath string, fatalOnFailure bool, ssm bool) error { - path := "file:" - if ssm { - path = "ssm:" - } - out, err := exec. - Command("bash", "-c", "sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a append-config -m ec2 -s -c "+path+configOutputPath). - Output() - - if err != nil && fatalOnFailure { - log.Fatal(fmt.Sprint(err) + string(out)) - } else if err != nil { - log.Printf(fmt.Sprint(err) + string(out)) - } else { - log.Printf("Agent has started") - } - - return err -} - func StartAgent(configOutputPath string, fatalOnFailure bool, ssm bool) error { agentStartCommand := environment.GetEnvironmentMetaData().AgentStartCommand return StartAgentWithCommand(configOutputPath, fatalOnFailure, ssm, agentStartCommand) diff --git a/util/common/agent_util_windows.go b/util/common/agent_util_windows.go index a4883123d..2e932205c 100644 --- a/util/common/agent_util_windows.go +++ b/util/common/agent_util_windows.go @@ -33,9 +33,8 @@ func CopyFile(pathIn string, pathOut string) error { } log.Printf("File %s abs path %s", pathIn, pathInAbs) - params := append([]string{"-NoProfile", "-NonInteractive", "cp " + pathInAbs + " " + pathOut}) - out, err := exec.Command(ps, params...).Output() - + bashArgs := append([]string{"-NoProfile", "-NonInteractive", "cp " + pathInAbs + " " + pathOut}) + out, err := exec.Command(ps, bashArgs...).Output() if err != nil { log.Printf("Copy file failed: %v; the output is: %s", err, string(out)) @@ -47,29 +46,6 @@ func CopyFile(pathIn string, pathOut string) error { } -func StartAgentWithMultiConfig(configOutputPath string, fatalOnFailure bool, ssm bool) error { - - ps, err := exec.LookPath("powershell.exe") - - if err != nil { - return err - } - - params := append([]string{"-NoProfile", "-NonInteractive", "-NoExit", "& \"C:\\Program Files\\Amazon\\AmazonCloudWatchAgent\\amazon-cloudwatch-agent-ctl.ps1\" -a append-config -m ec2 -s -c file:" + configOutputPath}) - out, err := exec.Command(ps, params...).Output() - - if err != nil && fatalOnFailure { - log.Printf("Start agent failed: %v; the output is: %s", err, string(out)) - return err - } else if err != nil { - log.Printf(fmt.Sprint(err) + string(out)) - } else { - log.Printf("Agent has started") - } - - return err -} - func StartAgent(configOutputPath string, fatalOnFailure bool, ssm bool) error { // @TODO add ssm functionality @@ -79,8 +55,8 @@ func StartAgent(configOutputPath string, fatalOnFailure bool, ssm bool) error { return err } - params := append([]string{"-NoProfile", "-NonInteractive", "& \"C:\\Program Files\\Amazon\\AmazonCloudWatchAgent\\amazon-cloudwatch-agent-ctl.ps1\" -a fetch-config -m ec2 -s -c file:" + configOutputPath}) - out, err := exec.Command(ps, params...).Output() + bashArgs := append([]string{"-NoProfile", "-NonInteractive", "& \"C:\\Program Files\\Amazon\\AmazonCloudWatchAgent\\amazon-cloudwatch-agent-ctl.ps1\" -a fetch-config -m ec2 -s -c file:" + configOutputPath}) + out, err := exec.Command(ps, bashArgs...).Output() if err != nil && fatalOnFailure { log.Printf("Start agent failed: %v; the output is: %s", err, string(out)) @@ -101,8 +77,8 @@ func StopAgent() error { return err } - params := append([]string{"-NoProfile", "-NonInteractive", "& \"C:\\Program Files\\Amazon\\AmazonCloudWatchAgent\\amazon-cloudwatch-agent-ctl.ps1\" -a stop"}) - out, err := exec.Command(ps, params...).Output() + bashArgs := append([]string{"-NoProfile", "-NonInteractive", "& \"C:\\Program Files\\Amazon\\AmazonCloudWatchAgent\\amazon-cloudwatch-agent-ctl.ps1\" -a stop"}) + out, err := exec.Command(ps, bashArgs...).Output() if err != nil { log.Printf("Stop agent failed: %v; the output is: %s", err, string(out)) diff --git a/util/common/traces.go b/util/common/traces.go new file mode 100644 index 000000000..b22dd1983 --- /dev/null +++ b/util/common/traces.go @@ -0,0 +1,114 @@ +package common + +import ( + "context" + "encoding/json" + "reflect" + "testing" + "time" + + "github.com/aws/amazon-cloudwatch-agent-test/util/awsservice" + "github.com/aws/aws-sdk-go-v2/service/xray/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/attribute" +) + +const ( + AGENT_SHUTDOWN_DELAY = 20 * time.Second // this const is the delay between stopping trace generation and stopping agent +) + +type TraceTestConfig struct { + Generator TraceGeneratorInterface + Name string + AgentConfigPath string + AgentRuntime time.Duration +} +type TraceGeneratorConfig struct { + Interval time.Duration + Annotations map[string]interface{} + Metadata map[string]map[string]interface{} + Attributes []attribute.KeyValue +} +type TraceGenerator struct { + Cfg *TraceGeneratorConfig + SegmentsGenerationCount int + SegmentsEndedCount int + AgentConfigPath string + AgentRuntime time.Duration + Name string + Done chan struct{} +} +type TraceGeneratorInterface interface { + StartSendingTraces(ctx context.Context) error + StopSendingTraces() + Generate(ctx context.Context) error + GetSegmentCount() (int, int) + GetAgentConfigPath() string + GetGeneratorConfig() *TraceGeneratorConfig + GetContext() context.Context + GetAgentRuntime() time.Duration + GetName() string +} + +func TraceTest(t *testing.T, traceTest TraceTestConfig) error { + t.Helper() + startTime := time.Now() + CopyFile(traceTest.AgentConfigPath, ConfigOutputPath) + require.NoError(t, StartAgent(ConfigOutputPath, true, false), "Couldn't Start the agent") + go func() { + require.NoError(t, traceTest.Generator.StartSendingTraces(context.Background()), "load generator exited with error") + }() + time.Sleep(traceTest.AgentRuntime) + traceTest.Generator.StopSendingTraces() + time.Sleep(AGENT_SHUTDOWN_DELAY) + StopAgent() + testsGenerated, testsEnded := traceTest.Generator.GetSegmentCount() + t.Logf("For %s , Test Cases Generated %d | Test Cases Ended: %d", traceTest.Name, testsGenerated, testsEnded) + endTime := time.Now() + t.Logf("Agent has been running for %s", endTime.Sub(startTime)) + time.Sleep(10 * time.Second) + + traceIDs, err := awsservice.GetTraceIDs(startTime, endTime, awsservice.FilterExpression( + traceTest.Generator.GetGeneratorConfig().Annotations)) + require.NoError(t, err, "unable to get trace IDs") + segments, err := awsservice.GetSegments(traceIDs) + require.NoError(t, err, "unable to get segments") + + assert.True(t, len(segments) >= testsGenerated, + "FAILED: Not enough segments, expected %d but got %d , traceIDCount: %d", + testsGenerated, len(segments), len(traceIDs)) + require.NoError(t, SegmentValidationTest(t, traceTest, segments), "Segment Validation Failed") + return nil +} + +func SegmentValidationTest(t *testing.T, traceTest TraceTestConfig, segments []types.Segment) error { + t.Helper() + cfg := traceTest.Generator.GetGeneratorConfig() + for _, segment := range segments { + var result map[string]interface{} + require.NoError(t, json.Unmarshal([]byte(*segment.Document), &result)) + if _, ok := result["parent_id"]; ok { + // skip subsegments + continue + } + annotations, ok := result["annotations"] + assert.True(t, ok, "missing annotations") + assert.True(t, reflect.DeepEqual(annotations, cfg.Annotations), "mismatching annotations") + metadataByNamespace, ok := result["metadata"].(map[string]interface{}) + assert.True(t, ok, "missing metadata") + for namespace, wantMetadata := range cfg.Metadata { + var gotMetadata map[string]interface{} + gotMetadata, ok = metadataByNamespace[namespace].(map[string]interface{}) + assert.Truef(t, ok, "missing metadata in namespace: %s", namespace) + for key, wantValue := range wantMetadata { + var gotValue interface{} + gotValue, ok = gotMetadata[key] + assert.Truef(t, ok, "missing expected metadata key: %s", key) + assert.Truef(t, reflect.DeepEqual(gotValue, wantValue), "mismatching values for key (%s):\ngot\n\t%v\nwant\n\t%v", key, gotValue, wantValue) + } + } + } + return nil + +} diff --git a/validator/validators/basic/basic_validator.go b/validator/validators/basic/basic_validator.go index f50c7479e..a99096504 100644 --- a/validator/validators/basic/basic_validator.go +++ b/validator/validators/basic/basic_validator.go @@ -9,7 +9,8 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" + cwtypes "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" + cwltypes "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" "github.com/aws/aws-sdk-go/aws" "go.uber.org/multierr" @@ -60,18 +61,18 @@ func (s *BasicValidator) CheckData(startTime, endTime time.Time) error { ec2InstanceId = awsservice.GetInstanceId() metricNamespace = s.vConfig.GetMetricNamespace() validationMetric = s.vConfig.GetMetricValidation() - validationLog = s.vConfig.GetLogValidation() + logValidations = s.vConfig.GetLogValidation() ) for _, metric := range validationMetric { - metricDimensions := []types.Dimension{ + metricDimensions := []cwtypes.Dimension{ { Name: aws.String("InstanceId"), Value: aws.String(ec2InstanceId), }, } for _, dimension := range metric.MetricDimension { - metricDimensions = append(metricDimensions, types.Dimension{ + metricDimensions = append(metricDimensions, cwtypes.Dimension{ Name: aws.String(dimension.Name), Value: aws.String(dimension.Value), }) @@ -82,8 +83,8 @@ func (s *BasicValidator) CheckData(startTime, endTime time.Time) error { } } - for _, log := range validationLog { - err := s.ValidateLogs(log.LogStream, log.LogValue, log.LogLevel, log.LogSource, log.LogLines, startTime, endTime) + for _, logValidation := range logValidations { + err := s.ValidateLogs(logValidation.LogStream, logValidation.LogValue, logValidation.LogLevel, logValidation.LogSource, logValidation.LogLines, startTime, endTime) if err != nil { multiErr = multierr.Append(multiErr, err) } @@ -105,40 +106,40 @@ func (s *BasicValidator) Cleanup() error { return nil } -func (s *BasicValidator) ValidateLogs(logStream, logLine, logLevel, logSource string, numberOfLogLine int, startTime, endTime time.Time) error { - var ( - logGroup = awsservice.GetInstanceId() - ) - log.Printf("Start to validate log '%s' with number of logs lines %d within log group %s, log stream %s, start time %v and end time %v", logLine, numberOfLogLine, logGroup, logStream, startTime, endTime) - ok, err := awsservice.ValidateLogs(logGroup, logStream, &startTime, &endTime, func(logs []string) bool { - if len(logs) < 1 { - return false - } - actualNumberOfLogLines := 0 - for _, l := range logs { - switch logSource { - case "WindowsEvents": - if logLevel != "" && strings.Contains(l, logLine) && strings.Contains(l, logLevel) { - actualNumberOfLogLines += 1 - } - default: - if strings.Contains(l, logLine) { - actualNumberOfLogLines += 1 +func (s *BasicValidator) ValidateLogs(logStream, logLine, logLevel, logSource string, expectedMinimumEventCount int, startTime, endTime time.Time) error { + logGroup := awsservice.GetInstanceId() + log.Printf("Start to validate that substring '%s' has at least %d log event(s) within log group %s, log stream %s, between %v and %v", logLine, expectedMinimumEventCount, logGroup, logStream, startTime, endTime) + return awsservice.ValidateLogs( + logGroup, + logStream, + &startTime, + &endTime, + awsservice.AssertLogsNotEmpty(), + awsservice.AssertNoDuplicateLogs(), + func(events []cwltypes.OutputLogEvent) error { + var actualEventCount int + for _, event := range events { + message := *event.Message + switch logSource { + case "WindowsEvents": + if logLevel != "" && strings.Contains(message, logLine) && strings.Contains(message, logLevel) { + actualEventCount += 1 + } + default: + if strings.Contains(message, logLine) { + actualEventCount += 1 + } } } - } - - return numberOfLogLine <= actualNumberOfLogLines - }) - - if !ok || err != nil { - return fmt.Errorf("\n the number of log line for '%s' is %d which does not match the actual number with log group %s, log stream %s, start time %v and end time %v with err %v", logLine, numberOfLogLine, logGroup, logStream, startTime, endTime, err) - } - - return nil + if actualEventCount < expectedMinimumEventCount { + return fmt.Errorf("log event count for %q in %s/%s between %v and %v is %d which is less than the expected %d", logLine, logGroup, logStream, startTime, endTime, actualEventCount, expectedMinimumEventCount) + } + return nil + }, + ) } -func (s *BasicValidator) ValidateMetric(metricName, metricNamespace string, metricDimensions []types.Dimension, metricValue float64, metricSampleCount int, startTime, endTime time.Time) error { +func (s *BasicValidator) ValidateMetric(metricName, metricNamespace string, metricDimensions []cwtypes.Dimension, metricValue float64, metricSampleCount int, startTime, endTime time.Time) error { var ( boundAndPeriod = s.vConfig.GetAgentCollectionPeriod().Seconds() ) @@ -174,18 +175,18 @@ func (s *BasicValidator) ValidateMetric(metricName, metricNamespace string, metr return nil } -func (s *BasicValidator) buildMetricQueries(metricName, metricNamespace string, metricDimensions []types.Dimension) []types.MetricDataQuery { +func (s *BasicValidator) buildMetricQueries(metricName, metricNamespace string, metricDimensions []cwtypes.Dimension) []cwtypes.MetricDataQuery { var metricQueryPeriod = int32(s.vConfig.GetAgentCollectionPeriod().Seconds()) - metricInformation := types.Metric{ + metricInformation := cwtypes.Metric{ Namespace: aws.String(metricNamespace), MetricName: aws.String(metricName), Dimensions: metricDimensions, } - metricDataQueries := []types.MetricDataQuery{ + metricDataQueries := []cwtypes.MetricDataQuery{ { - MetricStat: &types.MetricStat{ + MetricStat: &cwtypes.MetricStat{ Metric: &metricInformation, Period: &metricQueryPeriod, Stat: aws.String(string(models.AVERAGE)),