From 692c783154b34e9c209eaf66eca5a94416b8b680 Mon Sep 17 00:00:00 2001 From: Ashvitha Date: Mon, 30 Oct 2023 13:22:31 -0400 Subject: [PATCH] [CC 5965] Improve HCP Observability E2E tests and add periodic tests (#2946) * Setup observability metrics tests * Cleanup http_client.go and observability_test.go * Refactor tests by using table driven approach * Refactor and add comments to the client * Remove param to token function * remove consul export test redundant * Remove hardcoded collector image * Move metrics validation from server to consul-k8s tests and update to use the /records endpoint * Change to achooo docker hub and fix lint errors --- acceptance/go.mod | 13 +- acceptance/go.sum | 50 ++--- acceptance/tests/cloud/fakeserver_client.go | 158 ++++++++++++++ acceptance/tests/cloud/metrics_validation.go | 114 ++++++++++ .../{basic_test.go => observability_test.go} | 204 ++++++------------ .../bases/cloud/hcp-mock/deployment.yaml | 2 +- 6 files changed, 370 insertions(+), 171 deletions(-) create mode 100644 acceptance/tests/cloud/fakeserver_client.go create mode 100644 acceptance/tests/cloud/metrics_validation.go rename acceptance/tests/cloud/{basic_test.go => observability_test.go} (58%) diff --git a/acceptance/go.mod b/acceptance/go.mod index 8ba1ebd0bb..13b68936bf 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -13,6 +13,8 @@ require ( github.com/hashicorp/serf v0.10.1 github.com/hashicorp/vault/api v1.8.3 github.com/stretchr/testify v1.8.3 + go.opentelemetry.io/proto/otlp v1.0.0 + google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.26.3 k8s.io/apimachinery v0.26.3 @@ -30,7 +32,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set v1.7.1 // indirect @@ -61,6 +63,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/gruntwork-io/gruntwork-cli v0.7.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect @@ -123,7 +126,7 @@ require ( golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect golang.org/x/mod v0.9.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect @@ -131,9 +134,9 @@ require ( golang.org/x/tools v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect - google.golang.org/grpc v1.49.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/grpc v1.56.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/acceptance/go.sum b/acceptance/go.sum index 91dc2e489f..ebf575b207 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -81,7 +81,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -111,8 +110,9 @@ github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3 github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/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= @@ -120,11 +120,6 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= 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-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -177,8 +172,6 @@ github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry 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.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -306,6 +299,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= @@ -355,7 +349,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= @@ -375,7 +368,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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= @@ -392,7 +384,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/gruntwork-io/gruntwork-cli v0.7.0 h1:YgSAmfCj9c61H+zuvHwKfYUwlMhu5arnQQLM4RH+CYs= github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= github.com/gruntwork-io/terratest v0.31.2 h1:xvYHA80MUq5kx670dM18HInewOrrQrAN+XbVVtytUHg= @@ -517,7 +510,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -674,7 +667,6 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -776,7 +768,8 @@ go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZ go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs= go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ= go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -896,8 +889,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= 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= @@ -965,7 +958,6 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1127,7 +1119,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG 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= @@ -1135,8 +1126,11 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D 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-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= 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= @@ -1151,11 +1145,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa 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.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= 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= @@ -1168,10 +1159,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1195,7 +1184,6 @@ gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/acceptance/tests/cloud/fakeserver_client.go b/acceptance/tests/cloud/fakeserver_client.go new file mode 100644 index 0000000000..ec668d16e5 --- /dev/null +++ b/acceptance/tests/cloud/fakeserver_client.go @@ -0,0 +1,158 @@ +package cloud + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strconv" +) + +const ( + // recordsPathConsul and recordsPathCollector distinguish metrics for consul vs. collector when fetching records. + recordsPathConsul = "v1/metrics/consul" + recordsPathCollector = "v1/metrics/collector" +) + +var ( + errEncodingPayload = errors.New("failed to encode payload") + errCreatingRequest = errors.New("failed to create HTTP request") + errMakingRequest = errors.New("failed to make request") + errReadingBody = errors.New("failed to read body") + errClosingBody = errors.New("failed to close body") + errParsingBody = errors.New("failed to parse body") +) + +// fakeServerClient provides an interface to communicate with the fakesever (a fake HCP Telemetry Gateway) via HTTP. +type fakeServerClient struct { + client *http.Client + tunnel string +} + +// modifyTelemetryConfigBody is a POST body that provides telemetry config changes to the fakeserver. +type modifyTelemetryConfigBody struct { + Filters []string `json:"filters"` + Labels map[string]string `json:"labels"` + Disabled bool `json:"disabled"` +} + +// TokenResponse is used to read a token response from the fakeserver. +type TokenResponse struct { + Token string `json:"token"` +} + +// RecordsResponse is used to read a /records response from the fakeserver. +type RecordsResponse struct { + Records []*RequestRecord `json:"records"` +} + +// RequestRecord holds info about a single request. +type RequestRecord struct { + Method string `json:"method"` + Path string `json:"path"` + Body []byte `json:"body"` + ValidRequest bool `json:"validRequest"` + Timestamp int64 `json:"timestamp"` +} + +// newfakeServerClient returns a fakeServerClient to be used in tests to communicate with the fake Telemetry Gateway. +func newfakeServerClient(tunnel string) *fakeServerClient { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + + return &fakeServerClient{ + client: &http.Client{Transport: tr}, + tunnel: tunnel, + } +} + +// requestToken retrieves a token from the fakeserver's token endpoint. +func (f *fakeServerClient) requestToken() (string, error) { + url := fmt.Sprintf("https://%s/token", f.tunnel) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return "", fmt.Errorf("%w: %w", errCreatingRequest, err) + } + + resp, err := f.handleRequest(req) + if err != nil { + return "", err + } + + tokenResponse := &TokenResponse{} + err = json.Unmarshal(resp, tokenResponse) + if err != nil { + return "", fmt.Errorf("%w : %w", errParsingBody, err) + } + + return tokenResponse.Token, nil +} + +// modifyTelemetryConfig can update the telemetry config returned by the fakeserver. +// via the fakeserver's modify_telemetry_config endpoint. +func (f *fakeServerClient) modifyTelemetryConfig(payload *modifyTelemetryConfigBody) error { + url := fmt.Sprintf("https://%s/modify_telemetry_config", f.tunnel) + payloadBuf := new(bytes.Buffer) + + err := json.NewEncoder(payloadBuf).Encode(payload) + if err != nil { + return fmt.Errorf("%w:%w", errEncodingPayload, err) + } + + req, err := http.NewRequest("POST", url, payloadBuf) + if err != nil { + return fmt.Errorf("%w: %w", errCreatingRequest, err) + } + + _, err = f.handleRequest(req) + + return err +} + +func (f *fakeServerClient) getRecordsForPath(path string, refreshTime int64) ([]*RequestRecord, error) { + url := fmt.Sprintf("https://%s/records/%s", f.tunnel, path) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, fmt.Errorf("%w: %w", errCreatingRequest, err) + } + if refreshTime > 0 { + q := req.URL.Query() + q.Add("since", strconv.FormatInt(refreshTime, 10)) + req.URL.RawQuery = q.Encode() + } + + resp, err := f.handleRequest(req) + if err != nil { + return nil, err + } + + recordsResponse := &RecordsResponse{} + err = json.Unmarshal(resp, recordsResponse) + if err != nil { + return nil, fmt.Errorf("%w : %w", errParsingBody, err) + } + + return recordsResponse.Records, nil +} + +// handleRequest returns the response body if the request is succesful. +func (f *fakeServerClient) handleRequest(req *http.Request) ([]byte, error) { + resp, err := f.client.Do(req) + if err != nil { + return nil, fmt.Errorf("%w : %w", errMakingRequest, err) + } + body, err := io.ReadAll(resp.Body) + cErr := resp.Body.Close() + if cErr != nil { + return nil, fmt.Errorf("%w : %w", errClosingBody, err) + } + if err != nil { + return nil, fmt.Errorf("%w : %w", errReadingBody, err) + } + + return body, nil +} diff --git a/acceptance/tests/cloud/metrics_validation.go b/acceptance/tests/cloud/metrics_validation.go new file mode 100644 index 0000000000..558ae54509 --- /dev/null +++ b/acceptance/tests/cloud/metrics_validation.go @@ -0,0 +1,114 @@ +package cloud + +import ( + "strings" + + "github.com/hashicorp/serf/testutil/retry" + "github.com/stretchr/testify/require" + otlpcolmetrics "go.opentelemetry.io/proto/otlp/collector/metrics/v1" + otlpcommon "go.opentelemetry.io/proto/otlp/common/v1" + otlpmetrics "go.opentelemetry.io/proto/otlp/metrics/v1" + "google.golang.org/protobuf/proto" +) + +type metricValidations struct { + disabled bool + expectedMetricName string + disallowedMetricName string + expectedLabelKeys []string +} + +// validateMetrics ensure OTLP metrics as recorded by the Collector or Consul as expected. +func validateMetrics(r *retry.R, records []*RequestRecord, validations *metricValidations, since int64) { + // If metrics are disabled, no metrics records should exist, and return early. + if validations.disabled { + require.Empty(r, records) + return + } + + // If metrics are not disabled, records should not be empty. + require.NotEmpty(r, records) + + for _, record := range records { + require.True(r, record.ValidRequest, "expected request to be valid") + + req := &otlpcolmetrics.ExportMetricsServiceRequest{} + err := proto.Unmarshal(record.Body, req) + require.NoError(r, err, "failed to extract metrics from body") + + // Basic validation that metrics are not empty. + require.NotEmpty(r, req.GetResourceMetrics()) + require.NotEmpty(r, req.ResourceMetrics[0].GetScopeMetrics()) + require.NotEmpty(r, req.ResourceMetrics[0].ScopeMetrics[0].GetMetrics()) + + // Verify expected key labels and metric names. + labels := externalLabels(req, since) + for _, key := range validations.expectedLabelKeys { + require.Contains(r, labels, key) + } + validateMetricName(r, req, validations) + } +} + +// validateMetricName ensures an expected metric name has been recorded based on filters and disallowed metrics are not present. +func validateMetricName(t *retry.R, request *otlpcolmetrics.ExportMetricsServiceRequest, validations *metricValidations) { + exists := false + for _, metric := range request.ResourceMetrics[0].ScopeMetrics[0].GetMetrics() { + require.NotContains(t, metric.Name, validations.disallowedMetricName) + + if strings.Contains(metric.Name, validations.expectedMetricName) { + exists = true + } + } + + require.True(t, exists) +} + +// externalLabels converts OTLP labels to a map[string]string format. +func externalLabels(request *otlpcolmetrics.ExportMetricsServiceRequest, since int64) map[string]string { + // For the Consul Telemetry Collector, labels are contained at the higher level scope. + attrs := request.ResourceMetrics[0].GetResource().GetAttributes() + + // For Consul server metrics, labels are contained with individual metrics, and must be extracted. + if len(attrs) < 1 { + attrs = getMetricLabel(request.ResourceMetrics[0].GetScopeMetrics(), since) + } + + labels := make(map[string]string, len(attrs)) + for _, kv := range attrs { + k := strings.ReplaceAll(kv.GetKey(), ".", "_") + labels[k] = kv.GetValue().GetStringValue() + } + + return labels +} + +// getMetricLabel returns labels at each datapoint within a metric. +func getMetricLabel(scopeMetrics []*otlpmetrics.ScopeMetrics, since int64) []*otlpcommon.KeyValue { + // The attributes field can only be accessed on the specific implementation (gauge, sum or hist). + for _, metric := range scopeMetrics[0].Metrics { + switch v := metric.Data.(type) { + case *otlpmetrics.Metric_Gauge: + for _, dp := range v.Gauge.GetDataPoints() { + // When a refresh has occured, filter time since last refresh as older data points may not have latest labels. + if dp.StartTimeUnixNano > uint64(since) { + return dp.Attributes + } + } + case *otlpmetrics.Metric_Histogram: + for _, dp := range v.Histogram.GetDataPoints() { + if dp.StartTimeUnixNano > uint64(since) { + return dp.Attributes + } + } + case *otlpmetrics.Metric_Sum: + for _, dp := range v.Sum.GetDataPoints() { + if dp.StartTimeUnixNano > uint64(since) { + return dp.Attributes + } + } + } + } + + return []*otlpcommon.KeyValue{} +} diff --git a/acceptance/tests/cloud/basic_test.go b/acceptance/tests/cloud/observability_test.go similarity index 58% rename from acceptance/tests/cloud/basic_test.go rename to acceptance/tests/cloud/observability_test.go index e17169700a..5a2bf7b365 100644 --- a/acceptance/tests/cloud/basic_test.go +++ b/acceptance/tests/cloud/observability_test.go @@ -4,12 +4,6 @@ package cloud import ( - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" "strings" "testing" "time" @@ -24,10 +18,6 @@ import ( "github.com/stretchr/testify/require" ) -type TokenResponse struct { - Token string `json:"token"` -} - var ( resourceSecretName = "resource-sec-name" resourceSecretKey = "resource-sec-key" @@ -54,47 +44,7 @@ var ( scadaAddressSecretKeyValue = "fake-server:443" ) -// The fake-server has a requestToken endpoint to retrieve the token. -func requestToken(endpoint string) (string, error) { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - - client := &http.Client{Transport: tr} - url := fmt.Sprintf("https://%s/token", endpoint) - req, err := http.NewRequest("GET", url, nil) - if err != nil { - fmt.Println("Error creating request:", err) - return "", errors.New("error creating request") - } - - // Perform the request - resp, err := client.Do(req) - if err != nil { - fmt.Println("Error sending request:", err) - return "", errors.New("error making request") - } - defer resp.Body.Close() - - // Read the response body - body, err := io.ReadAll(resp.Body) - if err != nil { - fmt.Println("Error reading response:", err) - return "", errors.New("error reading body") - } - - var tokenResponse TokenResponse - err = json.Unmarshal(body, &tokenResponse) - if err != nil { - fmt.Println("Error parsing response:", err) - return "", errors.New("error parsing body") - } - - return tokenResponse.Token, nil - -} - -func TestBasicCloud(t *testing.T) { +func TestObservabilityCloud(t *testing.T) { ctx := suite.Environment().DefaultContext(t) kubectlOptions := ctx.KubectlOptions(t) @@ -138,8 +88,9 @@ func TestBasicCloud(t *testing.T) { require.NoError(r, tunnel.ForwardPortE(t)) }) + fsClient := newfakeServerClient(tunnel.Endpoint()) logger.Log(t, "fake-server addr:"+tunnel.Endpoint()) - consulToken, err := requestToken(tunnel.Endpoint()) + consulToken, err := fsClient.requestToken() if err != nil { logger.Log(t, "error finding consul token") return @@ -171,13 +122,6 @@ func TestBasicCloud(t *testing.T) { "global.cloud.scadaAddress.secretKey": scadaAddressSecretKey, "connectInject.default": "true", - // TODO: Follow up with this bug - "global.acls.manageSystemACLs": "false", - "global.gossipEncryption.autoGenerate": "false", - "global.tls.enabled": "true", - "global.tls.enableAutoEncrypt": "true", - // TODO: Take this out - "telemetryCollector.enabled": "true", "telemetryCollector.image": cfg.ConsulCollectorImage, "telemetryCollector.cloud.clientId.secretName": clientIDSecretName, @@ -185,8 +129,6 @@ func TestBasicCloud(t *testing.T) { "telemetryCollector.cloud.clientSecret.secretName": clientSecretName, "telemetryCollector.cloud.clientSecret.secretKey": clientSecretKey, - // Either we set the global.trustedCAs (make sure it's idented exactly) or we - // set TLS to insecure "telemetryCollector.extraEnvironmentVars.HCP_API_TLS": "insecure", "telemetryCollector.extraEnvironmentVars.HCP_AUTH_TLS": "insecure", @@ -196,33 +138,10 @@ func TestBasicCloud(t *testing.T) { "server.extraEnvironmentVars.HCP_API_TLS": "insecure", "server.extraEnvironmentVars.HCP_AUTH_TLS": "insecure", "server.extraEnvironmentVars.HCP_SCADA_TLS": "insecure", - - // This is pregenerated CA used for testing. It can be replaced at any time and isn't - // meant for anything other than testing - // "global.trustedCAs[0]": `-----BEGIN CERTIFICATE----- - // MIICrjCCAZYCCQD5LxMcnMY8rDANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDDA5m - // YWtlLXNlcnZlci1jYTAeFw0yMzA1MTkxMjIwMzhaFw0zMzA1MTYxMjIwMzhaMBkx - // FzAVBgNVBAMMDmZha2Utc2VydmVyLWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A - // MIIBCgKCAQEAwhbiII7sMultedFzQVhVZz5Ti+9lWrpZb8y0ZR6NaNvoxDPX151t - // Adh5NegSeH/+351iDBGZHhmKECtBuk8FJgk88O7y8A7Yg+/lyeZd0SJTEeiYUe7d - // sSaBTYSmixyn6s15Y5MVp9gM7t2YXrocRkFxDtdhLMWf0zwzJEwDouFMMiFZw5II - // yDbI6UfwKyB8C8ln10+TcczbheaOMQ1jGn35YWAG/LEdutU6DO2Y/GZYQ41nyLF1 - // klqh34USQPVQSQW7R7GiDxyhh1fGaDF6RAzH4RerzQSNvvTHmBXIGurB/Hnu1n3p - // CwWeatWMU5POy1es73S/EPM0NpWD5RabSwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB - // AQBayoTltSW55PvKVp9cmqGOBMlkIMKPd6Ny4bCb/3UF+3bzQmIblh3O3kEt7WoY - // fA9vp+6cSRGVqgBfR2bi40RrerLNA79yywIZjfBMteNuRoul5VeD+mLyFCo4197r - // Atl2TEx2kl2V8rjCsEBcTqKqetVOMLYEZ2tbCeUt1A/K7OzaJfHgelEYcsVt68Q9 - // /BLoo2UXfOpRrcsx7u7s5HPVbG3bx+1MvGJZ2C3i0B6agnkGDzEpoM4KZGxEefB9 - // DOHIJfie9d9BQD52nZh3SGHz0b3vfJ430XrQmaNZ26fuIEyIYrpvyAhBXckj2iTD - // 1TXpqr/1D7EUbddktyhXTK9e - // -----END CERTIFICATE-----`, } if cfg.ConsulImage != "" { helmValues["global.image"] = cfg.ConsulImage } - if cfg.ConsulCollectorImage != "" { - helmValues["telemetryCollector.image"] = cfg.ConsulCollectorImage - } consulCluster := consul.NewHelmCluster(t, helmValues, suite.Environment().DefaultContext(t), suite.Config(), releaseName) consulCluster.Create(t) @@ -231,56 +150,73 @@ func TestBasicCloud(t *testing.T) { k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.NoCleanup, cfg.DebugDirectory, "../fixtures/bases/static-server") t.Log("Finished deployment. Validating expected conditions now") - // Give some time for collector send metrics - time.Sleep(5 * time.Second) - err = validate(tunnel.Endpoint()) - logger.Log(t, fmt.Sprintf("result: %v", err)) - require.NoError(t, err) -} - -func validate(endpoint string) error { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - - client := &http.Client{Transport: tr} - url := fmt.Sprintf("https://%s/validation", endpoint) - req, err := http.NewRequest("GET", url, nil) - if err != nil { - fmt.Println("Error creating request:", err) - return errors.New("error creating validation request") + for name, tc := range map[string]struct { + refresh *modifyTelemetryConfigBody + refreshTime int64 + recordsPath string + timeout time.Duration + wait time.Duration + validations *metricValidations + }{ + "collectorExportsMetrics": { + recordsPath: recordsPathCollector, + // High timeout as Collector metrics scraped every 1 minute (https://github.com/hashicorp/consul-telemetry-collector/blob/dfdbf51b91d502a18f3b143a94ab4d50cdff10b8/internal/otel/config/helpers/receivers/prometheus_receiver.go#L54) + timeout: 5 * time.Minute, + wait: 1 * time.Second, + validations: &metricValidations{ + expectedLabelKeys: []string{"service_name", "service_instance_id"}, + expectedMetricName: "otelcol_receiver_accepted_metric_points", + disallowedMetricName: "server.memory_heap_size", + }, + }, + "consulPeriodicRefreshUpdateConfig": { + refresh: &modifyTelemetryConfigBody{ + Filters: []string{"consul.state"}, + Labels: map[string]string{"new_label": "testLabel"}, + }, + recordsPath: recordsPathConsul, + // High timeout as Consul server metrics exported every 1 minute (https://github.com/hashicorp/consul/blob/9776c10efb4472f196b47f88bc0db58b1bfa12ef/agent/hcp/telemetry/otel_sink.go#L27) + timeout: 3 * time.Minute, + wait: 30 * time.Second, + validations: &metricValidations{ + expectedLabelKeys: []string{"node_id", "node_name", "new_label"}, + expectedMetricName: "consul.state.services", + disallowedMetricName: "consul.fsm", + }, + }, + "consulPeriodicRefreshDisabled": { + refresh: &modifyTelemetryConfigBody{ + Filters: []string{"consul.state"}, + Labels: map[string]string{"new_label": "testLabel"}, + Disabled: true, + }, + recordsPath: recordsPathConsul, + // High timeout as Consul server metrics exported every 1 minute (https://github.com/hashicorp/consul/blob/9776c10efb4472f196b47f88bc0db58b1bfa12ef/agent/hcp/telemetry/otel_sink.go#L27) + timeout: 3 * time.Minute, + wait: 30 * time.Second, + validations: &metricValidations{ + disabled: true, + }, + }, + } { + t.Run(name, func(t *testing.T) { + // For a refresh test, we force a telemetry config update before validating metrics using fakeserver's /telemetry_config_modify endpoint. + if tc.refresh != nil { + refreshTime := time.Now() + err := fsClient.modifyTelemetryConfig(tc.refresh) + require.NoError(t, err) + // Add 10 seconds (2 * periodic refresh interval in fakeserver) to allow a periodic refresh from Consul side to take place. + tc.refreshTime = refreshTime.Add(10 * time.Second).UnixNano() + } + + // Validate metrics are correct using fakeserver's /records endpoint to retrieve metric exports that occured from Consul/Collector to fakeserver. + // We use retry as we wait for Consul or the Collector to export metrics. This is the best we can do to avoid flakiness. + retry.RunWith(&retry.Timer{Timeout: tc.timeout, Wait: tc.wait}, t, func(r *retry.R) { + records, err := fsClient.getRecordsForPath(tc.recordsPath, tc.refreshTime) + require.NoError(r, err) + validateMetrics(r, records, tc.validations, tc.refreshTime) + }) + }) } - - // Perform the request - resp, err := client.Do(req) - if err != nil { - fmt.Println("Error sending request:", err) - return errors.New("error making validation request") - } - if resp.StatusCode == http.StatusExpectationFailed { - // Read the response body - body, err := io.ReadAll(resp.Body) - if err != nil { - fmt.Println("Error reading response:", err) - return errors.New("error reading body") - } - var message errMsg - err = json.Unmarshal(body, &message) - if err != nil { - fmt.Println("Error parsing response:", err) - return errors.New("error parsing body") - } - - return fmt.Errorf("Failed validation: %s", message) - } else if resp.StatusCode != http.StatusOK { - return errors.New("unexpected status code response from failure") - } - - return nil - -} - -type errMsg struct { - Error string `json:"error"` } diff --git a/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml b/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml index 7278557cdb..78547d5118 100644 --- a/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml +++ b/acceptance/tests/fixtures/bases/cloud/hcp-mock/deployment.yaml @@ -19,7 +19,7 @@ spec: containers: - name: fake-server # TODO: move this to a hashicorp mirror - image: docker.io/chaapppie/fakeserver:latest + image: docker.io/achooo/fakeserver:latest ports: - containerPort: 443 name: https