From 295bff9d16876c4118e7e45f8d13b74bc2ec1959 Mon Sep 17 00:00:00 2001 From: Ewe Zi Yi <36802364+deadlycoconuts@users.noreply.github.com> Date: Thu, 18 May 2023 09:52:09 +0800 Subject: [PATCH 1/2] Update go mod mlp dependency (#337) --- api/go.mod | 2 +- api/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/go.mod b/api/go.mod index 88348f12a..d609e0c7a 100644 --- a/api/go.mod +++ b/api/go.mod @@ -8,7 +8,7 @@ require ( github.com/GoogleCloudPlatform/spark-on-k8s-operator v0.0.0-20220214044918-55732a6a392c github.com/antihax/optional v1.0.0 github.com/caraml-dev/merlin v0.0.0 - github.com/caraml-dev/mlp v1.7.6 + github.com/caraml-dev/mlp v1.7.7-0.20230428104022-779530aec912 github.com/caraml-dev/turing/engines/experiment v0.0.0 github.com/caraml-dev/turing/engines/router v0.0.0 github.com/caraml-dev/universal-prediction-interface v0.3.4 diff --git a/api/go.sum b/api/go.sum index b188500f9..5fdc93ae6 100644 --- a/api/go.sum +++ b/api/go.sum @@ -243,8 +243,8 @@ github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c/go. github.com/caraml-dev/merlin/api v0.0.0-20230403075012-795947162429 h1:utxGPa/erqKIUhgBFMgnbORjKUIqVKLs7VXa0ZB0jNY= github.com/caraml-dev/merlin/api v0.0.0-20230403075012-795947162429/go.mod h1:BRGKVbv3zEu9rE6pE2RNlj/IZfqy/3HEqBQGLK5rHMc= github.com/caraml-dev/merlin/python/batch-predictor v0.0.0-20230403075012-795947162429/go.mod h1:jYSIcxx7FDccKSva3mo12YhQ0rYuP4MOEbgSveY82HE= -github.com/caraml-dev/mlp v1.7.6 h1:u3OvbtPY7w/j9z7WO9YwhKJA0Y0Qy6OzanREfeA7os4= -github.com/caraml-dev/mlp v1.7.6/go.mod h1:ahdKpb/SKFEyHE6817AOh0b2fyroTzJmXM8U+2BG75M= +github.com/caraml-dev/mlp v1.7.7-0.20230428104022-779530aec912 h1:XQwsmz0CM5O+fchhQQe3W9llL5E5IqqJrhLkJhrlPuI= +github.com/caraml-dev/mlp v1.7.7-0.20230428104022-779530aec912/go.mod h1:ahdKpb/SKFEyHE6817AOh0b2fyroTzJmXM8U+2BG75M= github.com/caraml-dev/universal-prediction-interface v0.3.4 h1:cPytzpjXE/8RhSw3iS0JFZzNdM3tJ/l8UcHTPrxQWEo= github.com/caraml-dev/universal-prediction-interface v0.3.4/go.mod h1:e0qmFOXQxx8HFg5ObYyQO3WVnrqsr5v5JApFmeF7eJo= github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= From 21ddbb185a3962aa7c8c619eac2e6b22583a5b7c Mon Sep 17 00:00:00 2001 From: aria Date: Fri, 26 May 2023 10:24:56 +0800 Subject: [PATCH 2/2] Remove decryption when retrieving secret from MLP (#338) * Update mlp client * Remove decryption when retrieving secret from MLP * Fix lint * Fix mlp path * Update default mlp url in documentation and local dev setup --------- Co-authored-by: Pradithya Aria --- README.md | 4 +- api/.env.development | 2 +- api/config-dev.yaml | 2 +- api/e2e/test/router_e2e_test.go | 26 +++++----- api/e2e/test/router_test.go | 10 ++-- api/e2e/test/routers_suite_test.go | 10 ++-- api/go.mod | 23 +++++---- api/go.sum | 55 +++++++++++++--------- api/turing/api/appcontext.go | 3 +- api/turing/api/appcontext_test.go | 11 ++--- api/turing/config/config.go | 5 +- api/turing/config/config_test.go | 5 +- api/turing/service/mlp_service.go | 21 ++++----- api/turing/service/mlp_service_test.go | 30 ++++-------- infra/charts/turing/README.md | 8 ++-- infra/charts/turing/templates/_helpers.tpl | 2 +- 16 files changed, 104 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index 9c6d81a0a..559814baf 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,7 @@ ClusterConfig: TuringEncryptionKey: password MLPConfig: MerlinURL: http://localhost:8082/v1 - MLPURL: http://localhost:8081/v1 + MLPURL: http://localhost:8081 MLPEncryptionKey: password TuringUIConfig: ServingDirectory: ../ui/build @@ -337,7 +337,7 @@ Then, update the config file `.env.development.local` as shown below. ``` REACT_APP_HOMEPAGE=/turing REACT_APP_TURING_API=http://localhost:8080/v1 -REACT_APP_MLP_API=http://localhost:8081/v1 +REACT_APP_MLP_API=http://localhost:8081 REACT_APP_MERLIN_API=http://localhost:8082/v1 REACT_APP_OAUTH_CLIENT_ID=xxxxxxx.apps.googleusercontent.com REACT_APP_DEFAULT_DOCKER_REGISTRY=docker.io diff --git a/api/.env.development b/api/.env.development index 8559c9ae4..7822788a1 100644 --- a/api/.env.development +++ b/api/.env.development @@ -27,7 +27,7 @@ VAULT_ADDRESS=http://vault.example.com:8200/ VAULT_TOKEN= MERLIN_URL=http://mlp.example.com/api/merlin/v1 -MLP_URL=http://mlp.example.com/api/v1 +MLP_URL=http://mlp.example.com/api MLP_ENCRYPTION_KEY= TURING_ENCRYPTION_KEY=test_encryption_key diff --git a/api/config-dev.yaml b/api/config-dev.yaml index 86d8534b6..29d50c9c8 100644 --- a/api/config-dev.yaml +++ b/api/config-dev.yaml @@ -88,7 +88,7 @@ ClusterConfig: TuringEncryptionKey: password MLPConfig: MerlinURL: http://localhost:8082/v1 - MLPURL: http://localhost:8081/v1 + MLPURL: http://localhost:8081 MLPEncryptionKey: password TuringUIConfig: ServingDirectory: ../ui/build diff --git a/api/e2e/test/router_e2e_test.go b/api/e2e/test/router_e2e_test.go index 4aefb7194..c568664c4 100644 --- a/api/e2e/test/router_e2e_test.go +++ b/api/e2e/test/router_e2e_test.go @@ -65,7 +65,7 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp WithJSON(json.RawMessage(`[{"client": {"id": 4}}, {"client": {"id": 7}}]`)). Expect().Status(http.StatusOK). JSON().Array(). - Equal(JSONPayload("testdata/responses/router_proprietary_exp_batch_predict.json")) + IsEqual(JSONPayload("testdata/responses/router_proprietary_exp_batch_predict.json")) }) }) }) @@ -116,13 +116,13 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp }, defaultDeploymentIntervals...).Should(Succeed()) version. - ValueEqual("status", api.Status.Failed). - ValueEqual("error", "Requested CPU is more than max permissible") + HasValue("status", api.Status.Failed). + HasValue("error", "Requested CPU is more than max permissible") }) It("keeps previously deployed version active", func() { router = api.GetRouter(apiE, routerCtx.ProjectID, routerCtx.ID) - router.Path("$.config.version").Equal(1) + router.Path("$.config.version").IsEqual(1) }) }) }) @@ -197,8 +197,8 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp }, defaultDeploymentIntervals...).Should(Succeed()) version. - ValueEqual("status", api.Status.Failed). - ValueEqual("error", "Requested CPU is more than max permissible") + HasValue("status", api.Status.Failed). + HasValue("error", "Requested CPU is more than max permissible") }) It("keeps previous valid version as router's current version", func() { @@ -244,8 +244,8 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp }, defaultDeploymentIntervals...).Should(Succeed()) router. - ValueEqual("status", api.Status.Deployed). - Path("$.config.version").Equal(1) + HasValue("status", api.Status.Deployed). + Path("$.config.version").IsEqual(1) }) }) }) @@ -276,7 +276,7 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp }, defaultDeploymentIntervals...).Should(Succeed()) version. - ValueEqual("status", api.Status.Deployed). + HasValue("status", api.Status.Deployed). NotContainsKey("error") }) @@ -290,8 +290,8 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp It("updates router's configuration to the new version", func() { api.GetRouter(apiE, routerCtx.ProjectID, routerCtx.ID). - ValueEqual("status", api.Status.Deployed). - Path("$.config.version").Equal(3) + HasValue("status", api.Status.Deployed). + Path("$.config.version").IsEqual(3) }) }) @@ -320,7 +320,7 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp WithPath("routerId", routerCtx.ID). Expect().Status(http.StatusBadRequest). JSON(). - Equal(json.RawMessage(`{ + IsEqual(json.RawMessage(`{ "description": "invalid delete request", "error": "router is currently deployed. Undeploy it first." }`)) @@ -366,7 +366,7 @@ var _ = DeployedRouterContext("testdata/create_router_nop_logger_proprietary_exp WithPath("routerId", routerCtx.ID). Expect().Status(http.StatusNotFound). JSON(). - Equal(json.RawMessage(`{ + IsEqual(json.RawMessage(`{ "description": "router not found", "error": "record not found" }`)) diff --git a/api/e2e/test/router_test.go b/api/e2e/test/router_test.go index 8317d9a43..e4d49e559 100644 --- a/api/e2e/test/router_test.go +++ b/api/e2e/test/router_test.go @@ -37,7 +37,7 @@ var _ = DeployedRouterContext("testdata/create_router_std_ensembler_proprietary_ WithJSON(json.RawMessage(`{"client": {"id": 4}}`)). Expect(). Status(http.StatusOK). - JSON().Equal(json.RawMessage(`{"version": "control"}`)) + JSON().IsEqual(json.RawMessage(`{"version": "control"}`)) }) }) @@ -48,7 +48,7 @@ var _ = DeployedRouterContext("testdata/create_router_std_ensembler_proprietary_ WithJSON(json.RawMessage(`{"client": {"id": 7}}`)). Expect(). Status(http.StatusOK). - JSON().Equal(json.RawMessage(`{"version": "treatment-a"}`)) + JSON().IsEqual(json.RawMessage(`{"version": "treatment-a"}`)) }) }) }) @@ -70,7 +70,8 @@ var _ = DeployedRouterContext("testdata/create_router_with_traffic_rules.json.tm When("request satisfies the first traffic rule", func() { It("responds with responses from `treatment-a` route", func() { want = httpexpect. - NewValue(GinkgoT(), JSONPayload("testdata/responses/traffic_rules/traffic-rule-1.json")). + NewValue(GinkgoT(), + JSONPayload("testdata/responses/traffic_rules/traffic-rule-1.json")). Object() got = config.NewHTTPExpect(GinkgoT(), routerCtx.Endpoint). @@ -87,7 +88,8 @@ var _ = DeployedRouterContext("testdata/create_router_with_traffic_rules.json.tm When("request satisfies the second traffic rule", func() { It("responds with responses from `treatment-b` route", func() { want = httpexpect. - NewValue(GinkgoT(), JSONPayload("testdata/responses/traffic_rules/traffic-rule-2.json")). + NewValue(GinkgoT(), + JSONPayload("testdata/responses/traffic_rules/traffic-rule-2.json")). Object() got = config.NewHTTPExpect(GinkgoT(), routerCtx.Endpoint). diff --git a/api/e2e/test/routers_suite_test.go b/api/e2e/test/routers_suite_test.go index 408f73091..06da46b27 100644 --- a/api/e2e/test/routers_suite_test.go +++ b/api/e2e/test/routers_suite_test.go @@ -181,8 +181,8 @@ func DeployedRouterContext(payloadTpl string, protocol routerConfig.Protocol, ar }, defaultDeploymentIntervals...).Should(Succeed()) router. - ValueEqual("status", "deployed"). - Value("config").Object().ValueEqual("version", 1) + HasValue("status", "deployed"). + Value("config").Object().HasValue("version", 1) endpoint, err := url.Parse(router.Value("endpoint").String().Raw()) Expect(err).ShouldNot(HaveOccurred()) @@ -292,12 +292,12 @@ func AssertResponsePayload(want, got *httpexpect.Object) { if len(resp.Response.RouteResponses) > 0 { got. - ValueEqual("request", want.Value("request").Raw()). + HasValue("request", want.Value("request").Raw()). Value("response").Object(). - ValueEqual("experiment", want.Path("$.response.experiment").Raw()). + HasValue("experiment", want.Path("$.response.experiment").Raw()). Value("route_responses").Array(). ContainsOnly(want.Path("$.response.route_responses").Array().Raw()...) } else { - got.Equal(want.Raw()) + got.IsEqual(want.Raw()) } } diff --git a/api/go.mod b/api/go.mod index d609e0c7a..43d82f83a 100644 --- a/api/go.mod +++ b/api/go.mod @@ -8,11 +8,11 @@ require ( github.com/GoogleCloudPlatform/spark-on-k8s-operator v0.0.0-20220214044918-55732a6a392c github.com/antihax/optional v1.0.0 github.com/caraml-dev/merlin v0.0.0 - github.com/caraml-dev/mlp v1.7.7-0.20230428104022-779530aec912 + github.com/caraml-dev/mlp v1.7.7-0.20230519042541-3415407aa27b github.com/caraml-dev/turing/engines/experiment v0.0.0 github.com/caraml-dev/turing/engines/router v0.0.0 github.com/caraml-dev/universal-prediction-interface v0.3.4 - github.com/gavv/httpexpect/v2 v2.3.1 + github.com/gavv/httpexpect/v2 v2.15.0 github.com/getkin/kin-openapi v0.76.0 github.com/ghodss/yaml v1.0.0 github.com/go-playground/validator/v10 v10.11.1 @@ -60,7 +60,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/ajg/form v1.5.1 // indirect - github.com/andybalholm/brotli v1.0.3 // indirect + github.com/andybalholm/brotli v1.0.4 // indirect github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect @@ -94,10 +94,11 @@ require ( github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator v9.31.0+incompatible // indirect github.com/go-stack/stack v1.8.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-querystring v1.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect @@ -114,7 +115,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/imkira/go-interpol v1.0.0 // indirect + github.com/imkira/go-interpol v1.1.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.13.0 // indirect github.com/jackc/pgio v1.0.0 // indirect @@ -133,11 +134,12 @@ require ( github.com/lib/pq v1.10.3 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.11 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -154,6 +156,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/sanity-io/litter v1.5.5 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/afero v1.9.2 // indirect @@ -166,8 +169,8 @@ require ( github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.0+incompatible // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.30.0 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/valyala/fasthttp v1.34.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect @@ -197,7 +200,7 @@ require ( k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c // indirect k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect knative.dev/networking v0.0.0-20211101215640-8c71a2708e7d // indirect - moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e // indirect + moul.io/http2curl/v2 v2.3.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/api/go.sum b/api/go.sum index 5fdc93ae6..8102075ea 100644 --- a/api/go.sum +++ b/api/go.sum @@ -165,8 +165,9 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +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 v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -243,8 +244,8 @@ github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c/go. github.com/caraml-dev/merlin/api v0.0.0-20230403075012-795947162429 h1:utxGPa/erqKIUhgBFMgnbORjKUIqVKLs7VXa0ZB0jNY= github.com/caraml-dev/merlin/api v0.0.0-20230403075012-795947162429/go.mod h1:BRGKVbv3zEu9rE6pE2RNlj/IZfqy/3HEqBQGLK5rHMc= github.com/caraml-dev/merlin/python/batch-predictor v0.0.0-20230403075012-795947162429/go.mod h1:jYSIcxx7FDccKSva3mo12YhQ0rYuP4MOEbgSveY82HE= -github.com/caraml-dev/mlp v1.7.7-0.20230428104022-779530aec912 h1:XQwsmz0CM5O+fchhQQe3W9llL5E5IqqJrhLkJhrlPuI= -github.com/caraml-dev/mlp v1.7.7-0.20230428104022-779530aec912/go.mod h1:ahdKpb/SKFEyHE6817AOh0b2fyroTzJmXM8U+2BG75M= +github.com/caraml-dev/mlp v1.7.7-0.20230519042541-3415407aa27b h1:gnHGvCi48tbpWyvIIN9T51OjjBPN87CSjlNezq74H9s= +github.com/caraml-dev/mlp v1.7.7-0.20230519042541-3415407aa27b/go.mod h1:KwanmpEzX11cIczhSs7e55M0EvgTuiZWC+uHQYppG5U= github.com/caraml-dev/universal-prediction-interface v0.3.4 h1:cPytzpjXE/8RhSw3iS0JFZzNdM3tJ/l8UcHTPrxQWEo= github.com/caraml-dev/universal-prediction-interface v0.3.4/go.mod h1:e0qmFOXQxx8HFg5ObYyQO3WVnrqsr5v5JApFmeF7eJo= github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= @@ -519,15 +520,12 @@ github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fasthttp/websocket v1.4.3-rc.6 h1:omHqsl8j+KXpmzRjF8bmzOSYJ8GnS0E3efi1wYT+niY= -github.com/fasthttp/websocket v1.4.3-rc.6/go.mod h1:43W9OM2T8FeXpCWMsBd9Cb7nE2CACNqNvCqQCoty/Lc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= @@ -550,8 +548,8 @@ github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3n github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/gavv/httpexpect/v2 v2.3.1 h1:sGLlKMn8AuHS9ztK9Sb7AJ7OxIL8v2PcLdyxfKt1Fo4= -github.com/gavv/httpexpect/v2 v2.3.1/go.mod h1:yOE8m/aqFYQDNrgprMeXgq4YynfN9h1NgcE1+1suV64= +github.com/gavv/httpexpect/v2 v2.15.0 h1:CCnFk9of4l4ijUhnMxyoEpJsIIBKcuWIFLMwwGTZxNs= +github.com/gavv/httpexpect/v2 v2.15.0/go.mod h1:7myOP3A3VyS4+qnA4cm8DAad8zMN+7zxDB80W9f8yIc= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= github.com/getkin/kin-openapi v0.2.0/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk= @@ -704,6 +702,7 @@ github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2 github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= @@ -827,8 +826,9 @@ github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e/go.m github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20210624211700-ce35c99b3faf/go.mod h1:j3IqhBG3Ox1NXmmhbWU4UmiHVAf2dUgB7le1Ch7JZQ0= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -1010,8 +1010,8 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/imkira/go-interpol v1.0.0 h1:HrmLyvOLJyjR0YofMw8QGdCIuYOs4TJUBDNU5sJC09E= -github.com/imkira/go-interpol v1.0.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= @@ -1125,11 +1125,11 @@ github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1201,13 +1201,13 @@ github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwM github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -1216,8 +1216,10 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1257,6 +1259,8 @@ github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go. github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= @@ -1428,6 +1432,7 @@ github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pilagod/gorm-cursor-paginator v1.3.0/go.mod h1:j8Bc6Ik1CZJxn/UpwWOa9ncFncy7GWfRB+WxHM0ot8o= +github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1544,10 +1549,10 @@ github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIH github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873 h1:N3Af8f13ooDKcIhsmFT7Z05CStZWu4C7Md0uDEy4q6o= -github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873/go.mod h1:dmPawKuiAeG/aFYVs2i+Dyosoo7FNcm+Pi8iK6ZUrX8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc= @@ -1658,6 +1663,7 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= @@ -1703,9 +1709,9 @@ github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= 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.27.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= -github.com/valyala/fasthttp v1.30.0 h1:nBNzWrgZUUHohyLPU/jTvXdhrcaf2m5k3bWk+3Q049g= github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= +github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= @@ -1729,12 +1735,12 @@ github.com/xanzy/go-gitlab v0.32.0 h1:tBm+OXv1t+KBsqlXkSDFz+YUjRM0GFsjpOWYOod3Eb github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -1878,6 +1884,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= @@ -2168,6 +2175,7 @@ golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2288,6 +2296,7 @@ golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -2672,8 +2681,8 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= -moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e h1:C7q+e9M5nggAvWfVg9Nl66kebKeuJlP3FD58V4RR5wo= -moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e/go.mod h1:nejbQVfXh96n9dSF6cH3Jsk/QI1Z2oEL7sSI2ifXFNA= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= diff --git a/api/turing/api/appcontext.go b/api/turing/api/appcontext.go index 4215e3f75..42651beb1 100644 --- a/api/turing/api/appcontext.go +++ b/api/turing/api/appcontext.go @@ -56,8 +56,7 @@ func NewAppContext( cryptoService := service.NewCryptoService(cfg.TuringEncryptionKey) // Init MLP service - mlpSvc, err := service.NewMLPService(cfg.MLPConfig.MLPURL, cfg.MLPConfig.MLPEncryptionKey, - cfg.MLPConfig.MerlinURL) + mlpSvc, err := service.NewMLPService(cfg.MLPConfig.MLPURL, cfg.MLPConfig.MerlinURL) if err != nil { return nil, errors.Wrapf(err, "Failed initializing MLP Service") } diff --git a/api/turing/api/appcontext_test.go b/api/turing/api/appcontext_test.go index 56f74d581..c2e86a230 100644 --- a/api/turing/api/appcontext_test.go +++ b/api/turing/api/appcontext_test.go @@ -205,9 +205,8 @@ func TestNewAppContext(t *testing.T) { EnvironmentConfigPath: "path-to-env-file.yaml", }, MLPConfig: &config.MLPConfig{ - MerlinURL: "http://mlp.example.com/api/merlin/v1", - MLPURL: "http://mlp.example.com/api/mlp/v1", - MLPEncryptionKey: "key", + MerlinURL: "http://mlp.example.com/api/merlin/v1", + MLPURL: "http://mlp.example.com/api/mlp/v1", }, TuringEncryptionKey: "turing-key", AlertConfig: &config.AlertConfig{ @@ -251,10 +250,9 @@ func TestNewAppContext(t *testing.T) { }, ) monkey.Patch(service.NewMLPService, - func(mlpBasePath string, mlpEncryptionKey string, merlinBasePath string, + func(mlpBasePath string, merlinBasePath string, ) (service.MLPService, error) { assert.Equal(t, testCfg.MLPConfig.MLPURL, mlpBasePath) - assert.Equal(t, testCfg.MLPConfig.MLPEncryptionKey, mlpEncryptionKey) assert.Equal(t, testCfg.MLPConfig.MerlinURL, merlinBasePath) return mlpSvc, nil }, @@ -290,8 +288,7 @@ func TestNewAppContext(t *testing.T) { ) // Create expected components - mlpService, err := service.NewMLPService(testCfg.MLPConfig.MLPURL, - testCfg.MLPConfig.MLPEncryptionKey, testCfg.MLPConfig.MerlinURL) + mlpService, err := service.NewMLPService(testCfg.MLPConfig.MLPURL, testCfg.MLPConfig.MerlinURL) assert.NoError(t, err) experimentService, err := service.NewExperimentsService(testCfg.Experiment) assert.NoError(t, err) diff --git a/api/turing/config/config.go b/api/turing/config/config.go index c8aa9d10d..4f09f6f51 100644 --- a/api/turing/config/config.go +++ b/api/turing/config/config.go @@ -411,9 +411,8 @@ type GitlabConfig struct { // MLPConfig captures the configuration used to connect to the Merlin/MLP API servers type MLPConfig struct { - MerlinURL string `validate:"required"` - MLPURL string `validate:"required"` - MLPEncryptionKey string `validate:"required"` + MerlinURL string `validate:"required"` + MLPURL string `validate:"required"` } // OpenapiConfig contains the settings for the OpenAPI specs used for validation and Swagger UI diff --git a/api/turing/config/config_test.go b/api/turing/config/config_test.go index 1c5a8a46a..01cd5781d 100644 --- a/api/turing/config/config_test.go +++ b/api/turing/config/config_test.go @@ -876,9 +876,8 @@ func TestConfigValidate(t *testing.T) { TuringEncryptionKey: "secret", AlertConfig: nil, MLPConfig: &config.MLPConfig{ - MerlinURL: "http://merlin.example.com", - MLPURL: "http://mlp.example.com", - MLPEncryptionKey: "secret", + MerlinURL: "http://merlin.example.com", + MLPURL: "http://mlp.example.com", }, } diff --git a/api/turing/service/mlp_service.go b/api/turing/service/mlp_service.go index 3b8a47a08..25f37e140 100644 --- a/api/turing/service/mlp_service.go +++ b/api/turing/service/mlp_service.go @@ -57,18 +57,16 @@ func newMerlinClient(googleClient *http.Client, basePath string) *merlinClient { } type mlpClient struct { - CryptoService api *mlp.APIClient } -func newMLPClient(googleClient *http.Client, basePath string, encryptionKey string) *mlpClient { +func newMLPClient(googleClient *http.Client, basePath string) *mlpClient { cfg := mlp.NewConfiguration() cfg.BasePath = basePath cfg.HTTPClient = googleClient return &mlpClient{ - CryptoService: NewCryptoService(encryptionKey), - api: mlp.NewAPIClient(cfg), + api: mlp.NewAPIClient(cfg), } } @@ -76,7 +74,6 @@ func newMLPClient(googleClient *http.Client, basePath string, encryptionKey stri // from (currently) the Merlin API. func NewMLPService( mlpBasePath string, - mlpEncryptionKey string, merlinBasePath string, ) (MLPService, error) { // Create an HTTP client with Google default credential. @@ -93,7 +90,7 @@ func NewMLPService( svc := &mlpService{ merlinClient: newMerlinClient(httpClient, merlinBasePath), - mlpClient: newMLPClient(httpClient, mlpBasePath, mlpEncryptionKey), + mlpClient: newMLPClient(httpClient, mlpBasePath), cache: cache.New(mlpCacheExpirySeconds*time.Second, mlpCacheCleanUpSeconds*time.Second), } @@ -142,13 +139,13 @@ func (service mlpService) GetProjects(name string) ([]mlp.Project, error) { ctx, cancel := context.WithTimeout(context.Background(), mlpQueryTimeoutSeconds*time.Second) defer cancel() - var options *mlp.ProjectApiProjectsGetOpts + var options *mlp.ProjectApiV1ProjectsGetOpts if len(name) > 0 { - options = &mlp.ProjectApiProjectsGetOpts{ + options = &mlp.ProjectApiV1ProjectsGetOpts{ Name: optional.NewString(name), } } - projects, resp, err := service.mlpClient.api.ProjectApi.ProjectsGet(ctx, options) + projects, resp, err := service.mlpClient.api.ProjectApi.V1ProjectsGet(ctx, options) if err != nil { return nil, err } @@ -193,7 +190,7 @@ func (service mlpService) GetSecret(projectID models.ID, name string) (string, e ctx, cancel := context.WithTimeout(context.Background(), mlpQueryTimeoutSeconds*time.Second) defer cancel() - secrets, resp, err := service.mlpClient.api.SecretApi.ProjectsProjectIdSecretsGet(ctx, int32(projectID)) + secrets, resp, err := service.mlpClient.api.SecretApi.V1ProjectsProjectIdSecretsGet(ctx, int32(projectID)) if err != nil { return "", err } @@ -202,7 +199,7 @@ func (service mlpService) GetSecret(projectID models.ID, name string) (string, e } for _, secret := range secrets { if secret.Name == name { - return service.mlpClient.Decrypt(secret.Data) + return secret.Data, nil } } return "", fmt.Errorf("secret %s not found in project %d", name, projectID) @@ -212,7 +209,7 @@ func (service mlpService) refreshProjects() error { ctx, cancel := context.WithTimeout(context.Background(), mlpQueryTimeoutSeconds*time.Second) defer cancel() - projects, resp, err := service.mlpClient.api.ProjectApi.ProjectsGet(ctx, nil) + projects, resp, err := service.mlpClient.api.ProjectApi.V1ProjectsGet(ctx, nil) if err != nil { return err } diff --git a/api/turing/service/mlp_service_test.go b/api/turing/service/mlp_service_test.go index 6e9fdbf88..77f58f744 100644 --- a/api/turing/service/mlp_service_test.go +++ b/api/turing/service/mlp_service_test.go @@ -20,16 +20,6 @@ import ( mlp "github.com/caraml-dev/mlp/api/client" ) -type mockCryptoService struct{} - -func (*mockCryptoService) Encrypt(text string) (string, error) { - return text, nil -} - -func (*mockCryptoService) Decrypt(text string) (string, error) { - return text, nil -} - // testSetupEnvForGoogleCredentials creates a temporary file containing dummy user account JSON // then set the environment variable GOOGLE_APPLICATION_CREDENTIALS to point to the file. // @@ -109,20 +99,18 @@ func TestNewMLPService(t *testing.T) { }, ) monkey.Patch(newMLPClient, - func(googleClient *http.Client, basePath string, encryptionKey string) *mlpClient { + func(googleClient *http.Client, basePath string) *mlpClient { assert.Equal(t, gc, googleClient) assert.Equal(t, "mlp-base-path", basePath) - assert.Equal(t, "mlp-enc-key", encryptionKey) // Create test client mlpClient := &mlpClient{ - CryptoService: &mockCryptoService{}, api: &mlp.APIClient{ ProjectApi: &mlp.ProjectApiService{}, }, } // Patch Get Projects - monkey.PatchInstanceMethod(reflect.TypeOf(mlpClient.api.ProjectApi), "ProjectsGet", - func(svc *mlp.ProjectApiService, ctx context.Context, localVarOptionals *mlp.ProjectApiProjectsGetOpts, + monkey.PatchInstanceMethod(reflect.TypeOf(mlpClient.api.ProjectApi), "V1ProjectsGet", + func(svc *mlp.ProjectApiService, ctx context.Context, localVarOptionals *mlp.ProjectApiV1ProjectsGetOpts, ) ([]mlp.Project, *http.Response, error) { return projects, nil, nil }) @@ -130,7 +118,7 @@ func TestNewMLPService(t *testing.T) { }, ) - svc, err := NewMLPService("mlp-base-path", "mlp-enc-key", "merlin-base-path") + svc, err := NewMLPService("mlp-base-path", "merlin-base-path") assert.NoError(t, err) assert.NotNil(t, svc) @@ -183,9 +171,8 @@ func TestNewMLPClient(t *testing.T) { cfg.HTTPClient = gc // Test - resultClient := newMLPClient(gc, "base-path", "enc-key") + resultClient := newMLPClient(gc, "base-path") require.NotNil(t, resultClient) - assert.Equal(t, NewCryptoService("enc-key"), resultClient.CryptoService) assert.Equal(t, mlp.NewAPIClient(cfg), resultClient.api) } @@ -198,8 +185,8 @@ func TestMLPServiceGetProject(t *testing.T) { } svc := newTestMLPService() - monkey.PatchInstanceMethod(reflect.TypeOf(svc.mlpClient.api.ProjectApi), "ProjectsGet", - func(svc *mlp.ProjectApiService, ctx context.Context, localVarOptionals *mlp.ProjectApiProjectsGetOpts, + monkey.PatchInstanceMethod(reflect.TypeOf(svc.mlpClient.api.ProjectApi), "V1ProjectsGet", + func(svc *mlp.ProjectApiService, ctx context.Context, localVarOptionals *mlp.ProjectApiV1ProjectsGetOpts, ) ([]mlp.Project, *http.Response, error) { return projects, nil, nil }) @@ -255,7 +242,7 @@ func TestMLPServiceGetSecret(t *testing.T) { svc := newTestMLPService() monkey.PatchInstanceMethod( reflect.TypeOf(svc.mlpClient.api.SecretApi), - "ProjectsProjectIdSecretsGet", + "V1ProjectsProjectIdSecretsGet", func(svc *mlp.SecretApiService, ctx context.Context, projectId int32, @@ -288,7 +275,6 @@ func newTestMLPService() *mlpService { }, }, mlpClient: &mlpClient{ - CryptoService: &mockCryptoService{}, api: &mlp.APIClient{ ProjectApi: &mlp.ProjectApiService{}, }, diff --git a/infra/charts/turing/README.md b/infra/charts/turing/README.md index f37cdc792..5edef0f91 100644 --- a/infra/charts/turing/README.md +++ b/infra/charts/turing/README.md @@ -93,17 +93,17 @@ The following table lists the configurable parameters of the Turing chart and th | turing.environmentConfigs | list | `[{"k8s_config":{"cluster":{},"name":"dev-cluster","user":{}},"name":"dev"}]` | Set this field to configure environment configs. See api/environments-dev.yaml for sample structure | | turing.experimentEngines | list | `[]` | Turing Experiment Engines configuration | | turing.extraArgs | list | `[]` | List of string containing additional Turing API server arguments. For example, multiple "-config" can be specified to use multiple config files | -| turing.extraContainers | list | `[]` | List of sidecar containers to attach to the Pod. For example, you can attach sidecar container that forward logs or dynamically update some configuration files. | +| turing.extraContainers | list | `[]` | List of sidecar containers to attach to the Pod. For example, you can attach sidecar container that forward logs or dynamically update some configuration files. | | turing.extraEnvs | list | `[]` | List of extra environment variables to add to Turing API server container | | turing.extraInitContainers | list | `[]` | List of extra initContainers to add to the Pod. For example, you need to run some init scripts to fetch credentials from a remote server | | turing.extraVolumeMounts | list | `[]` | Extra volume mounts to attach to Turing API server container. For example to mount the extra volume containing secrets | -| turing.extraVolumes | list | `[]` | Extra volumes to attach to the Pod. For example, you can mount additional secrets to these volumes | +| turing.extraVolumes | list | `[]` | Extra volumes to attach to the Pod. For example, you can mount additional secrets to these volumes | | turing.image.registry | string | `"ghcr.io"` | Docker registry for Turing API image. User is required to override the registry for now as there is no publicly available Turing image | | turing.image.repository | string | `"caraml-dev/turing"` | Docker image repository for Turing API | | turing.image.tag | string | `"v1.7.1"` | Docker image tag for Turing API | -| turing.ingress.class | string | `""` | Ingress class annotation to add to this Ingress rule, useful when there are multiple ingress controllers installed | +| turing.ingress.class | string | `""` | Ingress class annotation to add to this Ingress rule, useful when there are multiple ingress controllers installed | | turing.ingress.enabled | bool | `false` | Enable ingress to provision Ingress resource for external access to Turing API | -| turing.ingress.host | string | `""` | Set host value to enable name based virtual hosting. This allows routing HTTP traffic to multiple host names at the same IP address. If no host is specified, the ingress rule applies to all inbound HTTP traffic through the IP address specified. https://kubernetes.io/docs/concepts/services-networking/ingress/#name-based-virtual-hosting | +| turing.ingress.host | string | `""` | Set host value to enable name based virtual hosting. This allows routing HTTP traffic to multiple host names at the same IP address. If no host is specified, the ingress rule applies to all inbound HTTP traffic through the IP address specified. https://kubernetes.io/docs/concepts/services-networking/ingress/#name-based-virtual-hosting | | turing.ingress.useV1Beta1 | bool | `false` | Whether to use networking.k8s.io/v1 (k8s version >= 1.19) or networking.k8s.io/v1beta1 (1.16 >= k8s version >= 1.22) | | turing.labels | object | `{}` | | | turing.livenessProbe.path | string | `"/v1/internal/live"` | HTTP path for liveness check | diff --git a/infra/charts/turing/templates/_helpers.tpl b/infra/charts/turing/templates/_helpers.tpl index 3de203886..56144caa1 100644 --- a/infra/charts/turing/templates/_helpers.tpl +++ b/infra/charts/turing/templates/_helpers.tpl @@ -186,7 +186,7 @@ MLPConfig: MLPEncryptionKey: {{ include "turing.mlp.encryption.key" . | quote }} {{ if .Values.tags.mlp }} MerlinURL: {{ printf "http://%s:8080/v1" (include "turing.merlin.name" .) }} - MLPURL: {{ printf "http://%s:8080/v1" (include "turing.mlp.name" .) }} + MLPURL: {{ printf "http://%s:8080" (include "turing.mlp.name" .) }} {{ end }} TuringEncryptionKey: {{ include "turing.encryption.key" . | quote }} Sentry: