feat: support yaml in blob, file, and http syncs (#1522)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
This commit is contained in:
parent
7a0656713a
commit
76d673ae8f
133
core/go.sum
133
core/go.sum
|
|
@ -1,25 +1,5 @@
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20240906125204-0a6a901b42e8.1 h1:18ZObecoJfRbNQDeuW0PoBR829Mw8FrPrmWIbbaA5hs=
|
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20240906125204-0a6a901b42e8.1/go.mod h1:WA65xyBj+VxPfJ3a+EqdZtWGeNdwqiaQO1sriHaNL1Y=
|
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20241220192239-696330adaff0.1 h1:IUAEwQk7D6DNKKJD3QawHOsIyxVzvJEvSwaf4IrOCWo=
|
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20241220192239-696330adaff0.1/go.mod h1:tuqaSMGk0JdcgfeGezlkUyPs5EcRvefx3pY12jl0CWc=
|
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20241220192239-696330adaff0.2 h1:DTzLajNo/KOdqIyYQEf1ycToux8PzatOqeLgppUJYO0=
|
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20241220192239-696330adaff0.2/go.mod h1:CgtzL3a/OZI2tPbGH0TWbMEyPFGPeE3NT9AXvrGZ9Ic=
|
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2 h1:D3HI5RQbqgffyf+Z77+hReDx5kigFVAKGvttULD9/ms=
|
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2 h1:D3HI5RQbqgffyf+Z77+hReDx5kigFVAKGvttULD9/ms=
|
||||||
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2/go.mod h1:b9rfG6rbGXZAlLwQwedvZ0kI0nUcR+aLaYF70pj920E=
|
buf.build/gen/go/open-feature/flagd/grpc/go v1.5.1-20250127221518-be6d1143b690.2/go.mod h1:b9rfG6rbGXZAlLwQwedvZ0kI0nUcR+aLaYF70pj920E=
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.35.2-20240906125204-0a6a901b42e8.1 h1:YH4cN90+V8Ma0oesiknkwAfpaXv1os0wf6hHxZbsYXI=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.35.2-20240906125204-0a6a901b42e8.1/go.mod h1:Xr7OXtIywezTZbrenv3UbcK0eSikuoXJ/Au9MlmMADs=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.0-20240906125204-0a6a901b42e8.1 h1:sLBOg6If+/9NAB/PpHdRWruKdhJINz4Hc6gn5mA3yDQ=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.0-20240906125204-0a6a901b42e8.1/go.mod h1:8XwTwJgC9sKuuFvYbpqZzHNjXsSgv9omI1j6+XC3534=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.0-20241220192239-696330adaff0.1 h1:0zxUV0cXmmlD1QVDfpAB48Gz0dPP6NUdrdQAofUVRQ0=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.0-20241220192239-696330adaff0.1/go.mod h1:8XwTwJgC9sKuuFvYbpqZzHNjXsSgv9omI1j6+XC3534=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.1-20241220192239-696330adaff0.1 h1:CYsQrPu6h2qVEKuc7gu3X4wv2ohFr/OWD29J2thKX6o=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.1-20241220192239-696330adaff0.1/go.mod h1:5XEoBVvGcahkyF86hwFtNBAEwhu8Gi7jhg8kSEAEI4Q=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.2-20241220192239-696330adaff0.1 h1:ksMEWnFsZYnIiKG6FWVknPGvgkqnFCXu8J2RyxyJr2c=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.2-20241220192239-696330adaff0.1/go.mod h1:goa0LsW/Zl0hcpskkrxrk02pdPAvlzNllrriC3GjBSk=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.3-20241220192239-696330adaff0.1 h1:k0Ing4Z+RWUwdMsQkrJP4BtzmiFwKMflkyjKY13Qp8Y=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.3-20241220192239-696330adaff0.1/go.mod h1:i4r8Y6TOuQGjptheWsep7c1PZodfGPohMDQLGoxImfs=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.4-20241220192239-696330adaff0.1 h1:GzWS8kvK11LM7OnrTSofL5RJlOOeSC8DrZ58ExnG1TA=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.4-20241220192239-696330adaff0.1/go.mod h1:wemFLfCpuNfhrBQ7NwzbtYxbg+IihAYqJcNeS+fLpLI=
|
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.4-20250127221518-be6d1143b690.1 h1:0vXmOkGv8nO5H1W8TkSz+GtZhvD2LNXiQaiucEio6vk=
|
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.4-20250127221518-be6d1143b690.1 h1:0vXmOkGv8nO5H1W8TkSz+GtZhvD2LNXiQaiucEio6vk=
|
||||||
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.4-20250127221518-be6d1143b690.1/go.mod h1:wemFLfCpuNfhrBQ7NwzbtYxbg+IihAYqJcNeS+fLpLI=
|
buf.build/gen/go/open-feature/flagd/protocolbuffers/go v1.36.4-20250127221518-be6d1143b690.1/go.mod h1:wemFLfCpuNfhrBQ7NwzbtYxbg+IihAYqJcNeS+fLpLI=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
|
@ -29,8 +9,6 @@ cloud.google.com/go/auth v0.8.1 h1:QZW9FjC5lZzN864p13YxvAtGUlQ+KgRL+8Sg45Z6vxo=
|
||||||
cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc=
|
cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
|
cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
|
||||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
|
||||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
|
||||||
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
|
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
|
||||||
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
|
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
|
||||||
cloud.google.com/go/iam v1.1.13 h1:7zWBXG9ERbMLrzQBRhFliAV+kjcRToDTgQT3CTwYyv4=
|
cloud.google.com/go/iam v1.1.13 h1:7zWBXG9ERbMLrzQBRhFliAV+kjcRToDTgQT3CTwYyv4=
|
||||||
|
|
@ -39,8 +17,6 @@ cloud.google.com/go/longrunning v0.5.12 h1:5LqSIdERr71CqfUsFlJdBpOkBH8FBCFD7P1nT
|
||||||
cloud.google.com/go/longrunning v0.5.12/go.mod h1:S5hMV8CDJ6r50t2ubVJSKQVv5u0rmik5//KgLO3k4lU=
|
cloud.google.com/go/longrunning v0.5.12/go.mod h1:S5hMV8CDJ6r50t2ubVJSKQVv5u0rmik5//KgLO3k4lU=
|
||||||
cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs=
|
cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs=
|
||||||
cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0=
|
cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0=
|
||||||
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
|
|
||||||
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
|
||||||
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
|
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
|
||||||
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
||||||
connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY=
|
connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY=
|
||||||
|
|
@ -117,14 +93,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.6.0 h1:pSVxMTeNOVwsQsJgUV8ENNvtZSev528FbE0fV0+XsWo=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.6.0/go.mod h1:3nnfWovrlZq2rTpucrJ2KMIS8TMf6IoFneofmeqk/qk=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.6.1 h1:EBHcGqqP7cJi1ygvNs7+APzyNBWzcVhHVwogCxQqj+w=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.6.1/go.mod h1:3nnfWovrlZq2rTpucrJ2KMIS8TMf6IoFneofmeqk/qk=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.0 h1:fDGVmOyIS8H4WJhtv0YUOoeoUXo7sZLu+VXVr70BR1U=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.0/go.mod h1:OYRb6FSTVmMM+MNQ7ElmMsczyNSepw+OU4Z8emDSi4w=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.1 h1:N9nEU+sFL793cZc11fsZ/Rlicvlg7hcOFOI6CVjvIhk=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.1/go.mod h1:OYRb6FSTVmMM+MNQ7ElmMsczyNSepw+OU4Z8emDSi4w=
|
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.3 h1:orvGaTW5Qdcowpr7vgfMNuqYNjQYcqtw9W1Bk4QyI38=
|
github.com/diegoholiveira/jsonlogic/v3 v3.7.3 h1:orvGaTW5Qdcowpr7vgfMNuqYNjQYcqtw9W1Bk4QyI38=
|
||||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.3/go.mod h1:OYRb6FSTVmMM+MNQ7ElmMsczyNSepw+OU4Z8emDSi4w=
|
github.com/diegoholiveira/jsonlogic/v3 v3.7.3/go.mod h1:OYRb6FSTVmMM+MNQ7ElmMsczyNSepw+OU4Z8emDSi4w=
|
||||||
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
|
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
|
||||||
|
|
@ -212,10 +180,6 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||||
github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
|
github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
|
||||||
github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
|
github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
|
||||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||||
|
|
@ -253,12 +217,6 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20240708163558-2aa89b314322 h1:5zbNHqcZAc9jlhSrC0onuVL2RPpvYcDaNvW2wOZBfUY=
|
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20240708163558-2aa89b314322/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
|
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20241220191753-b81a56eea3b2 h1:96TDmaXEkKcR5mC3L3s+XcYeD/1bk1J3S1su5sTGFDU=
|
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20241220191753-b81a56eea3b2/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
|
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20250106184836-37baa2cdea48 h1:qtUAqQxMT252ZE2T/ESExiSOgx+enrOnhPBUMIerKNs=
|
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20250106184836-37baa2cdea48/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
|
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20250127221449-bb763438abc5 h1:0RKCLYeQpvSsKR95kc894tm8GAZmq7bcG48v0KJ0HCs=
|
github.com/open-feature/flagd-schemas v0.2.9-0.20250127221449-bb763438abc5 h1:0RKCLYeQpvSsKR95kc894tm8GAZmq7bcG48v0KJ0HCs=
|
||||||
github.com/open-feature/flagd-schemas v0.2.9-0.20250127221449-bb763438abc5/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
|
github.com/open-feature/flagd-schemas v0.2.9-0.20250127221449-bb763438abc5/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
|
||||||
github.com/open-feature/open-feature-operator/apis v0.2.44 h1:0r4Z+RnJltuHdRBv79NFgAckhna6/M3Wcec6gzNX5vI=
|
github.com/open-feature/open-feature-operator/apis v0.2.44 h1:0r4Z+RnJltuHdRBv79NFgAckhna6/M3Wcec6gzNX5vI=
|
||||||
|
|
@ -275,8 +233,6 @@ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/j
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
|
||||||
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
|
||||||
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
|
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
|
||||||
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
|
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
|
|
@ -291,7 +247,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
|
@ -323,64 +278,24 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
||||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
|
||||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
|
||||||
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
|
|
||||||
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
|
|
||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0 h1:7F29RDmnlqk6B5d+sUqemt8TBfDqxryYW5gX6L74RFA=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0/go.mod h1:ZiGDq7xwDMKmWDrN1XsXAj0iC7hns+2DhxBFSncNHSE=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk=
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA=
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU=
|
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU=
|
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.55.0 h1:sSPw658Lk2NWAv74lkD3B/RSDb+xRFx46GjkrL3VUZo=
|
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.55.0/go.mod h1:nC00vyCmQixoeaxF6KNyP42II/RHa9UdruK02qBmHvI=
|
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E=
|
go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E=
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk=
|
go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk=
|
||||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
|
||||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
|
||||||
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
|
|
||||||
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
|
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.33.0 h1:Gs5VK9/WUJhNXZgn8MR6ITatvAmKeIuCtNbsP3JkNqU=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.33.0/go.mod h1:dL5ykHZmm1B1nVRk9dDjChwDmt81MjVp3gLkQRwKf/Q=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
|
||||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
|
||||||
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
|
|
||||||
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
|
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
|
@ -399,17 +314,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
|
|
||||||
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
|
||||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
|
||||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
|
||||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
|
|
||||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||||
golang.org/x/exp v0.0.0-20250128144449-3edf0e91c1ae h1:COZdc9Ut6wLq7MO9GIYxfZl4n4ScmgqQLoHocKXrxco=
|
golang.org/x/exp v0.0.0-20250128144449-3edf0e91c1ae h1:COZdc9Ut6wLq7MO9GIYxfZl4n4ScmgqQLoHocKXrxco=
|
||||||
|
|
@ -440,15 +347,9 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
|
||||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
|
||||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
|
||||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
|
||||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
|
||||||
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
|
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
|
||||||
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
@ -475,8 +376,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|
@ -485,8 +384,6 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
|
||||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
|
||||||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
@ -512,8 +409,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
@ -531,16 +428,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 h1:CT2Thj5AuPV9phrYMtzX11k+XkzMGfRAet42PmoTATM=
|
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 h1:CT2Thj5AuPV9phrYMtzX11k+XkzMGfRAet42PmoTATM=
|
||||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988/go.mod h1:7uvplUBj4RjHAxIZ//98LzOvrQ04JBkaixRmCMI29hc=
|
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988/go.mod h1:7uvplUBj4RjHAxIZ//98LzOvrQ04JBkaixRmCMI29hc=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
|
@ -548,14 +437,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
|
|
||||||
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
|
|
||||||
google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI=
|
|
||||||
google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
|
||||||
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
|
|
||||||
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
|
||||||
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
|
|
||||||
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
|
||||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
|
@ -567,16 +448,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
|
||||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
|
|
||||||
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
|
||||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
|
||||||
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
|
|
||||||
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
package blob
|
package blob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/open-feature/flagd/core/pkg/logger"
|
"github.com/open-feature/flagd/core/pkg/logger"
|
||||||
"github.com/open-feature/flagd/core/pkg/sync"
|
"github.com/open-feature/flagd/core/pkg/sync"
|
||||||
|
"github.com/open-feature/flagd/core/pkg/utils"
|
||||||
"gocloud.dev/blob"
|
"gocloud.dev/blob"
|
||||||
_ "gocloud.dev/blob/azureblob" // needed to initialize Azure Blob Storage driver
|
_ "gocloud.dev/blob/azureblob" // needed to initialize Azure Blob Storage driver
|
||||||
_ "gocloud.dev/blob/gcsblob" // needed to initialize GCS driver
|
_ "gocloud.dev/blob/gcsblob" // needed to initialize GCS driver
|
||||||
|
|
@ -126,11 +128,20 @@ func (hs *Sync) fetchObjectModificationTime(ctx context.Context, bucket *blob.Bu
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hs *Sync) fetchObject(ctx context.Context, bucket *blob.Bucket) (string, error) {
|
func (hs *Sync) fetchObject(ctx context.Context, bucket *blob.Bucket) (string, error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
r, err := bucket.NewReader(ctx, hs.Object, nil)
|
||||||
err := bucket.Download(ctx, hs.Object, buf, nil)
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error opening reader for object %s/%s: %w", hs.Bucket, hs.Object, err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
data, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error downloading object %s/%s: %w", hs.Bucket, hs.Object, err)
|
return "", fmt.Errorf("error downloading object %s/%s: %w", hs.Bucket, hs.Object, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.String(), nil
|
json, err := utils.ConvertToJSON(data, filepath.Ext(hs.Object), r.ContentType())
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error converting blob data to json: %w", err)
|
||||||
|
}
|
||||||
|
return json, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,32 @@ import (
|
||||||
"go.uber.org/mock/gomock"
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
func TestBlobSync(t *testing.T) {
|
||||||
scheme = "xyz"
|
tests := map[string]struct {
|
||||||
bucket = "b"
|
scheme string
|
||||||
object = "o"
|
bucket string
|
||||||
)
|
object string
|
||||||
|
content string
|
||||||
|
convertedContent string
|
||||||
|
}{
|
||||||
|
"json file type": {
|
||||||
|
scheme: "xyz",
|
||||||
|
bucket: "b",
|
||||||
|
object: "flags.json",
|
||||||
|
content: "{\"flags\":{}}",
|
||||||
|
convertedContent: "{\"flags\":{}}",
|
||||||
|
},
|
||||||
|
"yaml file type": {
|
||||||
|
scheme: "xyz",
|
||||||
|
bucket: "b",
|
||||||
|
object: "flags.yaml",
|
||||||
|
content: "flags: []",
|
||||||
|
convertedContent: "{\"flags\":[]}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func TestSync(t *testing.T) {
|
for name, tt := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
mockCron := synctesting.NewMockCron(ctrl)
|
mockCron := synctesting.NewMockCron(ctrl)
|
||||||
mockCron.EXPECT().AddFunc(gomock.Any(), gomock.Any()).DoAndReturn(func(spec string, cmd func()) error {
|
mockCron.EXPECT().AddFunc(gomock.Any(), gomock.Any()).DoAndReturn(func(spec string, cmd func()) error {
|
||||||
|
|
@ -27,12 +46,12 @@ func TestSync(t *testing.T) {
|
||||||
mockCron.EXPECT().Start().Times(1)
|
mockCron.EXPECT().Start().Times(1)
|
||||||
|
|
||||||
blobSync := &Sync{
|
blobSync := &Sync{
|
||||||
Bucket: scheme + "://" + bucket,
|
Bucket: tt.scheme + "://" + tt.bucket,
|
||||||
Object: object,
|
Object: tt.object,
|
||||||
Cron: mockCron,
|
Cron: mockCron,
|
||||||
Logger: logger.NewLogger(nil, false),
|
Logger: logger.NewLogger(nil, false),
|
||||||
}
|
}
|
||||||
blobMock := NewMockBlob(scheme, func() *Sync {
|
blobMock := NewMockBlob(tt.scheme, func() *Sync {
|
||||||
return blobSync
|
return blobSync
|
||||||
})
|
})
|
||||||
blobSync.BlobURLMux = blobMock.URLMux()
|
blobSync.BlobURLMux = blobMock.URLMux()
|
||||||
|
|
@ -40,8 +59,7 @@ func TestSync(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
dataSyncChan := make(chan sync.DataSync, 1)
|
dataSyncChan := make(chan sync.DataSync, 1)
|
||||||
|
|
||||||
config := "my-config"
|
blobMock.AddObject(tt.object, tt.content)
|
||||||
blobMock.AddObject(object, config)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := blobSync.Sync(ctx, dataSyncChan)
|
err := blobSync.Sync(ctx, dataSyncChan)
|
||||||
|
|
@ -52,17 +70,19 @@ func TestSync(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
data := <-dataSyncChan // initial sync
|
data := <-dataSyncChan // initial sync
|
||||||
if data.FlagData != config {
|
if data.FlagData != tt.convertedContent {
|
||||||
t.Errorf("expected content: %s, but received content: %s", config, data.FlagData)
|
t.Errorf("expected content: %s, but received content: %s", tt.convertedContent, data.FlagData)
|
||||||
}
|
}
|
||||||
tickWithConfigChange(t, mockCron, dataSyncChan, blobMock, "new config")
|
tickWithConfigChange(t, mockCron, dataSyncChan, blobMock, tt.object, tt.convertedContent)
|
||||||
tickWithoutConfigChange(t, mockCron, dataSyncChan)
|
tickWithoutConfigChange(t, mockCron, dataSyncChan)
|
||||||
tickWithConfigChange(t, mockCron, dataSyncChan, blobMock, "new config 2")
|
tickWithConfigChange(t, mockCron, dataSyncChan, blobMock, tt.object, tt.convertedContent)
|
||||||
tickWithoutConfigChange(t, mockCron, dataSyncChan)
|
tickWithoutConfigChange(t, mockCron, dataSyncChan)
|
||||||
tickWithoutConfigChange(t, mockCron, dataSyncChan)
|
tickWithoutConfigChange(t, mockCron, dataSyncChan)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tickWithConfigChange(t *testing.T, mockCron *synctesting.MockCron, dataSyncChan chan sync.DataSync, blobMock *MockBlob, newConfig string) {
|
func tickWithConfigChange(t *testing.T, mockCron *synctesting.MockCron, dataSyncChan chan sync.DataSync, blobMock *MockBlob, object string, newConfig string) {
|
||||||
time.Sleep(1 * time.Millisecond) // sleep so the new file has different modification date
|
time.Sleep(1 * time.Millisecond) // sleep so the new file has different modification date
|
||||||
blobMock.AddObject(object, newConfig)
|
blobMock.AddObject(object, newConfig)
|
||||||
mockCron.Tick()
|
mockCron.Tick()
|
||||||
|
|
@ -73,7 +93,7 @@ func tickWithConfigChange(t *testing.T, mockCron *synctesting.MockCron, dataSync
|
||||||
t.Errorf("expected content: %s, but received content: %s", newConfig, data.FlagData)
|
t.Errorf("expected content: %s, but received content: %s", newConfig, data.FlagData)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("data channel unexpecdly closed")
|
t.Errorf("data channel unexpectedly closed")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
t.Errorf("data channel has no expected update")
|
t.Errorf("data channel has no expected update")
|
||||||
|
|
@ -87,13 +107,18 @@ func tickWithoutConfigChange(t *testing.T, mockCron *synctesting.MockCron, dataS
|
||||||
if ok {
|
if ok {
|
||||||
t.Errorf("unexpected update: %s", data.FlagData)
|
t.Errorf("unexpected update: %s", data.FlagData)
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("data channel unexpecdly closed")
|
t.Errorf("data channel unexpectedly closed")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReSync(t *testing.T) {
|
func TestReSync(t *testing.T) {
|
||||||
|
const (
|
||||||
|
scheme = "xyz"
|
||||||
|
bucket = "b"
|
||||||
|
object = "flags.json"
|
||||||
|
)
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
mockCron := synctesting.NewMockCron(ctrl)
|
mockCron := synctesting.NewMockCron(ctrl)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,17 @@ package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"path/filepath"
|
||||||
msync "sync"
|
msync "sync"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/open-feature/flagd/core/pkg/logger"
|
"github.com/open-feature/flagd/core/pkg/logger"
|
||||||
"github.com/open-feature/flagd/core/pkg/sync"
|
"github.com/open-feature/flagd/core/pkg/sync"
|
||||||
"gopkg.in/yaml.v3"
|
"github.com/open-feature/flagd/core/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -32,8 +32,6 @@ type Watcher interface {
|
||||||
type Sync struct {
|
type Sync struct {
|
||||||
URI string
|
URI string
|
||||||
Logger *logger.Logger
|
Logger *logger.Logger
|
||||||
// FileType indicates the file type e.g., json, yaml/yml etc.,
|
|
||||||
fileType string
|
|
||||||
// watchType indicates how to watch the file FSNOTIFY|FILEINFO
|
// watchType indicates how to watch the file FSNOTIFY|FILEINFO
|
||||||
watchType string
|
watchType string
|
||||||
watcher Watcher
|
watcher Watcher
|
||||||
|
|
@ -176,42 +174,22 @@ func (fs *Sync) fetch(_ context.Context) (string, error) {
|
||||||
if fs.URI == "" {
|
if fs.URI == "" {
|
||||||
return "", errors.New("no filepath string set")
|
return "", errors.New("no filepath string set")
|
||||||
}
|
}
|
||||||
if fs.fileType == "" {
|
|
||||||
uriSplit := strings.Split(fs.URI, ".")
|
file, err := os.Open(fs.URI)
|
||||||
fs.fileType = uriSplit[len(uriSplit)-1]
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error opening file %s: %w", fs.URI, err)
|
||||||
}
|
}
|
||||||
rawFile, err := os.ReadFile(fs.URI)
|
defer file.Close()
|
||||||
|
|
||||||
|
data, err := io.ReadAll(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error reading file %s: %w", fs.URI, err)
|
return "", fmt.Errorf("error reading file %s: %w", fs.URI, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch fs.fileType {
|
// File extension is used to determine the content type, so media type is unnecessary
|
||||||
case "yaml", "yml":
|
json, err := utils.ConvertToJSON(data, filepath.Ext(fs.URI), "")
|
||||||
return yamlToJSON(rawFile)
|
|
||||||
case "json":
|
|
||||||
return string(rawFile), nil
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("filepath extension for URI: '%s' is not supported", fs.URI)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// yamlToJSON is a generic helper function to convert
|
|
||||||
// yaml to json
|
|
||||||
func yamlToJSON(rawFile []byte) (string, error) {
|
|
||||||
if len(rawFile) == 0 {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var ms map[string]interface{}
|
|
||||||
// yaml.Unmarshal unmarshals to map[interface]interface{}
|
|
||||||
if err := yaml.Unmarshal(rawFile, &ms); err != nil {
|
|
||||||
return "", fmt.Errorf("unmarshal yaml: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := json.Marshal(ms)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("convert yaml to json: %w", err)
|
return "", fmt.Errorf("error converting file content to json: %w", err)
|
||||||
}
|
}
|
||||||
|
return json, nil
|
||||||
return string(r), err
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ func TestSimpleSync(t *testing.T) {
|
||||||
|
|
||||||
func TestFilePathSync_Fetch(t *testing.T) {
|
func TestFilePathSync_Fetch(t *testing.T) {
|
||||||
successDirName := t.TempDir()
|
successDirName := t.TempDir()
|
||||||
falureDirName := t.TempDir()
|
failureDirName := t.TempDir()
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
fpSync Sync
|
fpSync Sync
|
||||||
handleResponse func(t *testing.T, fetched string, err error)
|
handleResponse func(t *testing.T, fetched string, err error)
|
||||||
|
|
@ -213,9 +213,9 @@ func TestFilePathSync_Fetch(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"not found": {
|
"not found": {
|
||||||
fetchDirName: falureDirName,
|
fetchDirName: failureDirName,
|
||||||
fpSync: Sync{
|
fpSync: Sync{
|
||||||
URI: fmt.Sprintf("%s/%s", falureDirName, "not_found"),
|
URI: fmt.Sprintf("%s/%s", failureDirName, "not_found"),
|
||||||
Logger: logger.NewLogger(nil, false),
|
Logger: logger.NewLogger(nil, false),
|
||||||
},
|
},
|
||||||
handleResponse: func(t *testing.T, fetched string, err error) {
|
handleResponse: func(t *testing.T, fetched string, err error) {
|
||||||
|
|
@ -309,31 +309,3 @@ func writeToFile(t *testing.T, fetchDirName, fileContents string) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilePathSync_yamlToJSON(t *testing.T) {
|
|
||||||
tests := map[string]struct {
|
|
||||||
input []byte
|
|
||||||
handleResponse func(t *testing.T, output string, err error)
|
|
||||||
}{
|
|
||||||
"empty": {
|
|
||||||
input: []byte(""),
|
|
||||||
handleResponse: func(t *testing.T, output string, err error) {
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("expect no err, got err = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if output != "" {
|
|
||||||
t.Fatalf("expect output = '', got output = '%v'", output)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, tt := range tests {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
output, err := yamlToJSON(tt.input)
|
|
||||||
|
|
||||||
tt.handleResponse(t, output, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
parseUrl "net/url"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/open-feature/flagd/core/pkg/logger"
|
"github.com/open-feature/flagd/core/pkg/logger"
|
||||||
"github.com/open-feature/flagd/core/pkg/sync"
|
"github.com/open-feature/flagd/core/pkg/sync"
|
||||||
|
"github.com/open-feature/flagd/core/pkg/utils"
|
||||||
"golang.org/x/crypto/sha3" //nolint:gosec
|
"golang.org/x/crypto/sha3" //nolint:gosec
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -77,7 +80,7 @@ func (hs *Sync) Sync(ctx context.Context, dataSync chan<- sync.DataSync) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(body) == 0 {
|
if body == "" {
|
||||||
hs.Logger.Debug("configuration deleted")
|
hs.Logger.Debug("configuration deleted")
|
||||||
} else {
|
} else {
|
||||||
if hs.LastBodySHA == "" {
|
if hs.LastBodySHA == "" {
|
||||||
|
|
@ -89,7 +92,7 @@ func (hs *Sync) Sync(ctx context.Context, dataSync chan<- sync.DataSync) error {
|
||||||
dataSync <- sync.DataSync{FlagData: msg, Source: hs.URI, Type: sync.ALL}
|
dataSync <- sync.DataSync{FlagData: msg, Source: hs.URI, Type: sync.ALL}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentSHA := hs.generateSha(body)
|
currentSHA := hs.generateSha([]byte(body))
|
||||||
if hs.LastBodySHA != currentSHA {
|
if hs.LastBodySHA != currentSHA {
|
||||||
hs.Logger.Debug("configuration modified")
|
hs.Logger.Debug("configuration modified")
|
||||||
msg, err := hs.Fetch(ctx)
|
msg, err := hs.Fetch(ctx)
|
||||||
|
|
@ -115,13 +118,14 @@ func (hs *Sync) Sync(ctx context.Context, dataSync chan<- sync.DataSync) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hs *Sync) fetchBodyFromURL(ctx context.Context, url string) ([]byte, error) {
|
func (hs *Sync) fetchBodyFromURL(ctx context.Context, url string) (string, error) {
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", url, bytes.NewBuffer(nil))
|
req, err := http.NewRequestWithContext(ctx, "GET", url, bytes.NewBuffer(nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating request for url %s: %w", url, err)
|
return "", fmt.Errorf("error creating request for url %s: %w", url, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Add("Accept", "application/json")
|
req.Header.Add("Accept", "application/json")
|
||||||
|
req.Header.Add("Accept", "application/yaml")
|
||||||
|
|
||||||
if hs.AuthHeader != "" {
|
if hs.AuthHeader != "" {
|
||||||
req.Header.Set("Authorization", hs.AuthHeader)
|
req.Header.Set("Authorization", hs.AuthHeader)
|
||||||
|
|
@ -132,7 +136,7 @@ func (hs *Sync) fetchBodyFromURL(ctx context.Context, url string) ([]byte, error
|
||||||
|
|
||||||
resp, err := hs.Client.Do(req)
|
resp, err := hs.Client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error calling endpoint %s: %w", url, err)
|
return "", fmt.Errorf("error calling endpoint %s: %w", url, err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
err = resp.Body.Close()
|
err = resp.Body.Close()
|
||||||
|
|
@ -141,12 +145,31 @@ func (hs *Sync) fetchBodyFromURL(ctx context.Context, url string) ([]byte, error
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
statusOK := resp.StatusCode >= 200 && resp.StatusCode < 300
|
||||||
if err != nil {
|
if !statusOK {
|
||||||
return nil, fmt.Errorf("unable to read body to bytes: %w", err)
|
return "", fmt.Errorf("error fetching from url %s: %s", url, resp.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
return body, nil
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("unable to read body to bytes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
json, err := utils.ConvertToJSON(body, getFileExtensions(url), resp.Header.Get("Content-Type"))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error converting response body to json: %w", err)
|
||||||
|
}
|
||||||
|
return json, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFileExtensions returns the file extension from the URL path
|
||||||
|
func getFileExtensions(url string) string {
|
||||||
|
u, err := parseUrl.Parse(url)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Ext(u.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hs *Sync) generateSha(body []byte) string {
|
func (hs *Sync) generateSha(body []byte) string {
|
||||||
|
|
@ -164,9 +187,9 @@ func (hs *Sync) Fetch(ctx context.Context) (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if len(body) != 0 {
|
if body != "" {
|
||||||
hs.LastBodySHA = hs.generateSha(body)
|
hs.LastBodySHA = hs.generateSha([]byte(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(body), nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,19 +19,23 @@ import (
|
||||||
|
|
||||||
func TestSimpleSync(t *testing.T) {
|
func TestSimpleSync(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
resp := "test response"
|
|
||||||
|
|
||||||
mockCron := synctesting.NewMockCron(ctrl)
|
mockCron := synctesting.NewMockCron(ctrl)
|
||||||
mockCron.EXPECT().AddFunc(gomock.Any(), gomock.Any()).DoAndReturn(func(spec string, cmd func()) error {
|
mockCron.EXPECT().AddFunc(gomock.Any(), gomock.Any()).DoAndReturn(func(_ string, _ func()) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
mockCron.EXPECT().Start().Times(1)
|
mockCron.EXPECT().Start().Times(1)
|
||||||
|
|
||||||
mockClient := syncmock.NewMockClient(ctrl)
|
mockClient := syncmock.NewMockClient(ctrl)
|
||||||
mockClient.EXPECT().Do(gomock.Any()).Return(&http.Response{Body: io.NopCloser(strings.NewReader(resp))}, nil)
|
responseBody := "test response"
|
||||||
|
resp := &http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
|
Body: io.NopCloser(strings.NewReader(responseBody)),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
}
|
||||||
|
mockClient.EXPECT().Do(gomock.Any()).Return(resp, nil)
|
||||||
|
|
||||||
httpSync := Sync{
|
httpSync := Sync{
|
||||||
URI: "http://localhost",
|
URI: "http://localhost/flags",
|
||||||
Client: mockClient,
|
Client: mockClient,
|
||||||
Cron: mockCron,
|
Cron: mockCron,
|
||||||
LastBodySHA: "",
|
LastBodySHA: "",
|
||||||
|
|
@ -51,8 +55,51 @@ func TestSimpleSync(t *testing.T) {
|
||||||
|
|
||||||
data := <-dataSyncChan
|
data := <-dataSyncChan
|
||||||
|
|
||||||
if data.FlagData != resp {
|
if data.FlagData != responseBody {
|
||||||
t.Errorf("expected content: %s, but received content: %s", resp, data.FlagData)
|
t.Errorf("expected content: %s, but received content: %s", responseBody, data.FlagData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtensionWithQSSync(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
mockCron := synctesting.NewMockCron(ctrl)
|
||||||
|
mockCron.EXPECT().AddFunc(gomock.Any(), gomock.Any()).DoAndReturn(func(_ string, _ func()) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
mockCron.EXPECT().Start().Times(1)
|
||||||
|
|
||||||
|
mockClient := syncmock.NewMockClient(ctrl)
|
||||||
|
responseBody := "test response"
|
||||||
|
resp := &http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
|
Body: io.NopCloser(strings.NewReader(responseBody)),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
}
|
||||||
|
mockClient.EXPECT().Do(gomock.Any()).Return(resp, nil)
|
||||||
|
|
||||||
|
httpSync := Sync{
|
||||||
|
URI: "http://localhost/flags.json?env=dev",
|
||||||
|
Client: mockClient,
|
||||||
|
Cron: mockCron,
|
||||||
|
LastBodySHA: "",
|
||||||
|
Logger: logger.NewLogger(nil, false),
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
dataSyncChan := make(chan sync.DataSync)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := httpSync.Sync(ctx, dataSyncChan)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error start sync: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
data := <-dataSyncChan
|
||||||
|
|
||||||
|
if data.FlagData != responseBody {
|
||||||
|
t.Errorf("expected content: %s, but received content: %s", responseBody, data.FlagData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,9 +115,11 @@ func TestHTTPSync_Fetch(t *testing.T) {
|
||||||
handleResponse func(*testing.T, Sync, string, error)
|
handleResponse func(*testing.T, Sync, string, error)
|
||||||
}{
|
}{
|
||||||
"success": {
|
"success": {
|
||||||
setup: func(t *testing.T, client *syncmock.MockClient) {
|
setup: func(_ *testing.T, client *syncmock.MockClient) {
|
||||||
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
Body: io.NopCloser(strings.NewReader("test response")),
|
Body: io.NopCloser(strings.NewReader("test response")),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
}, nil)
|
}, nil)
|
||||||
},
|
},
|
||||||
uri: "http://localhost",
|
uri: "http://localhost",
|
||||||
|
|
@ -85,17 +134,19 @@ func TestHTTPSync_Fetch(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"return an error if no uri": {
|
"return an error if no uri": {
|
||||||
setup: func(t *testing.T, client *syncmock.MockClient) {},
|
setup: func(_ *testing.T, _ *syncmock.MockClient) {},
|
||||||
handleResponse: func(t *testing.T, _ Sync, fetched string, err error) {
|
handleResponse: func(t *testing.T, _ Sync, _ string, err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected err, got nil")
|
t.Error("expected err, got nil")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"update last body sha": {
|
"update last body sha": {
|
||||||
setup: func(t *testing.T, client *syncmock.MockClient) {
|
setup: func(_ *testing.T, client *syncmock.MockClient) {
|
||||||
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
Body: io.NopCloser(strings.NewReader("test response")),
|
Body: io.NopCloser(strings.NewReader("test response")),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
}, nil)
|
}, nil)
|
||||||
},
|
},
|
||||||
uri: "http://localhost",
|
uri: "http://localhost",
|
||||||
|
|
@ -121,7 +172,11 @@ func TestHTTPSync_Fetch(t *testing.T) {
|
||||||
if actualAuthHeader != "Bearer "+expectedToken {
|
if actualAuthHeader != "Bearer "+expectedToken {
|
||||||
t.Fatalf("expected Authorization header to be 'Bearer %s', got %s", expectedToken, actualAuthHeader)
|
t.Fatalf("expected Authorization header to be 'Bearer %s', got %s", expectedToken, actualAuthHeader)
|
||||||
}
|
}
|
||||||
return &http.Response{Body: io.NopCloser(strings.NewReader("test response"))}, nil
|
return &http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
|
Body: io.NopCloser(strings.NewReader("test response")),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
}, nil
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
uri: "http://localhost",
|
uri: "http://localhost",
|
||||||
|
|
@ -148,7 +203,11 @@ func TestHTTPSync_Fetch(t *testing.T) {
|
||||||
if actualAuthHeader != expectedHeader {
|
if actualAuthHeader != expectedHeader {
|
||||||
t.Fatalf("expected Authorization header to be '%s', got %s", expectedHeader, actualAuthHeader)
|
t.Fatalf("expected Authorization header to be '%s', got %s", expectedHeader, actualAuthHeader)
|
||||||
}
|
}
|
||||||
return &http.Response{Body: io.NopCloser(strings.NewReader("test response"))}, nil
|
return &http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
|
Body: io.NopCloser(strings.NewReader("test response")),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
}, nil
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
uri: "http://localhost",
|
uri: "http://localhost",
|
||||||
|
|
@ -167,6 +226,21 @@ func TestHTTPSync_Fetch(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"unauthorized request": {
|
||||||
|
setup: func(_ *testing.T, client *syncmock.MockClient) {
|
||||||
|
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
||||||
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
|
Body: io.NopCloser(strings.NewReader("test response")),
|
||||||
|
StatusCode: http.StatusUnauthorized,
|
||||||
|
}, nil)
|
||||||
|
},
|
||||||
|
uri: "http://localhost",
|
||||||
|
handleResponse: func(t *testing.T, _ Sync, _ string, err error) {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected unauthorized request to return an error")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tt := range tests {
|
for name, tt := range tests {
|
||||||
|
|
@ -226,9 +300,11 @@ func TestHTTPSync_Resync(t *testing.T) {
|
||||||
wantNotifications []sync.DataSync
|
wantNotifications []sync.DataSync
|
||||||
}{
|
}{
|
||||||
"success": {
|
"success": {
|
||||||
setup: func(t *testing.T, client *syncmock.MockClient) {
|
setup: func(_ *testing.T, client *syncmock.MockClient) {
|
||||||
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
client.EXPECT().Do(gomock.Any()).Return(&http.Response{
|
||||||
Body: io.NopCloser(strings.NewReader("test response")),
|
Header: map[string][]string{"Content-Type": {"application/json"}},
|
||||||
|
Body: io.NopCloser(strings.NewReader("")),
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
}, nil)
|
}, nil)
|
||||||
},
|
},
|
||||||
uri: "http://localhost",
|
uri: "http://localhost",
|
||||||
|
|
@ -251,8 +327,8 @@ func TestHTTPSync_Resync(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"error response": {
|
"error response": {
|
||||||
setup: func(t *testing.T, client *syncmock.MockClient) {},
|
setup: func(_ *testing.T, _ *syncmock.MockClient) {},
|
||||||
handleResponse: func(t *testing.T, _ Sync, fetched string, err error) {
|
handleResponse: func(t *testing.T, _ Sync, _ string, err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected err, got nil")
|
t.Error("expected err, got nil")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"mime"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var alphanumericRegex = regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||||
|
|
||||||
|
// ConvertToJSON attempts to convert the content of a file to JSON based on the file extension.
|
||||||
|
// The media type is used as a fallback in case the file extension is not recognized.
|
||||||
|
func ConvertToJSON(data []byte, fileExtension string, mediaType string) (string, error) {
|
||||||
|
var detectedType string
|
||||||
|
if fileExtension != "" {
|
||||||
|
// file extension only contains alphanumeric characters
|
||||||
|
detectedType = alphanumericRegex.ReplaceAllString(fileExtension, "")
|
||||||
|
} else {
|
||||||
|
parsedMediaType, _, err := mime.ParseMediaType(mediaType)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("unable to determine file format: %w", err)
|
||||||
|
}
|
||||||
|
detectedType = parsedMediaType
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize the detected type
|
||||||
|
detectedType = strings.ToLower(detectedType)
|
||||||
|
|
||||||
|
switch detectedType {
|
||||||
|
case "yaml", "yml", "application/yaml", "application/x-yaml":
|
||||||
|
str, err := YAMLToJSON(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error converting blob from yaml to json: %w", err)
|
||||||
|
}
|
||||||
|
return str, nil
|
||||||
|
case "json", "application/json":
|
||||||
|
return string(data), nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unsupported file format: '%s'", detectedType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConvertToJSON(t *testing.T) {
|
||||||
|
tests := map[string]struct {
|
||||||
|
data []byte
|
||||||
|
fileExtension string
|
||||||
|
mediaType string
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
errContains string
|
||||||
|
}{
|
||||||
|
"json file type": {
|
||||||
|
data: []byte(`{"flags": {"foo": "bar"}}`),
|
||||||
|
fileExtension: "json",
|
||||||
|
mediaType: "application/json",
|
||||||
|
want: `{"flags": {"foo": "bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"json file type using in http path": {
|
||||||
|
data: []byte(`{"flags": {"foo": "bar"}}`),
|
||||||
|
fileExtension: ".json/",
|
||||||
|
mediaType: "",
|
||||||
|
want: `{"flags": {"foo": "bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"json file type with encoding": {
|
||||||
|
data: []byte(`{"flags": {"foo": "bar"}}`),
|
||||||
|
fileExtension: "json",
|
||||||
|
mediaType: "application/json; charset=utf-8",
|
||||||
|
want: `{"flags": {"foo": "bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"yaml file type": {
|
||||||
|
data: []byte("flags:\n foo: bar"),
|
||||||
|
fileExtension: "yaml",
|
||||||
|
mediaType: "application/yaml",
|
||||||
|
want: `{"flags":{"foo":"bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"yaml file type with encoding": {
|
||||||
|
data: []byte("flags:\n foo: bar"),
|
||||||
|
fileExtension: "yaml",
|
||||||
|
mediaType: "application/yaml; charset=utf-8",
|
||||||
|
want: `{"flags":{"foo":"bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"yml file type": {
|
||||||
|
data: []byte("flags:\n foo: bar"),
|
||||||
|
fileExtension: "yml",
|
||||||
|
mediaType: "application/x-yaml",
|
||||||
|
want: `{"flags":{"foo":"bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"invalid yaml": {
|
||||||
|
data: []byte("invalid: [yaml: content"),
|
||||||
|
fileExtension: "yaml",
|
||||||
|
mediaType: "application/yaml",
|
||||||
|
wantErr: true,
|
||||||
|
errContains: "error converting blob from yaml to json",
|
||||||
|
},
|
||||||
|
"unsupported file type": {
|
||||||
|
data: []byte("some content"),
|
||||||
|
fileExtension: "txt",
|
||||||
|
mediaType: "text/plain",
|
||||||
|
wantErr: true,
|
||||||
|
errContains: "unsupported file format",
|
||||||
|
},
|
||||||
|
"empty file type with valid media type": {
|
||||||
|
data: []byte(`{"flags": {"foo": "bar"}}`),
|
||||||
|
fileExtension: "",
|
||||||
|
mediaType: "application/json",
|
||||||
|
want: `{"flags": {"foo": "bar"}}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"invalid media type": {
|
||||||
|
data: []byte("some content"),
|
||||||
|
fileExtension: "",
|
||||||
|
mediaType: "invalid/\\type",
|
||||||
|
wantErr: true,
|
||||||
|
errContains: "unable to determine file format",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tt := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
got, err := ConvertToJSON(tt.data, tt.fileExtension, tt.mediaType)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ConvertToJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if tt.wantErr {
|
||||||
|
if err == nil || !strings.Contains(err.Error(), tt.errContains) {
|
||||||
|
t.Errorf("ConvertToJSON() expected error containing %q, got %v", tt.errContains, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("ConvertToJSON() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// converts YAML byte array to JSON string
|
||||||
|
func YAMLToJSON(rawFile []byte) (string, error) {
|
||||||
|
if len(rawFile) == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var ms map[string]interface{}
|
||||||
|
if err := yaml.Unmarshal(rawFile, &ms); err != nil {
|
||||||
|
return "", fmt.Errorf("error unmarshaling yaml: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := json.Marshal(ms)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error marshaling json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(r), err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestYAMLToJSON(t *testing.T) {
|
||||||
|
tests := map[string]struct {
|
||||||
|
input []byte
|
||||||
|
expected string
|
||||||
|
expectedError bool
|
||||||
|
}{
|
||||||
|
"empty": {
|
||||||
|
input: []byte(""),
|
||||||
|
expected: "",
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
"simple yaml": {
|
||||||
|
input: []byte("key: value"),
|
||||||
|
expected: `{"key":"value"}`,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
"nested yaml": {
|
||||||
|
input: []byte("parent:\n child: value"),
|
||||||
|
expected: `{"parent":{"child":"value"}}`,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
"invalid yaml": {
|
||||||
|
input: []byte("invalid: yaml: : :"),
|
||||||
|
expectedError: true,
|
||||||
|
},
|
||||||
|
"array yaml": {
|
||||||
|
input: []byte("items:\n - item1\n - item2"),
|
||||||
|
expected: `{"items":["item1","item2"]}`,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
"complex yaml": {
|
||||||
|
input: []byte("bool: true\nnum: 123\nstr: hello\nobj:\n nested: value\narr:\n - 1\n - 2"),
|
||||||
|
expected: `{"arr":[1,2],"bool":true,"num":123,"obj":{"nested":"value"},"str":"hello"}`,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tt := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
output, err := YAMLToJSON(tt.input)
|
||||||
|
|
||||||
|
if tt.expectedError && err == nil {
|
||||||
|
t.Error("expected error but got none")
|
||||||
|
}
|
||||||
|
if !tt.expectedError && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if output != tt.expected {
|
||||||
|
t.Errorf("expected output '%v', got '%v'", tt.expected, output)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,10 +26,10 @@ See [sync source](../reference/sync-configuration.md#source-configuration) confi
|
||||||
The HTTP sync provider fetch flags from a remote source and periodically poll the source for flag definition updates.
|
The HTTP sync provider fetch flags from a remote source and periodically poll the source for flag definition updates.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
flagd start --uri https://my-flag-source.json
|
flagd start --uri https://my-flag-source/flags.json
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, `https://my-flag-source.json` is a remote endpoint responding valid feature flag definition when
|
In this example, `https://my-flag-source/flags.json` is a remote endpoint responding valid feature flag definition when
|
||||||
invoked with **HTTP GET** request.
|
invoked with **HTTP GET** request.
|
||||||
The polling interval, port, TLS settings, and authentication information can be configured.
|
The polling interval, port, TLS settings, and authentication information can be configured.
|
||||||
See [sync source](../reference/sync-configuration.md#source-configuration) configuration for details.
|
See [sync source](../reference/sync-configuration.md#source-configuration) configuration for details.
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,17 @@ it is passed to the correct implementation:
|
||||||
| `azblob` | `azblob://` | `azblob://my-container/my-flags.json` |
|
| `azblob` | `azblob://` | `azblob://my-container/my-flags.json` |
|
||||||
| `s3` | `s3://` | `s3://my-bucket/my-flags.json` |
|
| `s3` | `s3://` | `s3://my-bucket/my-flags.json` |
|
||||||
|
|
||||||
|
### Data Serialization
|
||||||
|
|
||||||
|
The `file`, `http`, `gcs`, `azblob` and `s3` sync providers expect the data to be formatted as JSON or YAML.
|
||||||
|
The file extension is used to determine the serialization format.
|
||||||
|
If the file extension hasn't been defined, the [media type](https://en.wikipedia.org/wiki/Media_type) will be used instead.
|
||||||
|
|
||||||
### Custom gRPC Target URI
|
### Custom gRPC Target URI
|
||||||
|
|
||||||
Apart from default `dns` resolution, Flagd also support different resolution method e.g. `xds`. Currently, we are supporting all [core resolver](https://grpc.io/docs/guides/custom-name-resolution/)
|
Apart from default `dns` resolution, Flagd also support different resolution method e.g. `xds`.
|
||||||
and one custom resolver for `envoy` proxy resolution. For more details, please refer the
|
Currently, we are supporting all [core resolver](https://grpc.io/docs/guides/custom-name-resolution/) and one custom resolver for `envoy` proxy resolution.
|
||||||
[RFC](https://github.com/open-feature/flagd/blob/main/docs/reference/specifications/proposal/rfc-grpc-custom-name-resolver.md) document.
|
For more details, please refer the [RFC](https://github.com/open-feature/flagd/blob/main/docs/reference/specifications/proposal/rfc-grpc-custom-name-resolver.md) document.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./bin/flagd start -x --uri envoy://localhost:9211/test.service
|
./bin/flagd start -x --uri envoy://localhost:9211/test.service
|
||||||
|
|
@ -72,8 +78,8 @@ Sync providers:
|
||||||
- `file` - config/samples/example_flags.json
|
- `file` - config/samples/example_flags.json
|
||||||
- `fsnotify` - config/samples/example_flags.json
|
- `fsnotify` - config/samples/example_flags.json
|
||||||
- `fileinfo` - config/samples/example_flags.json
|
- `fileinfo` - config/samples/example_flags.json
|
||||||
- `http` - <http://my-flag-source.json/>
|
- `http` - <http://my-flag-source.com/flags.json>
|
||||||
- `https` - <https://my-secure-flag-source.json/>
|
- `https` - <https://my-secure-flag-source.com/flags.json>
|
||||||
- `kubernetes` - default/my-flag-config
|
- `kubernetes` - default/my-flag-config
|
||||||
- `grpc`(insecure) - grpc-source:8080
|
- `grpc`(insecure) - grpc-source:8080
|
||||||
- `grpcs`(secure) - my-flag-source:8080
|
- `grpcs`(secure) - my-flag-source:8080
|
||||||
|
|
@ -88,9 +94,9 @@ Startup command:
|
||||||
--sources='[{"uri":"config/samples/example_flags.json","provider":"file"},
|
--sources='[{"uri":"config/samples/example_flags.json","provider":"file"},
|
||||||
{"uri":"config/samples/example_flags.json","provider":"fsnotify"},
|
{"uri":"config/samples/example_flags.json","provider":"fsnotify"},
|
||||||
{"uri":"config/samples/example_flags.json","provider":"fileinfo"},
|
{"uri":"config/samples/example_flags.json","provider":"fileinfo"},
|
||||||
{"uri":"http://my-flag-source.json","provider":"http","bearerToken":"bearer-dji34ld2l"},
|
{"uri":"http://my-flag-source/flags.json","provider":"http","bearerToken":"bearer-dji34ld2l"},
|
||||||
{"uri":"https://secure-remote/bearer-auth","provider":"http","authHeader":"Bearer bearer-dji34ld2l"},
|
{"uri":"https://secure-remote/bearer-auth/flags.json","provider":"http","authHeader":"Bearer bearer-dji34ld2l"},
|
||||||
{"uri":"https://secure-remote/basic-auth","provider":"http","authHeader":"Basic dXNlcjpwYXNz"},
|
{"uri":"https://secure-remote/basic-auth/flags.json","provider":"http","authHeader":"Basic dXNlcjpwYXNz"},
|
||||||
{"uri":"default/my-flag-config","provider":"kubernetes"},
|
{"uri":"default/my-flag-config","provider":"kubernetes"},
|
||||||
{"uri":"grpc-source:8080","provider":"grpc"},
|
{"uri":"grpc-source:8080","provider":"grpc"},
|
||||||
{"uri":"my-flag-source:8080","provider":"grpc", "maxMsgSize": 5242880},
|
{"uri":"my-flag-source:8080","provider":"grpc", "maxMsgSize": 5242880},
|
||||||
|
|
@ -110,7 +116,7 @@ sources:
|
||||||
provider: fsnotify
|
provider: fsnotify
|
||||||
- uri: config/samples/example_flags.json
|
- uri: config/samples/example_flags.json
|
||||||
provider: fileinfo
|
provider: fileinfo
|
||||||
- uri: http://my-flag-source.json
|
- uri: http://my-flag-source/flags.json
|
||||||
provider: http
|
provider: http
|
||||||
bearerToken: bearer-dji34ld2l
|
bearerToken: bearer-dji34ld2l
|
||||||
- uri: default/my-flag-config
|
- uri: default/my-flag-config
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue