Compare commits

...

45 Commits

Author SHA1 Message Date
Will Velida a9dafe6bac
Adding support for custom endpoint for OpenAI Conversation Component (#3834)
Signed-off-by: Will Velida <willvelida@hotmail.co.uk>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-06-05 20:31:52 -07:00
Nelson Parente 4a508409d7
feat: GCP copy, move, rename bucket (#3810)
Signed-off-by: nelson.parente <nelson_parente@live.com.pt>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-06-05 07:45:27 -07:00
Oisin Grehan 649483dda6
Update metadata.yaml for azure eventhubs binding (#3837)
Signed-off-by: Oisin Grehan <oising@gmail.com>
2025-06-04 11:32:54 -07:00
Nelson Parente 3525032f7a
Add metadata overrides for sensitive connection string values (URL and DSN support) (#3825)
Signed-off-by: nelson.parente <nelson_parente@live.com.pt>
2025-06-03 06:00:57 -07:00
Mike Nguyen 2f78a401b5
fix(tests): refactor env handling - sqlserver cert (#3823)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-05-28 22:36:49 -07:00
Josh van Leeuwen 88fce6a140
tests/certification: update dapr/dapr to HEAD (#3830)
Signed-off-by: joshvanl <me@joshvanl.dev>
2025-05-22 09:58:48 -07:00
Nelson Parente 026f99710a
GCP Storage Bucket binding: Bulk file transfer (#3811)
Signed-off-by: nelson.parente <nelson_parente@live.com.pt>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-05-22 07:03:56 -07:00
Josh van Leeuwen 132f562e48
Updates dapr/kit to main (#3816)
Signed-off-by: joshvanl <me@joshvanl.dev>
2025-05-22 06:59:46 -07:00
Gallardot 294dd75354
feat: kafka subpub and bindings support compression (#3676)
Signed-off-by: Gallardot <gallardot@apache.org>
Co-authored-by: Josh van Leeuwen <me@joshvanl.dev>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-05-16 10:45:37 -07:00
Nelson Parente 35b77e0c26
sec: bump opa (#3813)
Signed-off-by: nelson.parente <nelson_parente@live.com.pt>
2025-05-07 07:37:44 -07:00
Elena Kolevska 5f17025027
Adds Redis stream trimming by time(stream ID) (#3710)
Signed-off-by: Elena Kolevska <elena@kolevska.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: Nelson Parente <nelson_parente@live.com.pt>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
Co-authored-by: Bernd Verst <github@bernd.dev>
2025-05-06 10:59:30 -07:00
Anton Troshin 14921af0e1
Fix MQTT3 pubsub certification error (#3805)
Signed-off-by: Anton Troshin <anton@diagrid.io>
2025-05-06 08:03:08 -07:00
Adam shamis e53a258583
Feature/s3 add tagging to metadata (#3799)
Signed-off-by: adam6878 <adamshamis.dev@gmail.com>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-04-29 13:15:06 -07:00
Eric Shen 4dfc9e55d5
feat(pulsar): support subscribeInitialPosition on Pulsar consumer (#3700)
Signed-off-by: ericsyh <ericshenyuhao@outlook.com>
Signed-off-by: Eric Shen <ericshenyuhao@outlook.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
Co-authored-by: Josh van Leeuwen <me@joshvanl.dev>
2025-04-29 11:11:53 -07:00
Anton Troshin 01a3fe76d5
Add custom BulkGet method to Oracle Statestore (#3804)
Signed-off-by: Anton Troshin <anton@diagrid.io>
2025-04-29 10:39:12 -07:00
Anton Troshin 397766a23e
Support Oracle Connect Descriptors (#3800)
Signed-off-by: Anton Troshin <anton@diagrid.io>
2025-04-24 13:19:04 -07:00
Anton Troshin a68ca2179e
Solace pubsub conformance test fix (#3802)
Signed-off-by: Anton Troshin <anton@diagrid.io>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-04-23 05:34:59 -07:00
Cassie Coyle b2c31ceba2
Add baggage header support to http binding (#3723)
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
2025-04-23 05:33:24 -07:00
MikelRev 31a2088aac
Updated sqlserver auth to utilize default scope. (#3698)
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-04-17 08:54:52 -07:00
Emmanuel Auffray 70c99725fd
Adding GoogleAI models too (#3689)
Signed-off-by: Emmanuel Auffray <emmanuel.auffray@gmail.com>
Co-authored-by: Josh van Leeuwen <me@joshvanl.dev>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
2025-04-09 15:06:37 -07:00
Josh van Leeuwen 1bf9852e86
CVE go mod dep update (#3716)
Signed-off-by: joshvanl <me@joshvanl.dev>
2025-03-27 00:55:55 +02:00
Josh van Leeuwen d3eb43b827
go.mod: CVE updates (#3713)
Signed-off-by: joshvanl <me@joshvanl.dev>
2025-03-24 22:50:50 +02:00
Emmanuel Auffray 47947d8770
Adding Ollama as a conversation component for local dev/running of LLMs (#3688)
Signed-off-by: Emmanuel Auffray <emmanuel.auffray@gmail.com>
Co-authored-by: Mike Nguyen <hey@mike.ee>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-03-23 16:38:17 +00:00
Emmanuel Auffray b348969d81
Fix reference links of conversation components (#3690)
Signed-off-by: Emmanuel Auffray <emmanuel.auffray@gmail.com>
2025-03-21 13:52:15 +02:00
Josh van Leeuwen d8ac01bc76
Update go -> 1.24.1 & golangci-lint -> 1.64.6 (#3699)
Signed-off-by: joshvanl <me@joshvanl.dev>
2025-03-12 13:50:32 -07:00
Yaron Schneider 637d18d0f9
Release/rebase 1.15 (#3691) 2025-03-10 18:56:46 -07:00
Mike Nguyen 716542ae32
Merge branch 'release/rebase-1.15' of github.com:mikeee/components-contrib into release/rebase-1.15 2025-03-09 15:19:26 +00:00
Guspan Tanadi f406580f8e
docs(middleware/README): recent links components (#3638)
Signed-off-by: Guspan Tanadi <36249910+guspan-tanadi@users.noreply.github.com>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-03-09 15:17:19 +00:00
Elena Kolevska 0c2330bc19
reenables cert tests (#3642)
Signed-off-by: Elena Kolevska <elena@kolevska.com>
2025-03-09 15:16:53 +00:00
Josh van Leeuwen 692560dd8f
Workflows: Make request types optional and use proto strings (#3624)
Signed-off-by: joshvanl <me@joshvanl.dev>
2025-03-09 15:16:32 +00:00
Sam e427822ad8
fix: make sure region field is required on other components (#3625)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
2025-03-09 15:16:32 +00:00
Sam 1cae3ee094
feat(postgres): add iam roles anywhere auth profile (#3604)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
# Conflicts:
#	.build-tools/pkg/metadataschema/builtin-authentication-profiles.go
#	bindings/kafka/metadata.yaml
#	common/authentication/aws/static.go
#	common/authentication/aws/x509.go
#	common/authentication/postgresql/metadata.go
#	pubsub/kafka/metadata.yaml
2025-03-09 15:16:25 +00:00
Guspan Tanadi 2997e472d3
docs(middleware/README): recent links components (#3638)
Signed-off-by: Guspan Tanadi <36249910+guspan-tanadi@users.noreply.github.com>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2025-02-28 20:47:28 -08:00
Yaron Schneider 5ede374d0b
Update cert tests and build chain to latest (#3681)
Signed-off-by: yaron2 <schneider.yaron@live.com>
2025-02-26 10:39:42 -08:00
Artur Souza cf42966101
[1.15] Fix gcp bucket binding create + improve error messages. (#3678)
Signed-off-by: Artur Souza <asouza.pro@gmail.com>
2025-02-25 14:38:37 -08:00
Mike Nguyen 27f04354f8
ci: fix artifact handling (#3670)
Signed-off-by: Mike Nguyen <hey@mike.ee>
2025-02-14 06:48:32 -08:00
Elena Kolevska 1132db59d6
reenables cert tests (#3642)
Signed-off-by: Elena Kolevska <elena@kolevska.com>
2025-01-08 20:14:26 -08:00
MattCosturos 26808c927b
Recreate AEH Processor in the event of an error before retrying the processing operation (#3614)
Signed-off-by: MattCosturos <48531957+MattCosturos@users.noreply.github.com>
Signed-off-by: Matt Costuros <mcosturos@moog.com>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
Co-authored-by: Artur Souza <artursouza.ms@outlook.com>
2024-12-17 09:22:11 -08:00
Josh van Leeuwen aca5116d95
Workflows: Make request types optional and use proto strings (#3624)
Signed-off-by: joshvanl <me@joshvanl.dev>
2024-12-16 09:07:50 -08:00
Shivam Kumar fc8636dbba
Fix Redis EntraId Token Refresh (#3632)
Signed-off-by: Shivam Kumar <shivamkumar@microsoft.com>
Co-authored-by: Shivam Kumar <shivamkumar@microsoft.com>
2024-12-16 08:50:51 -08:00
Sam 026ae762fa
fix(pg): add region field too (#3628)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
2024-12-09 07:17:46 -08:00
Sam dcaa80eef8
style: pg cleaning up for things (#3627)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
2024-12-06 22:56:29 +00:00
Sam 1e295a7056
fix: make sure region field is required on other components (#3625)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
2024-12-06 14:00:34 -08:00
Sam 6200ea81de
style: improve clarity on aws changes (#3623)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
2024-12-04 12:45:34 -08:00
Sam 72c92fb1fe
feat(postgres): add iam roles anywhere auth profile (#3604)
Signed-off-by: Samantha Coyle <sam@diagrid.io>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
2024-12-03 13:17:13 -08:00
247 changed files with 4652 additions and 2595 deletions

View File

@ -1,6 +1,6 @@
module github.com/dapr/components-contrib/build-tools
go 1.23.5
go 1.24.1
require (
github.com/dapr/components-contrib v0.0.0
@ -12,17 +12,17 @@ require (
)
require (
github.com/dapr/kit v0.13.1-0.20240909215017-3823663aa4bb // indirect
github.com/dapr/kit v0.15.3-0.20250516121556-bc7dc566c45d // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/cast v1.8.0 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/apimachinery v0.26.10 // indirect
k8s.io/apimachinery v0.27.4 // indirect
)
replace github.com/dapr/components-contrib => ../

View File

@ -1,16 +1,16 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/dapr/kit v0.13.1-0.20240909215017-3823663aa4bb h1:ahLO7pMmX6HAuT6/RxYWBY4AN2fXQJcYlU1msY6Kt7U=
github.com/dapr/kit v0.13.1-0.20240909215017-3823663aa4bb/go.mod h1:Hz1W2LmWfA4UX/12MdA+brsf+np6f/1dJt6C6F63cjI=
github.com/dapr/kit v0.15.3-0.20250516121556-bc7dc566c45d h1:v+kZn9ami23xBsruyZmKErIOSlCdW9pR8wfHUg5+jys=
github.com/dapr/kit v0.15.3-0.20250516121556-bc7dc566c45d/go.mod h1:6w2Pr38zOAtBn+ld/jknwI4kgMfwanCIcFVnPykdPZQ=
github.com/davecgh/go-spew v1.1.0/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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
@ -27,20 +27,19 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY=
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -82,14 +81,13 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/apimachinery v0.26.10 h1:aE+J2KIbjctFqPp3Y0q4Wh2PD+l1p2g3Zp4UYjSvtGU=
k8s.io/apimachinery v0.26.10/go.mod h1:iT1ZP4JBP34wwM+ZQ8ByPEQ81u043iqAcsJYftX9amM=
k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -9,9 +9,13 @@ services:
shm_size: 1g
ulimits:
core: -1
# Setting nofile to 4096 and hard to 1048576, as recommended by Solace documentation
# Otherwise, the container will have an error and crash with:
# ERROR POST Violation [022]:Required system resource missing, Hard resource limit nofile 1048576 is required, 6592 detected
# https://docs.solace.com/Software-Broker/System-Resource-Requirements.htm#concurrent-open-files-considerations
nofile:
soft: 2448
hard: 6592
soft: 4096
hard: 1048576
deploy:
restart_policy:
condition: on-failure

View File

@ -0,0 +1,8 @@
#!/bin/bash
set -e
FILE="$1"
PROJECT="${2:-$FILE}"
docker compose -f .github/infrastructure/docker-compose-${FILE}.yml -p ${PROJECT} logs

View File

@ -440,6 +440,7 @@ const components = {
'pubsub.solace': {
conformance: true,
conformanceSetup: 'docker-compose.sh solace',
conformanceLogs: 'docker-compose-logs.sh solace',
},
'secretstores.azure.keyvault': {
certification: true,
@ -824,6 +825,7 @@ const components = {
* @property {boolean?} requireTerraform If true, requires Terraform
* @property {boolean?} requireKind If true, requires KinD
* @property {string?} conformanceSetup Setup script for conformance tests
* @property {string?} conformanceLogs Logs script for conformance tests
* @property {string?} conformanceDestroy Destroy script for conformance tests
* @property {string?} certificationSetup Setup script for certification tests
* @property {string?} certificationDestroy Destroy script for certification tests
@ -845,6 +847,7 @@ const components = {
* @property {boolean?} require-kind Requires KinD
* @property {string?} setup-script Setup script
* @property {string?} destroy-script Destroy script
* @property {string?} logs-script Logs script in case of failure
* @property {string?} nodejs-version Install the specified Node.js version if set
* @property {string?} mongodb-version Install the specified MongoDB version if set
* @property {string?} source-pkg Source package
@ -915,6 +918,7 @@ function GenerateMatrix(testKind, enableCloudTests) {
'require-kind': comp.requireKind ? 'true' : undefined,
'setup-script': comp[testKind + 'Setup'] || undefined,
'destroy-script': comp[testKind + 'Destroy'] || undefined,
'logs-script': comp[testKind + 'Logs'] || undefined,
'nodejs-version': comp.nodeJsVersion || undefined,
'mongodb-version': comp.mongoDbVersion || undefined,
'source-pkg': comp.sourcePkg

View File

@ -295,7 +295,7 @@ jobs:
uses: actions/upload-artifact@v4
if: github.event_name == 'schedule'
with:
name: cert_code_cov
name: ${{ matrix.component }}_cert_code_cov
path: ${{ env.TEST_PATH }}/tmp/cert_code_cov_files
retention-days: 7
@ -314,7 +314,7 @@ jobs:
uses: actions/upload-artifact@v4
if: always()
with:
name: result_files
name: ${{ matrix.component }}_result_files
path: tmp/result_files
retention-days: 1
@ -353,7 +353,7 @@ jobs:
continue-on-error: true
id: testresults
with:
name: result_files
# name: not being specified which will result in all artifacts being downloaded
path: tmp/result_files
- name: Build message

View File

@ -65,7 +65,7 @@ jobs:
GOOS: ${{ matrix.target_os }}
GOARCH: ${{ matrix.target_arch }}
GOPROXY: https://proxy.golang.org
GOLANGCI_LINT_VER: "v1.61.0"
GOLANGCI_LINT_VER: "v1.64.6"
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]

View File

@ -33,7 +33,7 @@ jobs:
GOOS: linux
GOARCH: amd64
GOPROXY: https://proxy.golang.org
GOLANGCI_LINT_VER: "v1.61.0"
GOLANGCI_LINT_VER: "v1.64.6"
steps:
- name: Check out code into the Go module directory
if: ${{ steps.skip_check.outputs.should_skip != 'true' }}

View File

@ -317,6 +317,10 @@ jobs:
exit 1
fi
- name: Retrieve infrastructure failure logs
if: failure() && matrix.logs-script != ''
run: .github/scripts/components-scripts/${{ matrix.logs-script }}
- name: Prepare test result info
if: always()
run: |
@ -332,7 +336,7 @@ jobs:
uses: actions/upload-artifact@v4
if: always()
with:
name: result_files
name: ${{ matrix.component }}_result_files
path: tmp/result_files
retention-days: 1
@ -346,14 +350,14 @@ jobs:
uses: actions/upload-artifact@v4
if: github.event_name == 'schedule'
with:
name: conf_code_cov
name: ${{ matrix.component }}_conf_code_cov
path: tmp/conf_code_cov
retention-days: 7
# Upload logs for test analytics to consume
- name: Upload test results
if: always()
uses: actions/upload-artifact@main
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.component }}_conformance_test
path: ${{ env.TEST_OUTPUT_FILE_PREFIX }}_conformance.*
@ -385,7 +389,7 @@ jobs:
continue-on-error: true
id: testresults
with:
name: result_files
# name: not being specified which will result in all artifacts being downloaded
path: tmp/result_files
- name: Build message

View File

@ -60,7 +60,7 @@ linters-settings:
# [deprecated] comma-separated list of pairs of the form pkg:regex
# the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
ignore: fmt:.*,io/ioutil:^Read.*
exclude-functions: fmt:.*,io/ioutil:^Read.*
# path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details
@ -285,7 +285,6 @@ linters:
- unparam
- wsl
- mnd
- gomnd
- testpackage
- err113
- nestif

View File

@ -57,11 +57,11 @@ func TestPublishMsg(t *testing.T) { //nolint:paralleltest
}}}
d := NewDingTalkWebhook(logger.NewLogger("test"))
err := d.Init(context.Background(), m)
err := d.Init(t.Context(), m)
require.NoError(t, err)
req := &bindings.InvokeRequest{Data: []byte(msg), Operation: bindings.CreateOperation, Metadata: map[string]string{}}
_, err = d.Invoke(context.Background(), req)
_, err = d.Invoke(t.Context(), req)
require.NoError(t, err)
}
@ -78,7 +78,7 @@ func TestBindingReadAndInvoke(t *testing.T) { //nolint:paralleltest
}}
d := NewDingTalkWebhook(logger.NewLogger("test"))
err := d.Init(context.Background(), m)
err := d.Init(t.Context(), m)
require.NoError(t, err)
var count int32
@ -92,11 +92,11 @@ func TestBindingReadAndInvoke(t *testing.T) { //nolint:paralleltest
return nil, nil
}
err = d.Read(context.Background(), handler)
err = d.Read(t.Context(), handler)
require.NoError(t, err)
req := &bindings.InvokeRequest{Data: []byte(msg), Operation: bindings.GetOperation, Metadata: map[string]string{}}
_, err = d.Invoke(context.Background(), req)
_, err = d.Invoke(t.Context(), req)
require.NoError(t, err)
select {
@ -117,7 +117,7 @@ func TestBindingClose(t *testing.T) {
"id": "x",
},
}}
require.NoError(t, d.Init(context.Background(), m))
require.NoError(t, d.Init(t.Context(), m))
require.NoError(t, d.Close())
require.NoError(t, d.Close(), "second close should not error")
}

View File

@ -14,7 +14,6 @@ limitations under the License.
package tablestore
import (
"context"
"encoding/json"
"os"
"testing"
@ -52,7 +51,7 @@ func TestDataEncodeAndDecode(t *testing.T) {
metadata := bindings.Metadata{Base: metadata.Base{
Properties: getTestProperties(),
}}
aliCloudTableStore.Init(context.Background(), metadata)
aliCloudTableStore.Init(t.Context(), metadata)
// test create
putData := map[string]interface{}{
@ -71,7 +70,7 @@ func TestDataEncodeAndDecode(t *testing.T) {
Data: data,
}
putInvokeResp, err := aliCloudTableStore.Invoke(context.Background(), putRowReq)
putInvokeResp, err := aliCloudTableStore.Invoke(t.Context(), putRowReq)
require.NoError(t, err)
assert.NotNil(t, putInvokeResp)
@ -82,7 +81,7 @@ func TestDataEncodeAndDecode(t *testing.T) {
"column2": int64(2),
})
putInvokeResp, err = aliCloudTableStore.Invoke(context.Background(), putRowReq)
putInvokeResp, err = aliCloudTableStore.Invoke(t.Context(), putRowReq)
require.NoError(t, err)
assert.NotNil(t, putInvokeResp)
@ -102,7 +101,7 @@ func TestDataEncodeAndDecode(t *testing.T) {
Data: getData,
}
getInvokeResp, err := aliCloudTableStore.Invoke(context.Background(), getInvokeReq)
getInvokeResp, err := aliCloudTableStore.Invoke(t.Context(), getInvokeReq)
require.NoError(t, err)
assert.NotNil(t, getInvokeResp)
@ -136,7 +135,7 @@ func TestDataEncodeAndDecode(t *testing.T) {
Data: listData,
}
listResp, err := aliCloudTableStore.Invoke(context.Background(), listReq)
listResp, err := aliCloudTableStore.Invoke(t.Context(), listReq)
require.NoError(t, err)
assert.NotNil(t, listResp)
@ -164,12 +163,12 @@ func TestDataEncodeAndDecode(t *testing.T) {
Data: deleteData,
}
deleteResp, err := aliCloudTableStore.Invoke(context.Background(), deleteReq)
deleteResp, err := aliCloudTableStore.Invoke(t.Context(), deleteReq)
require.NoError(t, err)
assert.NotNil(t, deleteResp)
getInvokeResp, err = aliCloudTableStore.Invoke(context.Background(), getInvokeReq)
getInvokeResp, err = aliCloudTableStore.Invoke(t.Context(), getInvokeReq)
require.NoError(t, err)
assert.Nil(t, getInvokeResp.Data)

View File

@ -15,7 +15,6 @@ package apns
import (
"bytes"
"context"
"io"
"net/http"
"strings"
@ -52,7 +51,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.NoError(t, err)
assert.Equal(t, developmentPrefix, binding.urlPrefix)
})
@ -67,7 +66,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.NoError(t, err)
assert.Equal(t, productionPrefix, binding.urlPrefix)
})
@ -81,7 +80,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.NoError(t, err)
assert.Equal(t, productionPrefix, binding.urlPrefix)
})
@ -94,7 +93,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.Error(t, err, "the key-id parameter is required")
})
@ -107,7 +106,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.NoError(t, err)
assert.Equal(t, testKeyID, binding.authorizationBuilder.keyID)
})
@ -120,7 +119,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.Error(t, err, "the team-id parameter is required")
})
@ -133,7 +132,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.NoError(t, err)
assert.Equal(t, testTeamID, binding.authorizationBuilder.teamID)
})
@ -146,7 +145,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.Error(t, err, "the private-key parameter is required")
})
@ -159,7 +158,7 @@ func TestInit(t *testing.T) {
},
}}
binding := NewAPNS(testLogger).(*APNS)
err := binding.Init(context.Background(), metadata)
err := binding.Init(t.Context(), metadata)
require.NoError(t, err)
assert.NotNil(t, binding.authorizationBuilder.privateKey)
})
@ -192,7 +191,7 @@ func TestInvoke(t *testing.T) {
t.Run("operation must be create", func(t *testing.T) {
testBinding := makeTestBinding(t, testLogger)
req := &bindings.InvokeRequest{Operation: bindings.DeleteOperation}
_, err := testBinding.Invoke(context.TODO(), req)
_, err := testBinding.Invoke(t.Context(), req)
require.Error(t, err, "operation not supported: delete")
})
@ -202,7 +201,7 @@ func TestInvoke(t *testing.T) {
Operation: bindings.CreateOperation,
Metadata: map[string]string{},
}
_, err := testBinding.Invoke(context.TODO(), req)
_, err := testBinding.Invoke(t.Context(), req)
require.Error(t, err, "the device-token parameter is required")
})
@ -213,7 +212,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the push type header is sent", func(t *testing.T) {
@ -224,7 +223,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the message ID is sent", func(t *testing.T) {
@ -235,7 +234,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the expiration is sent", func(t *testing.T) {
@ -246,7 +245,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the priority is sent", func(t *testing.T) {
@ -257,7 +256,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the topic is sent", func(t *testing.T) {
@ -268,7 +267,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the collapse ID is sent", func(t *testing.T) {
@ -279,7 +278,7 @@ func TestInvoke(t *testing.T) {
return successResponse()
})
_, _ = testBinding.Invoke(context.TODO(), successRequest)
_, _ = testBinding.Invoke(t.Context(), successRequest)
})
t.Run("the message ID is returned", func(t *testing.T) {
@ -287,7 +286,7 @@ func TestInvoke(t *testing.T) {
testBinding.client = newTestClient(func(req *http.Request) *http.Response {
return successResponse()
})
response, err := testBinding.Invoke(context.TODO(), successRequest)
response, err := testBinding.Invoke(t.Context(), successRequest)
require.NoError(t, err)
assert.NotNil(t, response.Data)
var body notificationResponse
@ -307,7 +306,7 @@ func TestInvoke(t *testing.T) {
Body: io.NopCloser(strings.NewReader(body)),
}
})
_, err := testBinding.Invoke(context.TODO(), successRequest)
_, err := testBinding.Invoke(t.Context(), successRequest)
require.Error(t, err, "BadDeviceToken")
})
}
@ -322,7 +321,7 @@ func makeTestBinding(t *testing.T, log logger.Logger) *APNS {
privateKeyKey: testPrivateKey,
},
}}
err := testBinding.Init(context.Background(), bindingMetadata)
err := testBinding.Init(t.Context(), bindingMetadata)
require.NoError(t, err)
return testBinding

View File

@ -40,7 +40,7 @@ import (
"github.com/dapr/kit/logger"
kitmd "github.com/dapr/kit/metadata"
"github.com/dapr/kit/ptr"
"github.com/dapr/kit/utils"
kitstrings "github.com/dapr/kit/strings"
)
const (
@ -49,6 +49,7 @@ const (
metadataFilePath = "filePath"
metadataPresignTTL = "presignTTL"
metadataStorageClass = "storageClass"
metadataTags = "tags"
metatadataContentType = "Content-Type"
metadataKey = "key"
@ -191,6 +192,15 @@ func (s *AWSS3) create(ctx context.Context, req *bindings.InvokeRequest) (*bindi
if contentTypeStr != "" {
contentType = &contentTypeStr
}
var tagging *string
if rawTags, ok := req.Metadata[metadataTags]; ok {
tagging, err = s.parseS3Tags(rawTags)
if err != nil {
return nil, fmt.Errorf("s3 binding error: parsing tags falied error: %w", err)
}
}
var r io.Reader
if metadata.FilePath != "" {
r, err = os.Open(metadata.FilePath)
@ -209,12 +219,14 @@ func (s *AWSS3) create(ctx context.Context, req *bindings.InvokeRequest) (*bindi
if metadata.StorageClass != "" {
storageClass = aws.String(metadata.StorageClass)
}
resultUpload, err := s.authProvider.S3().Uploader.UploadWithContext(ctx, &s3manager.UploadInput{
Bucket: ptr.Of(metadata.Bucket),
Key: ptr.Of(key),
Body: r,
ContentType: contentType,
StorageClass: storageClass,
Tagging: tagging,
})
if err != nil {
return nil, fmt.Errorf("s3 binding error: uploading failed: %w", err)
@ -418,16 +430,36 @@ func (s *AWSS3) parseMetadata(md bindings.Metadata) (*s3Metadata, error) {
return &m, nil
}
// Helper for parsing s3 tags metadata
func (s *AWSS3) parseS3Tags(raw string) (*string, error) {
tagEntries := strings.Split(raw, ",")
pairs := make([]string, 0, len(tagEntries))
for _, tagEntry := range tagEntries {
kv := strings.SplitN(strings.TrimSpace(tagEntry), "=", 2)
isInvalidTag := len(kv) != 2 || strings.TrimSpace(kv[0]) == "" || strings.TrimSpace(kv[1]) == ""
if isInvalidTag {
return nil, fmt.Errorf("invalid tag format: '%s' (expected key=value)", tagEntry)
}
pairs = append(pairs, fmt.Sprintf("%s=%s", strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])))
}
if len(pairs) == 0 {
return nil, nil
}
return aws.String(strings.Join(pairs, "&")), nil
}
// Helper to merge config and request metadata.
func (metadata s3Metadata) mergeWithRequestMetadata(req *bindings.InvokeRequest) (s3Metadata, error) {
merged := metadata
if val, ok := req.Metadata[metadataDecodeBase64]; ok && val != "" {
merged.DecodeBase64 = utils.IsTruthy(val)
merged.DecodeBase64 = kitstrings.IsTruthy(val)
}
if val, ok := req.Metadata[metadataEncodeBase64]; ok && val != "" {
merged.EncodeBase64 = utils.IsTruthy(val)
merged.EncodeBase64 = kitstrings.IsTruthy(val)
}
if val, ok := req.Metadata[metadataFilePath]; ok && val != "" {

View File

@ -14,7 +14,6 @@ limitations under the License.
package s3
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
@ -54,6 +53,24 @@ func TestParseMetadata(t *testing.T) {
})
}
func TestParseS3Tags(t *testing.T) {
t.Run("Has parsed s3 tags", func(t *testing.T) {
request := bindings.InvokeRequest{}
request.Metadata = map[string]string{
"decodeBase64": "yes",
"encodeBase64": "false",
"filePath": "/usr/vader.darth",
"storageClass": "STANDARD_IA",
"tags": "project=myproject,year=2024",
}
s3 := AWSS3{}
parsedTags, err := s3.parseS3Tags(request.Metadata["tags"])
require.NoError(t, err)
assert.Equal(t, "project=myproject&year=2024", *parsedTags)
})
}
func TestMergeWithRequestMetadata(t *testing.T) {
t.Run("Has merged metadata", func(t *testing.T) {
m := bindings.Metadata{}
@ -176,7 +193,7 @@ func TestGetOption(t *testing.T) {
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := s3.get(context.Background(), &r)
_, err := s3.get(t.Context(), &r)
require.Error(t, err)
})
}
@ -187,7 +204,7 @@ func TestDeleteOption(t *testing.T) {
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := s3.delete(context.Background(), &r)
_, err := s3.delete(t.Context(), &r)
require.Error(t, err)
})
}

View File

@ -14,7 +14,6 @@ limitations under the License.
package blobstorage
import (
"context"
"testing"
"github.com/stretchr/testify/require"
@ -28,7 +27,7 @@ func TestGetOption(t *testing.T) {
t.Run("return error if blobName is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := blobStorage.get(context.Background(), &r)
_, err := blobStorage.get(t.Context(), &r)
require.Error(t, err)
require.ErrorIs(t, err, ErrMissingBlobName)
})
@ -39,7 +38,7 @@ func TestDeleteOption(t *testing.T) {
t.Run("return error if blobName is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := blobStorage.delete(context.Background(), &r)
_, err := blobStorage.delete(t.Context(), &r)
require.Error(t, err)
require.ErrorIs(t, err, ErrMissingBlobName)
})
@ -50,7 +49,7 @@ func TestDeleteOption(t *testing.T) {
"blobName": "foo",
"deleteSnapshots": "invalid",
}
_, err := blobStorage.delete(context.Background(), &r)
_, err := blobStorage.delete(t.Context(), &r)
require.Error(t, err)
})
}

View File

@ -94,7 +94,7 @@ func createEventHubsBindingsAADMetadata() bindings.Metadata {
}
func testEventHubsBindingsAADAuthentication(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
log := logger.NewLogger("bindings.azure.eventhubs.integration.test")
@ -102,7 +102,7 @@ func testEventHubsBindingsAADAuthentication(t *testing.T) {
metadata := createEventHubsBindingsAADMetadata()
eventHubsBindings := NewAzureEventHubs(log)
err := eventHubsBindings.Init(context.Background(), metadata)
err := eventHubsBindings.Init(t.Context(), metadata)
require.NoError(t, err)
req := &bindings.InvokeRequest{
@ -142,11 +142,11 @@ func testEventHubsBindingsAADAuthentication(t *testing.T) {
}
func testReadIotHubEvents(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
logger := logger.NewLogger("bindings.azure.eventhubs.integration.test")
eh := NewAzureEventHubs(logger)
err := eh.Init(context.Background(), createIotHubBindingsMetadata())
err := eh.Init(t.Context(), createIotHubBindingsMetadata())
require.NoError(t, err)
// Invoke az CLI via bash script to send test IoT device events

View File

@ -162,8 +162,9 @@ metadata:
Storage container name.
example: '"myeventhubstoragecontainer"'
- name: getAllMessageProperties
type: bool
required: false
default: "false"
default: false
example: "false"
binding:
input: true

View File

@ -313,7 +313,7 @@ func TestWriteShouldFail(t *testing.T) {
t.Run("Missing hub should fail", func(t *testing.T) {
httpTransport.reset()
_, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{},
})
@ -325,7 +325,7 @@ func TestWriteShouldFail(t *testing.T) {
httpTransport.reset()
httpErr := errors.New("fake error")
httpTransport.errToReturn = httpErr
_, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
hubKey: "testHub",
@ -339,7 +339,7 @@ func TestWriteShouldFail(t *testing.T) {
t.Run("SignalR call returns status != [200, 202]", func(t *testing.T) {
httpTransport.reset()
httpTransport.response.StatusCode = 401
_, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
hubKey: "testHub",
@ -364,7 +364,7 @@ func TestWriteShouldSucceed(t *testing.T) {
t.Run("Has authorization", func(t *testing.T) {
httpTransport.reset()
_, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
hubKey: "testHub",
@ -397,7 +397,7 @@ func TestWriteShouldSucceed(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
httpTransport.reset()
s.hub = tt.hubInMetadata
_, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
hubKey: tt.hubInWriteRequest,
@ -433,7 +433,7 @@ func TestGetShouldSucceed(t *testing.T) {
t.Run("Can get negotiate response with accessKey", func(t *testing.T) {
s.aadToken = nil
s.accessKey = "AAbbcCsGEQKoLEH6oodDR0jK104Fu1c39Qgk+AA8D+M="
res, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
hubKey: "testHub",
},
@ -463,7 +463,7 @@ func TestGetShouldSucceed(t *testing.T) {
t.Run("Can get negotiate response with accessKey and userId", func(t *testing.T) {
s.aadToken = nil
s.accessKey = "AAbbcCsGEQKoLEH6oodDR0jK104Fu1c39Qgk+AA8D+M="
res, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
hubKey: "testHub",
userKey: "user1",
@ -499,7 +499,7 @@ func TestGetShouldSucceed(t *testing.T) {
}
httpTransport.reset()
res, err := s.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := s.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
hubKey: "testHub",
userKey: "user?1&2",

View File

@ -96,12 +96,12 @@ func TestWriteQueue(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{Data: []byte("This is my message")}
_, err = a.Invoke(context.Background(), &r)
_, err = a.Invoke(t.Context(), &r)
require.NoError(t, err)
require.NoError(t, a.Close())
@ -118,12 +118,12 @@ func TestWriteWithTTLInQueue(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1", metadata.TTLMetadataKey: "1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{Data: []byte("This is my message")}
_, err = a.Invoke(context.Background(), &r)
_, err = a.Invoke(t.Context(), &r)
require.NoError(t, err)
require.NoError(t, a.Close())
@ -140,7 +140,7 @@ func TestWriteWithTTLInWrite(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1", metadata.TTLMetadataKey: "1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{
@ -148,7 +148,7 @@ func TestWriteWithTTLInWrite(t *testing.T) {
Metadata: map[string]string{metadata.TTLMetadataKey: "1"},
}
_, err = a.Invoke(context.Background(), &r)
_, err = a.Invoke(t.Context(), &r)
require.NoError(t, err)
require.NoError(t, a.Close())
@ -162,7 +162,7 @@ func TestWriteWithTTLInWrite(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{Data: []byte("This is my message")}
@ -181,12 +181,12 @@ func TestReadQueue(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{Data: []byte("This is my message")}
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
_, err = a.Invoke(ctx, &r)
require.NoError(t, err)
@ -223,12 +223,12 @@ func TestReadQueueDecode(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1", "decodeBase64": "true"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{Data: []byte("VGhpcyBpcyBteSBtZXNzYWdl")}
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
_, err = a.Invoke(ctx, &r)
require.NoError(t, err)
@ -263,7 +263,7 @@ func TestReadQueueDecode(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
r := bindings.InvokeRequest{Data: []byte("This is my message")}
@ -294,10 +294,10 @@ func TestReadQueueNoMessage(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"storageAccessKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", "queue": "queue1", "storageAccount": "devstoreaccount1"}
err := a.Init(context.Background(), m)
err := a.Init(t.Context(), m)
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
received := 0
handler := func(ctx context.Context, data *bindings.ReadResponse) ([]byte, error) {
received++

View File

@ -75,7 +75,7 @@ func (q *CFQueues) Init(_ context.Context, metadata bindings.Metadata) error {
}
// Operations returns the supported operations for this binding.
func (q CFQueues) Operations() []bindings.OperationKind {
func (q *CFQueues) Operations() []bindings.OperationKind {
return []bindings.OperationKind{bindings.CreateOperation, "publish"}
}

View File

@ -201,7 +201,7 @@ func (ct *Binding) Close() error {
}
// GetComponentMetadata returns the metadata of the component.
func (ct Binding) GetComponentMetadata() (metadataInfo contribMetadata.MetadataMap) {
func (ct *Binding) GetComponentMetadata() (metadataInfo contribMetadata.MetadataMap) {
metadataStruct := commercetoolsMetadata{}
contribMetadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo, contribMetadata.BindingType)
return

View File

@ -85,7 +85,7 @@ func TestCronInitSuccess(t *testing.T) {
for _, test := range initTests {
c := getNewCron()
err := c.Init(context.Background(), getTestMetadata(test.schedule))
err := c.Init(t.Context(), getTestMetadata(test.schedule))
if test.errorExpected {
require.Errorf(t, err, "Got no error while initializing an invalid schedule: %s", test.schedule)
} else {
@ -100,10 +100,10 @@ func TestCronRead(t *testing.T) {
clk := clocktesting.NewFakeClock(time.Now())
c := getNewCronWithClock(clk)
schedule := "@every 1s"
require.NoErrorf(t, c.Init(context.Background(), getTestMetadata(schedule)), "error initializing valid schedule")
require.NoErrorf(t, c.Init(t.Context(), getTestMetadata(schedule)), "error initializing valid schedule")
expectedCount := int32(5)
var observedCount atomic.Int32
err := c.Read(context.Background(), func(ctx context.Context, res *bindings.ReadResponse) ([]byte, error) {
err := c.Read(t.Context(), func(ctx context.Context, res *bindings.ReadResponse) ([]byte, error) {
assert.NotNil(t, res)
observedCount.Add(1)
return nil, nil
@ -128,10 +128,10 @@ func TestCronReadWithContextCancellation(t *testing.T) {
clk := clocktesting.NewFakeClock(time.Now())
c := getNewCronWithClock(clk)
schedule := "@every 1s"
require.NoErrorf(t, c.Init(context.Background(), getTestMetadata(schedule)), "error initializing valid schedule")
require.NoErrorf(t, c.Init(t.Context(), getTestMetadata(schedule)), "error initializing valid schedule")
expectedCount := int32(5)
var observedCount atomic.Int32
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
err := c.Read(ctx, func(ctx context.Context, res *bindings.ReadResponse) ([]byte, error) {
assert.NotNil(t, res)
assert.LessOrEqualf(t, observedCount.Load(), expectedCount, "Invoke didn't stop the schedule")

View File

@ -78,7 +78,7 @@ func TestInvoke(t *testing.T) {
reqData := enc.Buffer()
// 3. invoke dapr dubbo output binding, get rsp bytes
rsp, err := output.Invoke(context.Background(), &bindings.InvokeRequest{
rsp, err := output.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
metadataRPCProviderPort: dubboPort,
metadataRPCProviderHostname: localhostIP,

View File

@ -25,10 +25,12 @@ import (
"net/url"
"reflect"
"strconv"
"sync"
"time"
"cloud.google.com/go/storage"
"github.com/google/uuid"
"go.uber.org/multierr"
"google.golang.org/api/googleapi"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
@ -37,7 +39,7 @@ import (
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/kit/logger"
kitmd "github.com/dapr/kit/metadata"
"github.com/dapr/kit/utils"
"github.com/dapr/kit/strings"
)
const (
@ -49,8 +51,12 @@ const (
metadataKey = "key"
maxResults = 1000
metadataKeyBC = "name"
signOperation = "sign"
metadataKeyBC = "name"
signOperation = "sign"
bulkGetOperation = "bulkGet"
copyOperation = "copy"
renameOperation = "rename"
moveOperation = "move"
)
// GCPStorage allows saving data to GCP bucket storage.
@ -84,6 +90,7 @@ type listPayload struct {
MaxResults int32 `json:"maxResults"`
Delimiter string `json:"delimiter"`
}
type signResponse struct {
SignURL string `json:"signURL"`
}
@ -138,6 +145,10 @@ func (g *GCPStorage) Operations() []bindings.OperationKind {
bindings.DeleteOperation,
bindings.ListOperation,
signOperation,
bulkGetOperation,
copyOperation,
renameOperation,
moveOperation,
}
}
@ -155,6 +166,14 @@ func (g *GCPStorage) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*
return g.list(ctx, req)
case signOperation:
return g.sign(ctx, req)
case bulkGetOperation:
return g.bulkGet(ctx, req)
case copyOperation:
return g.copy(ctx, req)
case renameOperation:
return g.rename(ctx, req)
case moveOperation:
return g.move(ctx, req)
default:
return nil, fmt.Errorf("unsupported operation %s", req.Operation)
}
@ -164,7 +183,7 @@ func (g *GCPStorage) create(ctx context.Context, req *bindings.InvokeRequest) (*
var err error
metadata, err := g.metadata.mergeWithRequestMetadata(req)
if err != nil {
return nil, fmt.Errorf("gcp bucket binding error. error merge metadata : %w", err)
return nil, fmt.Errorf("gcp bucket binding error while merging metadata : %w", err)
}
var name string
@ -186,14 +205,23 @@ func (g *GCPStorage) create(ctx context.Context, req *bindings.InvokeRequest) (*
}
h := g.client.Bucket(g.metadata.Bucket).Object(name).NewWriter(ctx)
defer h.Close()
// Cannot do `defer h.Close()` as Close() will flush the bytes and need to have error handling.
if _, err = io.Copy(h, r); err != nil {
return nil, fmt.Errorf("gcp bucket binding error. Uploading: %w", err)
cerr := h.Close()
if cerr != nil {
return nil, fmt.Errorf("gcp bucket binding error while uploading and closing: %w", err)
}
return nil, fmt.Errorf("gcp bucket binding error while uploading: %w", err)
}
err = h.Close()
if err != nil {
return nil, fmt.Errorf("gcp bucket binding error while flushing: %w", err)
}
objectURL, err := url.Parse(fmt.Sprintf(objectURLBase, g.metadata.Bucket, name))
if err != nil {
return nil, fmt.Errorf("gcp bucket binding error. error building url response: %w", err)
return nil, fmt.Errorf("gcp bucket binding error while building url response: %w", err)
}
resp := createResponse{
@ -202,7 +230,7 @@ func (g *GCPStorage) create(ctx context.Context, req *bindings.InvokeRequest) (*
b, err := json.Marshal(resp)
if err != nil {
return nil, fmt.Errorf("gcp binding error. error marshalling create response: %w", err)
return nil, fmt.Errorf("gcp bucket binding error while marshalling the create response: %w", err)
}
return &bindings.InvokeResponse{
@ -213,7 +241,7 @@ func (g *GCPStorage) create(ctx context.Context, req *bindings.InvokeRequest) (*
func (g *GCPStorage) get(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
metadata, err := g.metadata.mergeWithRequestMetadata(req)
if err != nil {
return nil, fmt.Errorf("gcp binding error. error merge metadata : %w", err)
return nil, fmt.Errorf("gcp binding error while merging metadata : %w", err)
}
var key string
@ -231,13 +259,13 @@ func (g *GCPStorage) get(ctx context.Context, req *bindings.InvokeRequest) (*bin
return nil, errors.New("object not found")
}
return nil, fmt.Errorf("gcp bucketgcp bucket binding error: error downloading bucket object: %w", err)
return nil, fmt.Errorf("gcp bucketgcp bucket binding error while downloading object: %w", err)
}
defer rc.Close()
data, err := io.ReadAll(rc)
if err != nil {
return nil, fmt.Errorf("gcp bucketgcp bucket binding error: io.ReadAll: %v", err)
return nil, fmt.Errorf("gcp bucketgcp bucket binding error while reading: %v", err)
}
if metadata.EncodeBase64 {
@ -299,7 +327,7 @@ func (g *GCPStorage) list(ctx context.Context, req *bindings.InvokeRequest) (*bi
jsonResponse, err := json.Marshal(result)
if err != nil {
return nil, fmt.Errorf("gcp bucketgcp bucket binding error. list operation. cannot marshal blobs to json: %w", err)
return nil, fmt.Errorf("gcp bucketgcp bucket binding error while listing: cannot marshal blobs to json: %w", err)
}
return &bindings.InvokeResponse{
@ -316,11 +344,11 @@ func (metadata gcpMetadata) mergeWithRequestMetadata(req *bindings.InvokeRequest
merged := metadata
if val, ok := req.Metadata[metadataDecodeBase64]; ok && val != "" {
merged.DecodeBase64 = utils.IsTruthy(val)
merged.DecodeBase64 = strings.IsTruthy(val)
}
if val, ok := req.Metadata[metadataEncodeBase64]; ok && val != "" {
merged.EncodeBase64 = utils.IsTruthy(val)
merged.EncodeBase64 = strings.IsTruthy(val)
}
if val, ok := req.Metadata[metadataSignTTL]; ok && val != "" {
merged.SignTTL = val
@ -348,7 +376,7 @@ func (g *GCPStorage) GetComponentMetadata() (metadataInfo metadata.MetadataMap)
func (g *GCPStorage) sign(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
metadata, err := g.metadata.mergeWithRequestMetadata(req)
if err != nil {
return nil, fmt.Errorf("gcp binding error. error merge metadata : %w", err)
return nil, fmt.Errorf("gcp binding error while merging metadata : %w", err)
}
var key string
@ -371,7 +399,7 @@ func (g *GCPStorage) sign(ctx context.Context, req *bindings.InvokeRequest) (*bi
SignURL: signURL,
})
if err != nil {
return nil, fmt.Errorf("gcp bucket binding error: error marshalling sign response: %w", err)
return nil, fmt.Errorf("gcp bucket binding error while marshalling sign response: %w", err)
}
return &bindings.InvokeResponse{
Data: jsonResponse,
@ -381,7 +409,7 @@ func (g *GCPStorage) sign(ctx context.Context, req *bindings.InvokeRequest) (*bi
func (g *GCPStorage) signObject(bucket, object, ttl string) (string, error) {
d, err := time.ParseDuration(ttl)
if err != nil {
return "", fmt.Errorf("gcp bucket binding error: error parsing signTTL: %w", err)
return "", fmt.Errorf("gcp bucket binding error while parsing signTTL: %w", err)
}
opts := &storage.SignedURLOptions{
Scheme: storage.SigningSchemeV4,
@ -395,3 +423,198 @@ func (g *GCPStorage) signObject(bucket, object, ttl string) (string, error) {
}
return u, nil
}
type objectData struct {
Name string `json:"name"`
Data []byte `json:"data"`
Attrs storage.ObjectAttrs `json:"attrs"`
}
func (g *GCPStorage) bulkGet(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
metadata, err := g.metadata.mergeWithRequestMetadata(req)
if err != nil {
return nil, fmt.Errorf("gcp binding error while merging metadata : %w", err)
}
if g.metadata.Bucket == "" {
return nil, errors.New("gcp bucket binding error: bucket is required")
}
var allObjs []*storage.ObjectAttrs
it := g.client.Bucket(g.metadata.Bucket).Objects(ctx, nil)
for {
attrs, err2 := it.Next()
if err2 == iterator.Done {
break
}
allObjs = append(allObjs, attrs)
}
var wg sync.WaitGroup
objectsCh := make(chan objectData, len(allObjs))
errCh := make(chan error, len(allObjs))
for i, obj := range allObjs {
wg.Add(1)
go func(idx int, object *storage.ObjectAttrs) {
defer wg.Done()
rc, err3 := g.client.Bucket(g.metadata.Bucket).Object(object.Name).NewReader(ctx)
if err3 != nil {
errCh <- err3
return
}
defer rc.Close()
data, readErr := io.ReadAll(rc)
if readErr != nil {
errCh <- readErr
return
}
if metadata.EncodeBase64 {
encoded := b64.StdEncoding.EncodeToString(data)
data = []byte(encoded)
}
objectsCh <- objectData{
Name: object.Name,
Data: data,
Attrs: *object,
}
}(i, obj)
}
wg.Wait()
close(errCh)
var multiErr error
for err := range errCh {
multierr.AppendInto(&multiErr, err)
}
if multiErr != nil {
return nil, multiErr
}
response := make([]objectData, 0, len(allObjs))
for obj := range objectsCh {
response = append(response, obj)
}
jsonResponse, err := json.Marshal(response)
if err != nil {
return nil, fmt.Errorf("gcp bucket binding error while marshalling bulk get response: %w", err)
}
return &bindings.InvokeResponse{
Data: jsonResponse,
}, nil
}
type movePayload struct {
DestinationBucket string `json:"destinationBucket"`
}
func (g *GCPStorage) move(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
var key string
if val, ok := req.Metadata[metadataKey]; ok && val != "" {
key = val
} else {
return nil, errors.New("gcp bucket binding error: can't read key value")
}
var payload movePayload
err := json.Unmarshal(req.Data, &payload)
if err != nil {
return nil, errors.New("gcp bucket binding error: invalid move payload")
}
if payload.DestinationBucket == "" {
return nil, errors.New("gcp bucket binding error: required 'destinationBucket' missing")
}
src := g.client.Bucket(g.metadata.Bucket).Object(key)
dst := g.client.Bucket(payload.DestinationBucket).Object(key)
if _, err := dst.CopierFrom(src).Run(ctx); err != nil {
return nil, fmt.Errorf("gcp bucket binding error while copying object: %w", err)
}
if err := src.Delete(ctx); err != nil {
return nil, fmt.Errorf("gcp bucket binding error while deleting object: %w", err)
}
return &bindings.InvokeResponse{
Data: []byte(fmt.Sprintf("object %s moved to %s", key, payload.DestinationBucket)),
}, nil
}
type renamePayload struct {
NewName string `json:"newName"`
}
func (g *GCPStorage) rename(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
var key string
if val, ok := req.Metadata[metadataKey]; ok && val != "" {
key = val
} else {
return nil, errors.New("gcp bucket binding error: can't read key value")
}
var payload renamePayload
err := json.Unmarshal(req.Data, &payload)
if err != nil {
return nil, errors.New("gcp bucket binding error: invalid rename payload")
}
if payload.NewName == "" {
return nil, errors.New("gcp bucket binding error: required 'newName' missing")
}
src := g.client.Bucket(g.metadata.Bucket).Object(key)
dst := g.client.Bucket(g.metadata.Bucket).Object(payload.NewName)
if _, err := dst.CopierFrom(src).Run(ctx); err != nil {
return nil, fmt.Errorf("gcp bucket binding error while copying object: %w", err)
}
if err := src.Delete(ctx); err != nil {
return nil, fmt.Errorf("gcp bucket binding error while deleting object: %w", err)
}
return &bindings.InvokeResponse{
Data: []byte(fmt.Sprintf("object %s renamed to %s", key, payload.NewName)),
}, nil
}
type copyPayload struct {
DestinationBucket string `json:"destinationBucket"`
}
func (g *GCPStorage) copy(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
var key string
if val, ok := req.Metadata[metadataKey]; ok && val != "" {
key = val
} else {
return nil, errors.New("gcp bucket binding error: can't read key value")
}
var payload copyPayload
err := json.Unmarshal(req.Data, &payload)
if err != nil {
return nil, errors.New("gcp bucket binding error: invalid copy payload")
}
if payload.DestinationBucket == "" {
return nil, errors.New("gcp bucket binding error: required 'destinationBucket' missing")
}
src := g.client.Bucket(g.metadata.Bucket).Object(key)
dst := g.client.Bucket(payload.DestinationBucket).Object(key)
if _, err := dst.CopierFrom(src).Run(ctx); err != nil {
return nil, fmt.Errorf("gcp bucket binding error while copying object: %w", err)
}
return &bindings.InvokeResponse{
Data: []byte(fmt.Sprintf("object %s copied to %s", key, payload.DestinationBucket)),
}, nil
}

View File

@ -14,7 +14,6 @@ limitations under the License.
package bucket
import (
"context"
"encoding/json"
"testing"
@ -64,7 +63,7 @@ func TestParseMetadata(t *testing.T) {
t.Run("Metadata is correctly marshalled to JSON", func(t *testing.T) {
json, err := json.Marshal(meta)
require.NoError(t, err)
assert.Equal(t,
assert.JSONEq(t,
"{\"type\":\"my_type\",\"project_id\":\"my_project_id\",\"private_key_id\":\"my_private_key_id\","+
"\"private_key\":\"my_private_key\",\"client_email\":\"my_email@mail.dapr\",\"client_id\":\"my_client_id\","+
"\"auth_uri\":\"my_auth_uri\",\"token_uri\":\"my_token_uri\",\"auth_provider_x509_cert_url\":\"my_auth_provider_x509\","+
@ -240,7 +239,7 @@ func TestGetOption(t *testing.T) {
gs.metadata = &gcpMetadata{}
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := gs.get(context.TODO(), &r)
_, err := gs.get(t.Context(), &r)
require.Error(t, err)
})
}
@ -251,7 +250,127 @@ func TestDeleteOption(t *testing.T) {
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := gs.delete(context.TODO(), &r)
_, err := gs.delete(t.Context(), &r)
require.Error(t, err)
})
}
func TestBulkGetOption(t *testing.T) {
gs := GCPStorage{logger: logger.NewLogger("test")}
gs.metadata = &gcpMetadata{}
t.Run("return error if bucket is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := gs.bulkGet(t.Context(), &r)
require.Error(t, err)
})
}
func TestCopyOption(t *testing.T) {
gs := GCPStorage{logger: logger.NewLogger("test")}
gs.metadata = &gcpMetadata{}
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{}
_, err := gs.copy(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: can't read key value", err.Error())
})
t.Run("return error if data is not valid json", func(t *testing.T) {
r := bindings.InvokeRequest{
Metadata: map[string]string{
"key": "my_key",
},
}
_, err := gs.copy(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: invalid copy payload", err.Error())
})
t.Run("return error if destinationBucket is missing", func(t *testing.T) {
r := bindings.InvokeRequest{
Data: []byte(`{}`),
Metadata: map[string]string{
"key": "my_key",
},
}
_, err := gs.copy(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: required 'destinationBucket' missing", err.Error())
})
}
func TestRenameOption(t *testing.T) {
gs := GCPStorage{logger: logger.NewLogger("test")}
gs.metadata = &gcpMetadata{}
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{
Data: []byte(`{"newName": "my_new_name"}`),
}
_, err := gs.rename(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: can't read key value", err.Error())
})
t.Run("return error if data is not valid json", func(t *testing.T) {
r := bindings.InvokeRequest{
Metadata: map[string]string{
"key": "my_key",
},
}
_, err := gs.rename(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: invalid rename payload", err.Error())
})
t.Run("return error if newName is missing", func(t *testing.T) {
r := bindings.InvokeRequest{
Data: []byte(`{}`),
Metadata: map[string]string{
"key": "my_key",
},
}
_, err := gs.rename(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: required 'newName' missing", err.Error())
})
}
func TestMoveOption(t *testing.T) {
gs := GCPStorage{logger: logger.NewLogger("test")}
gs.metadata = &gcpMetadata{}
t.Run("return error if key is missing", func(t *testing.T) {
r := bindings.InvokeRequest{
Data: []byte(`{"destinationBucket": "my_bucket"}`),
}
_, err := gs.move(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: can't read key value", err.Error())
})
t.Run("return error if data is not valid json", func(t *testing.T) {
r := bindings.InvokeRequest{
Metadata: map[string]string{
"key": "my_key",
},
}
_, err := gs.move(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: invalid move payload", err.Error())
})
t.Run("return error if destinationBucket is missing", func(t *testing.T) {
r := bindings.InvokeRequest{
Data: []byte(`{}`),
Metadata: map[string]string{
"key": "my_key",
},
}
_, err := gs.move(t.Context(), &r)
require.Error(t, err)
assert.Equal(t, "gcp bucket binding error: required 'destinationBucket' missing", err.Error())
})
}

View File

@ -108,6 +108,6 @@ func TestGraphQlRequestHeadersAndVariables(t *testing.T) {
"variable:episode": "JEDI",
},
}
_, err = gql.Invoke(context.Background(), req)
_, err = gql.Invoke(t.Context(), req)
require.NoError(t, err)
}

View File

@ -34,7 +34,7 @@ import (
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/kit/logger"
kitmd "github.com/dapr/kit/metadata"
"github.com/dapr/kit/utils"
kitstrings "github.com/dapr/kit/strings"
)
const (
@ -44,6 +44,7 @@ const (
TraceparentHeaderKey = "traceparent"
TracestateHeaderKey = "tracestate"
BaggageHeaderKey = "baggage"
TraceMetadataKey = "traceHeaders"
securityToken = "securityToken"
securityTokenHeader = "securityTokenHeader"
@ -136,7 +137,7 @@ func (h *HTTPSource) Init(_ context.Context, meta bindings.Metadata) error {
}
if val := meta.Properties["errorIfNot2XX"]; val != "" {
h.errorIfNot2XX = utils.IsTruthy(val)
h.errorIfNot2XX = kitstrings.IsTruthy(val)
} else {
// Default behavior
h.errorIfNot2XX = true
@ -251,7 +252,7 @@ func (h *HTTPSource) Invoke(parentCtx context.Context, req *bindings.InvokeReque
u = strings.TrimRight(u, "/") + "/" + strings.TrimLeft(req.Metadata["path"], "/")
}
if req.Metadata["errorIfNot2XX"] != "" {
errorIfNot2XX = utils.IsTruthy(req.Metadata["errorIfNot2XX"])
errorIfNot2XX = kitstrings.IsTruthy(req.Metadata["errorIfNot2XX"])
}
var body io.Reader
@ -318,6 +319,13 @@ func (h *HTTPSource) Invoke(parentCtx context.Context, req *bindings.InvokeReque
request.Header.Set(TracestateHeaderKey, ts)
}
if baggage, ok := req.Metadata[BaggageHeaderKey]; ok && baggage != "" {
if _, ok := request.Header[http.CanonicalHeaderKey(BaggageHeaderKey)]; ok {
h.logger.Warn("Tracing is enabled. A custom Baggage request header cannot be specified and is ignored.")
}
request.Header.Set(BaggageHeaderKey, baggage)
}
// Send the question
resp, err := h.client.Do(request)

View File

@ -439,7 +439,7 @@ func TestSecurityTokenHeaderForwarded(t *testing.T) {
err: "",
statusCode: 200,
}.ToInvokeRequest()
_, err = hs.Invoke(context.Background(), &req)
_, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
assert.Equal(t, "12345", handler.Headers["X-Token"])
})
@ -455,7 +455,7 @@ func TestSecurityTokenHeaderForwarded(t *testing.T) {
err: "",
statusCode: 200,
}.ToInvokeRequest()
_, err = hs.Invoke(context.Background(), &req)
_, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
assert.Empty(t, handler.Headers["X-Token"])
})
@ -473,47 +473,51 @@ func TestTraceHeadersForwarded(t *testing.T) {
req := TestCase{
input: "GET",
operation: "get",
metadata: map[string]string{"path": "/", "traceparent": "12345", "tracestate": "67890"},
metadata: map[string]string{"path": "/", "traceparent": "12345", "tracestate": "67890", "baggage": "key1=value1"},
path: "/",
err: "",
statusCode: 200,
}.ToInvokeRequest()
_, err = hs.Invoke(context.Background(), &req)
_, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
assert.Equal(t, "12345", handler.Headers["Traceparent"])
assert.Equal(t, "67890", handler.Headers["Tracestate"])
assert.Equal(t, "key1=value1", handler.Headers["Baggage"])
})
t.Run("trace headers should not be forwarded if empty", func(t *testing.T) {
req := TestCase{
input: "GET",
operation: "get",
metadata: map[string]string{"path": "/", "traceparent": "", "tracestate": ""},
metadata: map[string]string{"path": "/", "traceparent": "", "tracestate": "", "baggage": ""},
path: "/",
err: "",
statusCode: 200,
}.ToInvokeRequest()
_, err = hs.Invoke(context.Background(), &req)
_, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
_, traceParentExists := handler.Headers["Traceparent"]
assert.False(t, traceParentExists)
_, traceStateExists := handler.Headers["Tracestate"]
assert.False(t, traceStateExists)
_, baggageExists := handler.Headers["Baggage"]
assert.False(t, baggageExists)
})
t.Run("trace headers override headers in request metadata", func(t *testing.T) {
req := TestCase{
input: "GET",
operation: "get",
metadata: map[string]string{"path": "/", "Traceparent": "abcde", "Tracestate": "fghijk", "traceparent": "12345", "tracestate": "67890"},
metadata: map[string]string{"path": "/", "Traceparent": "abcde", "Tracestate": "fghijk", "Baggage": "oldvalue", "traceparent": "12345", "tracestate": "67890", "baggage": "key1=value1"},
path: "/",
err: "",
statusCode: 200,
}.ToInvokeRequest()
_, err = hs.Invoke(context.Background(), &req)
_, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
assert.Equal(t, "12345", handler.Headers["Traceparent"])
assert.Equal(t, "67890", handler.Headers["Tracestate"])
assert.Equal(t, "key1=value1", handler.Headers["Baggage"])
})
}
@ -624,7 +628,7 @@ func TestHTTPSBinding(t *testing.T) {
err: "",
statusCode: 200,
}.ToInvokeRequest()
response, err := hs.Invoke(context.Background(), &req)
response, err := hs.Invoke(t.Context(), &req)
require.NoError(t, err)
peerCerts, err := strconv.Atoi(string(response.Data))
require.NoError(t, err)
@ -638,7 +642,7 @@ func TestHTTPSBinding(t *testing.T) {
err: "",
statusCode: 201,
}.ToInvokeRequest()
response, err = hs.Invoke(context.Background(), &req)
response, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
peerCerts, err = strconv.Atoi(string(response.Data))
require.NoError(t, err)
@ -657,7 +661,7 @@ func TestHTTPSBinding(t *testing.T) {
err: "",
statusCode: 200,
}.ToInvokeRequest()
_, err = hs.Invoke(context.Background(), &req)
_, err = hs.Invoke(t.Context(), &req)
require.Error(t, err)
})
@ -677,7 +681,7 @@ func TestHTTPSBinding(t *testing.T) {
err: "",
statusCode: 200,
}.ToInvokeRequest()
response, err := hs.Invoke(context.Background(), &req)
response, err := hs.Invoke(t.Context(), &req)
require.NoError(t, err)
peerCerts, err := strconv.Atoi(string(response.Data))
require.NoError(t, err)
@ -694,7 +698,7 @@ func TestHTTPSBinding(t *testing.T) {
err: "",
statusCode: 201,
}.ToInvokeRequest()
response, err = hs.Invoke(context.Background(), &req)
response, err = hs.Invoke(t.Context(), &req)
require.NoError(t, err)
peerCerts, err = strconv.Atoi(string(response.Data))
require.NoError(t, err)
@ -851,7 +855,7 @@ func verifyDefaultBehaviors(t *testing.T, hs bindings.OutputBinding, handler *HT
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
req := tc.ToInvokeRequest()
response, err := hs.Invoke(context.Background(), &req)
response, err := hs.Invoke(t.Context(), &req)
if tc.err == "" {
require.NoError(t, err)
assert.Equal(t, tc.path, handler.Path)
@ -915,7 +919,7 @@ func verifyNon2XXErrorsSuppressed(t *testing.T, hs bindings.OutputBinding, handl
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
req := tc.ToInvokeRequest()
response, err := hs.Invoke(context.Background(), &req)
response, err := hs.Invoke(t.Context(), &req)
if tc.err == "" {
require.NoError(t, err)
assert.Equal(t, tc.path, handler.Path)
@ -965,7 +969,7 @@ func verifyTimeoutBehavior(t *testing.T, hs bindings.OutputBinding, handler *HTT
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
req := tc.ToInvokeRequest()
response, err := hs.Invoke(context.Background(), &req)
response, err := hs.Invoke(t.Context(), &req)
if tc.err == "" {
require.NoError(t, err)
assert.Equal(t, tc.path, handler.Path)
@ -999,7 +1003,7 @@ func TestMaxBodySizeHonored(t *testing.T) {
}
req := tc.ToInvokeRequest()
response, err := hs.Invoke(context.Background(), &req)
response, err := hs.Invoke(t.Context(), &req)
require.NoError(t, err)
// Should have only read 1KB

View File

@ -94,7 +94,7 @@ func TestInit(t *testing.T) {
"accessKey": "dummy-ak",
"secretKey": "dummy-sk",
}
err := obs.Init(context.Background(), m)
err := obs.Init(t.Context(), m)
require.NoError(t, err)
})
t.Run("Init with missing bucket name", func(t *testing.T) {
@ -104,7 +104,7 @@ func TestInit(t *testing.T) {
"accessKey": "dummy-ak",
"secretKey": "dummy-sk",
}
err := obs.Init(context.Background(), m)
err := obs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing obs bucket name"))
})
@ -115,7 +115,7 @@ func TestInit(t *testing.T) {
"endpoint": "dummy-endpoint",
"secretKey": "dummy-sk",
}
err := obs.Init(context.Background(), m)
err := obs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing the huawei access key"))
})
@ -126,7 +126,7 @@ func TestInit(t *testing.T) {
"endpoint": "dummy-endpoint",
"accessKey": "dummy-ak",
}
err := obs.Init(context.Background(), m)
err := obs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing the huawei secret key"))
})
@ -137,7 +137,7 @@ func TestInit(t *testing.T) {
"accessKey": "dummy-ak",
"secretKey": "dummy-sk",
}
err := obs.Init(context.Background(), m)
err := obs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing obs endpoint"))
})
@ -178,7 +178,7 @@ func TestCreateOperation(t *testing.T) {
Data: []byte(`"Hello OBS"`),
}
out, err := mo.create(context.Background(), req)
out, err := mo.create(t.Context(), req)
require.NoError(t, err)
var data createResponse
@ -209,7 +209,7 @@ func TestCreateOperation(t *testing.T) {
Data: []byte(`"Hello OBS"`),
}
out, err := mo.create(context.Background(), req)
out, err := mo.create(t.Context(), req)
require.NoError(t, err)
var data createResponse
@ -242,7 +242,7 @@ func TestCreateOperation(t *testing.T) {
},
}
_, err := mo.create(context.Background(), req)
_, err := mo.create(t.Context(), req)
require.NoError(t, err)
})
@ -267,7 +267,7 @@ func TestCreateOperation(t *testing.T) {
Data: []byte(`"Hello OBS"`),
}
_, err := mo.create(context.Background(), req)
_, err := mo.create(t.Context(), req)
require.Error(t, err)
})
}
@ -298,7 +298,7 @@ func TestUploadOperation(t *testing.T) {
Data: []byte(`{"sourceFile": "dummy-path"}`),
}
out, err := mo.upload(context.Background(), req)
out, err := mo.upload(t.Context(), req)
require.NoError(t, err)
var data createResponse
@ -329,7 +329,7 @@ func TestUploadOperation(t *testing.T) {
Data: []byte(`{"sourceFile": "dummy-path"}`),
}
out, err := mo.upload(context.Background(), req)
out, err := mo.upload(t.Context(), req)
require.NoError(t, err)
var data createResponse
@ -359,7 +359,7 @@ func TestUploadOperation(t *testing.T) {
Data: []byte(`{"sourceFile": "dummy-path"}`),
}
_, err := mo.upload(context.Background(), req)
_, err := mo.upload(t.Context(), req)
require.Error(t, err)
})
}
@ -393,7 +393,7 @@ func TestGetOperation(t *testing.T) {
},
}
_, err := mo.get(context.Background(), req)
_, err := mo.get(t.Context(), req)
require.NoError(t, err)
})
@ -410,7 +410,7 @@ func TestGetOperation(t *testing.T) {
Operation: "get",
}
_, err := mo.get(context.Background(), req)
_, err := mo.get(t.Context(), req)
require.Error(t, err)
})
@ -434,7 +434,7 @@ func TestGetOperation(t *testing.T) {
},
}
_, err := mo.get(context.Background(), req)
_, err := mo.get(t.Context(), req)
require.Error(t, err)
})
@ -466,7 +466,7 @@ func TestGetOperation(t *testing.T) {
},
}
_, err := mo.get(context.Background(), req)
_, err := mo.get(t.Context(), req)
require.Error(t, err)
})
}
@ -496,7 +496,7 @@ func TestDeleteOperation(t *testing.T) {
},
}
out, err := mo.delete(context.Background(), req)
out, err := mo.delete(t.Context(), req)
require.NoError(t, err)
var data createResponse
@ -518,7 +518,7 @@ func TestDeleteOperation(t *testing.T) {
Operation: "delete",
}
_, err := mo.delete(context.Background(), req)
_, err := mo.delete(t.Context(), req)
require.Error(t, err)
})
@ -542,7 +542,7 @@ func TestDeleteOperation(t *testing.T) {
},
}
_, err := mo.delete(context.Background(), req)
_, err := mo.delete(t.Context(), req)
require.Error(t, err)
})
}
@ -573,7 +573,7 @@ func TestListOperation(t *testing.T) {
Data: []byte("{\"maxResults\": 10}"),
}
_, err := mo.list(context.Background(), req)
_, err := mo.list(t.Context(), req)
require.NoError(t, err)
})
@ -598,7 +598,7 @@ func TestListOperation(t *testing.T) {
Data: []byte("{\"maxResults\": 10}"),
}
_, err := mo.list(context.Background(), req)
_, err := mo.list(t.Context(), req)
require.Error(t, err)
})
@ -627,7 +627,7 @@ func TestListOperation(t *testing.T) {
Data: []byte("{\"key\": \"value\"}"),
}
_, err := mo.list(context.Background(), req)
_, err := mo.list(t.Context(), req)
require.NoError(t, err)
})
}
@ -654,7 +654,7 @@ func TestInvoke(t *testing.T) {
Operation: "create",
}
_, err := mo.Invoke(context.Background(), req)
_, err := mo.Invoke(t.Context(), req)
require.NoError(t, err)
})
@ -686,7 +686,7 @@ func TestInvoke(t *testing.T) {
},
}
_, err := mo.Invoke(context.Background(), req)
_, err := mo.Invoke(t.Context(), req)
require.NoError(t, err)
})
@ -714,7 +714,7 @@ func TestInvoke(t *testing.T) {
},
}
_, err := mo.Invoke(context.Background(), req)
_, err := mo.Invoke(t.Context(), req)
require.NoError(t, err)
})
@ -743,7 +743,7 @@ func TestInvoke(t *testing.T) {
Data: []byte("{\"maxResults\": 10}"),
}
_, err := mo.Invoke(context.Background(), req)
_, err := mo.Invoke(t.Context(), req)
require.NoError(t, err)
})
@ -760,7 +760,7 @@ func TestInvoke(t *testing.T) {
Operation: "unknown",
}
_, err := mo.Invoke(context.Background(), req)
_, err := mo.Invoke(t.Context(), req)
require.Error(t, err)
})
}

View File

@ -167,7 +167,7 @@ func (mr *MockQueryAPIMockRecorder) QueryRawWithParams(arg0, arg1, arg2, arg3 in
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryRawWithParams", reflect.TypeOf((*MockQueryAPI)(nil).QueryRaw), arg0, arg1, arg2, arg3)
}
// QueryWithParams executes flux parametrized query on the InfluxDB server and returns QueryTableResult which parses streamed response into structures representing flux table parts
func (m *MockQueryAPI) QueryWithParams(ctx context.Context, query string, params interface{}) (*api.QueryTableResult, error) {
m.ctrl.T.Helper()
@ -181,4 +181,4 @@ func (m *MockQueryAPI) QueryWithParams(ctx context.Context, query string, params
func (mr *MockQueryAPIMockRecorder) QueryWithParams(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryWithParams", reflect.TypeOf((*MockQueryAPI)(nil).QueryWithParams), arg0, arg1, arg2)
}
}

View File

@ -14,7 +14,6 @@ limitations under the License.
package influx
import (
"context"
"testing"
"github.com/golang/mock/gomock"
@ -55,7 +54,7 @@ func TestInflux_Init(t *testing.T) {
assert.Nil(t, influx.client)
m := bindings.Metadata{Base: metadata.Base{Properties: map[string]string{"Url": "a", "Token": "a", "Org": "a", "Bucket": "a"}}}
err := influx.Init(context.Background(), m)
err := influx.Init(t.Context(), m)
require.NoError(t, err)
assert.NotNil(t, influx.queryAPI)
@ -90,12 +89,12 @@ func TestInflux_Invoke_BindingCreateOperation(t *testing.T) {
defer ctrl.Finish()
w := NewMockWriteAPIBlocking(ctrl)
w.EXPECT().WriteRecord(gomock.Eq(context.TODO()), gomock.Eq("a,a a")).Return(nil)
w.EXPECT().WriteRecord(gomock.Eq(t.Context()), gomock.Eq("a,a a")).Return(nil)
influx := &Influx{
writeAPI: w,
}
for _, test := range tests {
resp, err := influx.Invoke(context.TODO(), test.request)
resp, err := influx.Invoke(t.Context(), test.request)
assert.Equal(t, test.want.resp, resp)
assert.Equal(t, test.want.err, err)
}
@ -117,7 +116,7 @@ func TestInflux_Invoke_BindingInvalidOperation(t *testing.T) {
}
for _, test := range tests {
resp, err := (*Influx)(nil).Invoke(context.TODO(), test.request)
resp, err := (*Influx)(nil).Invoke(t.Context(), test.request)
assert.Equal(t, test.want.resp, resp)
assert.Equal(t, test.want.err, err)
}
@ -153,13 +152,13 @@ func TestInflux_Invoke_BindingQueryOperation(t *testing.T) {
defer ctrl.Finish()
q := NewMockQueryAPI(ctrl)
q.EXPECT().QueryRaw(gomock.Eq(context.TODO()), gomock.Eq("a"), gomock.Eq(influxdb2.DefaultDialect())).Return("ok", nil)
q.EXPECT().QueryRaw(gomock.Eq(t.Context()), gomock.Eq("a"), gomock.Eq(influxdb2.DefaultDialect())).Return("ok", nil)
influx := &Influx{
queryAPI: q,
logger: logger.NewLogger("test"),
}
for _, test := range tests {
resp, err := influx.Invoke(context.TODO(), test.request)
resp, err := influx.Invoke(t.Context(), test.request)
assert.Equal(t, test.want.resp, resp)
assert.Equal(t, test.want.err, err)
}

View File

@ -352,3 +352,12 @@ metadata:
It allows sending headers with special characters that are usually not allowed in HTTP headers.
example: "true"
default: "false"
- name: compression
type: string
required: false
description: |
Enables message compression.
There are five types of compression available: none, gzip, snappy, lz4, and zstd.
The default is none.
example: '"gzip"'
default: "none"

View File

@ -14,7 +14,6 @@ limitations under the License.
package kitex
import (
"context"
"testing"
"time"
@ -61,7 +60,7 @@ func TestInvoke(t *testing.T) {
metadataRPCMethodName: MethodName,
}
resp, err := output.Invoke(context.Background(), &bindings.InvokeRequest{
resp, err := output.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: metadata,
Data: reqData,
Operation: bindings.GetOperation,

View File

@ -106,7 +106,7 @@ func Test_kubeMQ_Init(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
kubemq := NewKubeMQ(logger.NewLogger("test"))
err := kubemq.Init(context.Background(), tt.meta)
err := kubemq.Init(t.Context(), tt.meta)
if tt.wantErr {
require.Error(t, err)
} else {
@ -117,10 +117,10 @@ func Test_kubeMQ_Init(t *testing.T) {
}
func Test_kubeMQ_Invoke_Read_Single_Message(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ctx, cancel := context.WithTimeout(t.Context(), time.Second*5)
defer cancel()
kubemq := NewKubeMQ(logger.NewLogger("test"))
err := kubemq.Init(context.Background(), getDefaultMetadata("test.read.single"))
err := kubemq.Init(t.Context(), getDefaultMetadata("test.read.single"))
require.NoError(t, err)
dataReadCh := make(chan []byte)
invokeRequest := &bindings.InvokeRequest{
@ -142,12 +142,12 @@ func Test_kubeMQ_Invoke_Read_Single_Message(t *testing.T) {
}
func Test_kubeMQ_Invoke_Read_Single_MessageWithHandlerError(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
ctx, cancel := context.WithTimeout(t.Context(), time.Second*10)
defer cancel()
kubemq := NewKubeMQ(logger.NewLogger("test"))
md := getDefaultMetadata("test.read.single.error")
md.Properties["autoAcknowledged"] = "false"
err := kubemq.Init(context.Background(), md)
err := kubemq.Init(t.Context(), md)
require.NoError(t, err)
invokeRequest := &bindings.InvokeRequest{
Data: []byte("test"),
@ -156,7 +156,7 @@ func Test_kubeMQ_Invoke_Read_Single_MessageWithHandlerError(t *testing.T) {
_, err = kubemq.Invoke(ctx, invokeRequest)
require.NoError(t, err)
firstReadCtx, firstReadCancel := context.WithTimeout(context.Background(), time.Second*3)
firstReadCtx, firstReadCancel := context.WithTimeout(t.Context(), time.Second*3)
defer firstReadCancel()
_ = kubemq.Read(firstReadCtx, func(ctx context.Context, req *bindings.ReadResponse) ([]byte, error) {
return nil, fmt.Errorf("handler error")
@ -164,7 +164,7 @@ func Test_kubeMQ_Invoke_Read_Single_MessageWithHandlerError(t *testing.T) {
<-firstReadCtx.Done()
dataReadCh := make(chan []byte)
secondReadCtx, secondReadCancel := context.WithTimeout(context.Background(), time.Second*3)
secondReadCtx, secondReadCancel := context.WithTimeout(t.Context(), time.Second*3)
defer secondReadCancel()
_ = kubemq.Read(secondReadCtx, func(ctx context.Context, req *bindings.ReadResponse) ([]byte, error) {
dataReadCh <- req.Data
@ -179,10 +179,10 @@ func Test_kubeMQ_Invoke_Read_Single_MessageWithHandlerError(t *testing.T) {
}
func Test_kubeMQ_Invoke_Error(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ctx, cancel := context.WithTimeout(t.Context(), time.Second*5)
defer cancel()
kubemq := NewKubeMQ(logger.NewLogger("test"))
err := kubemq.Init(context.Background(), getDefaultMetadata("***test***"))
err := kubemq.Init(t.Context(), getDefaultMetadata("***test***"))
require.NoError(t, err)
invokeRequest := &bindings.InvokeRequest{

View File

@ -16,7 +16,6 @@ limitations under the License.
package mqtt
import (
"context"
"os"
"testing"
"time"
@ -50,7 +49,7 @@ func getConnectionString() string {
func TestInvokeWithTopic(t *testing.T) {
t.Parallel()
ctx := context.Background()
ctx := t.Context()
url := getConnectionString()
if url == "" {
@ -106,7 +105,7 @@ func TestInvokeWithTopic(t *testing.T) {
}()
// Test invoke with default topic configured for component.
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{Data: dataDefault})
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{Data: dataDefault})
require.NoError(t, err)
m := <-msgCh
@ -116,7 +115,7 @@ func TestInvokeWithTopic(t *testing.T) {
assert.Equal(t, topicDefault, mqttMessage.Topic())
// Test invoke with customized topic.
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{
Data: dataCustomized,
Metadata: map[string]string{
mqttTopic: topicCustomized,

View File

@ -14,7 +14,6 @@ limitations under the License.
package mysql
import (
"context"
"encoding/json"
"fmt"
"os"
@ -60,13 +59,13 @@ func TestMysqlIntegration(t *testing.T) {
b := NewMysql(logger.NewLogger("test")).(*Mysql)
m := bindings.Metadata{Base: metadata.Base{Properties: map[string]string{connectionURLKey: url}}}
err := b.Init(context.Background(), m)
err := b.Init(t.Context(), m)
require.NoError(t, err)
defer b.Close()
t.Run("Invoke create table", func(t *testing.T) {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: execOperation,
Metadata: map[string]string{
commandSQLKey: `CREATE TABLE IF NOT EXISTS foo (
@ -81,7 +80,7 @@ func TestMysqlIntegration(t *testing.T) {
})
t.Run("Invoke delete", func(t *testing.T) {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: execOperation,
Metadata: map[string]string{
commandSQLKey: "DELETE FROM foo",
@ -92,7 +91,7 @@ func TestMysqlIntegration(t *testing.T) {
t.Run("Invoke insert", func(t *testing.T) {
for i := range 10 {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: execOperation,
Metadata: map[string]string{
commandSQLKey: fmt.Sprintf(
@ -107,7 +106,7 @@ func TestMysqlIntegration(t *testing.T) {
t.Run("Invoke update", func(t *testing.T) {
date := time.Now().Add(time.Hour)
for i := range 10 {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: execOperation,
Metadata: map[string]string{
commandSQLKey: fmt.Sprintf(
@ -123,7 +122,7 @@ func TestMysqlIntegration(t *testing.T) {
t.Run("Invoke update with parameters", func(t *testing.T) {
date := time.Now().Add(2 * time.Hour)
for i := range 10 {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: execOperation,
Metadata: map[string]string{
commandSQLKey: "UPDATE foo SET ts = ? WHERE id = ?",
@ -136,7 +135,7 @@ func TestMysqlIntegration(t *testing.T) {
})
t.Run("Invoke select", func(t *testing.T) {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: queryOperation,
Metadata: map[string]string{
commandSQLKey: "SELECT * FROM foo WHERE id < 3",
@ -167,7 +166,7 @@ func TestMysqlIntegration(t *testing.T) {
})
t.Run("Invoke select with parameters", func(t *testing.T) {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: queryOperation,
Metadata: map[string]string{
commandSQLKey: "SELECT * FROM foo WHERE id = ?",
@ -190,7 +189,7 @@ func TestMysqlIntegration(t *testing.T) {
})
t.Run("Invoke drop", func(t *testing.T) {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
res, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: execOperation,
Metadata: map[string]string{
commandSQLKey: "DROP TABLE foo",
@ -200,7 +199,7 @@ func TestMysqlIntegration(t *testing.T) {
})
t.Run("Invoke close", func(t *testing.T) {
_, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := b.Invoke(t.Context(), &bindings.InvokeRequest{
Operation: closeOperation,
})
require.NoError(t, err)

View File

@ -14,7 +14,6 @@ limitations under the License.
package mysql
import (
"context"
"encoding/json"
"errors"
"testing"
@ -39,7 +38,7 @@ func TestQuery(t *testing.T) {
AddRow(3, "value-3", time.Now().Add(2000))
mock.ExpectQuery("SELECT \\* FROM foo WHERE id < 4").WillReturnRows(rows)
ret, err := m.query(context.Background(), `SELECT * FROM foo WHERE id < 4`)
ret, err := m.query(t.Context(), `SELECT * FROM foo WHERE id < 4`)
require.NoError(t, err)
t.Logf("query result: %s", ret)
assert.Contains(t, string(ret), "\"id\":1")
@ -58,7 +57,7 @@ func TestQuery(t *testing.T) {
AddRow(2, 2.2, time.Now().Add(1000)).
AddRow(3, 3.3, time.Now().Add(2000))
mock.ExpectQuery("SELECT \\* FROM foo WHERE id < 4").WillReturnRows(rows)
ret, err := m.query(context.Background(), "SELECT * FROM foo WHERE id < 4")
ret, err := m.query(t.Context(), "SELECT * FROM foo WHERE id < 4")
require.NoError(t, err)
t.Logf("query result: %s", ret)
@ -85,7 +84,7 @@ func TestExec(t *testing.T) {
m, mock, _ := mockDatabase(t)
defer m.Close()
mock.ExpectExec("INSERT INTO foo \\(id, v1, ts\\) VALUES \\(.*\\)").WillReturnResult(sqlmock.NewResult(1, 1))
i, err := m.exec(context.Background(), "INSERT INTO foo (id, v1, ts) VALUES (1, 'test-1', '2021-01-22')")
i, err := m.exec(t.Context(), "INSERT INTO foo (id, v1, ts) VALUES (1, 'test-1', '2021-01-22')")
assert.Equal(t, int64(1), i)
require.NoError(t, err)
}
@ -102,7 +101,7 @@ func TestInvoke(t *testing.T) {
Metadata: metadata,
Operation: execOperation,
}
resp, err := m.Invoke(context.Background(), req)
resp, err := m.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, "1", resp.Metadata[respRowsAffectedKey])
})
@ -115,7 +114,7 @@ func TestInvoke(t *testing.T) {
Metadata: metadata,
Operation: execOperation,
}
resp, err := m.Invoke(context.Background(), req)
resp, err := m.Invoke(t.Context(), req)
assert.Nil(t, resp)
require.Error(t, err)
})
@ -133,7 +132,7 @@ func TestInvoke(t *testing.T) {
Metadata: metadata,
Operation: queryOperation,
}
resp, err := m.Invoke(context.Background(), req)
resp, err := m.Invoke(t.Context(), req)
require.NoError(t, err)
var data []any
err = json.Unmarshal(resp.Data, &data)
@ -149,7 +148,7 @@ func TestInvoke(t *testing.T) {
Metadata: metadata,
Operation: queryOperation,
}
resp, err := m.Invoke(context.Background(), req)
resp, err := m.Invoke(t.Context(), req)
assert.Nil(t, resp)
require.Error(t, err)
})
@ -159,7 +158,7 @@ func TestInvoke(t *testing.T) {
req := &bindings.InvokeRequest{
Operation: closeOperation,
}
resp, _ := m.Invoke(context.Background(), req)
resp, _ := m.Invoke(t.Context(), req)
assert.Nil(t, resp)
})
@ -169,7 +168,7 @@ func TestInvoke(t *testing.T) {
Metadata: map[string]string{},
Operation: "unsupported",
}
resp, err := m.Invoke(context.Background(), req)
resp, err := m.Invoke(t.Context(), req)
assert.Nil(t, resp)
require.Error(t, err)
})

View File

@ -124,3 +124,38 @@ metadata:
- "simple_protocol"
example: "cache_describe"
default: ""
- name: host
required: false
description: The host of the PostgreSQL database
example: "localhost"
type: string
- name: hostaddr
required: false
description: The host address of the PostgreSQL database
example: "127.0.0.1"
type: string
- name: port
required: false
description: The port of the PostgreSQL database
example: "5432"
type: string
- name: database
required: false
description: The database of the PostgreSQL database
example: "postgres"
type: string
- name: user
required: false
description: The user of the PostgreSQL database
example: "postgres"
type: string
- name: password
required: false
description: The password of the PostgreSQL database
example: "password"
type: string
- name: sslRootCert
required: false
description: The path to the SSL root certificate file
example: "/path/to/ssl/root/cert.pem"
type: string

View File

@ -34,7 +34,7 @@ func TestMetadata(t *testing.T) {
t.Run("has connection string", func(t *testing.T) {
m := psqlMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
}
err := m.InitWithMetadata(props)
@ -44,7 +44,7 @@ func TestMetadata(t *testing.T) {
t.Run("default timeout", func(t *testing.T) {
m := psqlMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
}
err := m.InitWithMetadata(props)
@ -55,7 +55,7 @@ func TestMetadata(t *testing.T) {
t.Run("invalid timeout", func(t *testing.T) {
m := psqlMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"timeout": "NaN",
}
@ -66,7 +66,7 @@ func TestMetadata(t *testing.T) {
t.Run("positive timeout", func(t *testing.T) {
m := psqlMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"timeout": "42",
}
@ -78,7 +78,7 @@ func TestMetadata(t *testing.T) {
t.Run("zero timeout", func(t *testing.T) {
m := psqlMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"timeout": "0",
}

View File

@ -14,7 +14,6 @@ limitations under the License.
package postgres
import (
"context"
"errors"
"fmt"
"os"
@ -70,7 +69,7 @@ func TestPostgresIntegration(t *testing.T) {
// live DB test
b := NewPostgres(logger.NewLogger("test")).(*Postgres)
m := bindings.Metadata{Base: metadata.Base{Properties: map[string]string{"connectionString": url}}}
if err := b.Init(context.Background(), m); err != nil {
if err := b.Init(t.Context(), m); err != nil {
t.Fatal(err)
}
@ -79,7 +78,7 @@ func TestPostgresIntegration(t *testing.T) {
Operation: execOperation,
Metadata: map[string]string{commandSQLKey: testTableDDL},
}
ctx := context.TODO()
ctx := t.Context()
t.Run("Invoke create table", func(t *testing.T) {
res, err := b.Invoke(ctx, req)
assertResponse(t, res, err)
@ -165,7 +164,7 @@ func testInitConfiguration(t *testing.T, connectionString string) {
Base: metadata.Base{Properties: tt.props},
}
err := p.Init(context.Background(), metadata)
err := p.Init(t.Context(), metadata)
if tt.expectedErr == nil {
require.NoError(t, err)
} else {

View File

@ -34,7 +34,7 @@ import (
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/kit/logger"
kitmd "github.com/dapr/kit/metadata"
"github.com/dapr/kit/utils"
"github.com/dapr/kit/strings"
)
const (
@ -313,7 +313,7 @@ func (r *RabbitMQ) parseMetadata(meta bindings.Metadata) error {
}
if val, ok := meta.Properties[externalSasl]; ok && val != "" {
m.ExternalSasl = utils.IsTruthy(val)
m.ExternalSasl = strings.IsTruthy(val)
}
if val, ok := meta.Properties[caCert]; ok && val != "" {
@ -336,7 +336,7 @@ func (r *RabbitMQ) parseMetadata(meta bindings.Metadata) error {
}
if val, ok := meta.Properties[externalSasl]; ok && val != "" {
m.ExternalSasl = utils.IsTruthy(val)
m.ExternalSasl = strings.IsTruthy(val)
}
ttl, ok, err := metadata.TryGetTTL(meta.Properties)

View File

@ -86,7 +86,7 @@ func TestQueuesWithTTL(t *testing.T) {
logger := logger.NewLogger("test")
r := NewRabbitMQ(logger).(*RabbitMQ)
err := r.Init(context.Background(), metadata)
err := r.Init(t.Context(), metadata)
require.NoError(t, err)
// Assert that if waited too long, we won't see any message
@ -99,7 +99,7 @@ func TestQueuesWithTTL(t *testing.T) {
defer ch.Close()
const tooLateMsgContent = "too_late_msg"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{Data: []byte(tooLateMsgContent)})
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{Data: []byte(tooLateMsgContent)})
require.NoError(t, err)
time.Sleep(time.Second + (ttlInSeconds * time.Second))
@ -110,7 +110,7 @@ func TestQueuesWithTTL(t *testing.T) {
// Getting before it is expired, should return it
const testMsgContent = "test_msg"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{Data: []byte(testMsgContent)})
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{Data: []byte(testMsgContent)})
require.NoError(t, err)
msg, ok, err := getMessageWithRetries(ch, queueName, maxGetDuration)
@ -150,14 +150,14 @@ func TestQueuesReconnect(t *testing.T) {
logger := logger.NewLogger("test")
r := NewRabbitMQ(logger).(*RabbitMQ)
err := r.Init(context.Background(), metadata)
err := r.Init(t.Context(), metadata)
require.NoError(t, err)
err = r.Read(context.Background(), handler)
err = r.Read(t.Context(), handler)
require.NoError(t, err)
const tooLateMsgContent = "success_msg1"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{Data: []byte(tooLateMsgContent)})
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{Data: []byte(tooLateMsgContent)})
require.NoError(t, err)
// perform a close connection with the rabbitmq server
@ -165,7 +165,7 @@ func TestQueuesReconnect(t *testing.T) {
time.Sleep(3 * defaultReconnectWait)
const testMsgContent = "reconnect_msg"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{Data: []byte(testMsgContent)})
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{Data: []byte(testMsgContent)})
require.NoError(t, err)
time.Sleep(defaultReconnectWait)
@ -199,7 +199,7 @@ func TestPublishingWithTTL(t *testing.T) {
logger := logger.NewLogger("test")
rabbitMQBinding1 := NewRabbitMQ(logger).(*RabbitMQ)
err := rabbitMQBinding1.Init(context.Background(), metadata)
err := rabbitMQBinding1.Init(t.Context(), metadata)
require.NoError(t, err)
// Assert that if waited too long, we won't see any message
@ -219,7 +219,7 @@ func TestPublishingWithTTL(t *testing.T) {
},
}
_, err = rabbitMQBinding1.Invoke(context.Background(), &writeRequest)
_, err = rabbitMQBinding1.Invoke(t.Context(), &writeRequest)
require.NoError(t, err)
time.Sleep(time.Second + (ttlInSeconds * time.Second))
@ -230,7 +230,7 @@ func TestPublishingWithTTL(t *testing.T) {
// Getting before it is expired, should return it
rabbitMQBinding2 := NewRabbitMQ(logger).(*RabbitMQ)
err = rabbitMQBinding2.Init(context.Background(), metadata)
err = rabbitMQBinding2.Init(t.Context(), metadata)
require.NoError(t, err)
const testMsgContent = "test_msg"
@ -240,7 +240,7 @@ func TestPublishingWithTTL(t *testing.T) {
contribMetadata.TTLMetadataKey: strconv.Itoa(ttlInSeconds * 1000),
},
}
_, err = rabbitMQBinding2.Invoke(context.Background(), &writeRequest)
_, err = rabbitMQBinding2.Invoke(t.Context(), &writeRequest)
require.NoError(t, err)
msg, ok, err := getMessageWithRetries(ch, queueName, maxGetDuration)
@ -280,7 +280,7 @@ func TestExclusiveQueue(t *testing.T) {
logger := logger.NewLogger("test")
r := NewRabbitMQ(logger).(*RabbitMQ)
err := r.Init(context.Background(), metadata)
err := r.Init(t.Context(), metadata)
require.NoError(t, err)
// Assert that if waited too long, we won't see any message
@ -334,7 +334,7 @@ func TestPublishWithPriority(t *testing.T) {
logger := logger.NewLogger("test")
r := NewRabbitMQ(logger).(*RabbitMQ)
err := r.Init(context.Background(), metadata)
err := r.Init(t.Context(), metadata)
require.NoError(t, err)
// Assert that if waited too long, we won't see any message
@ -347,7 +347,7 @@ func TestPublishWithPriority(t *testing.T) {
defer ch.Close()
const middlePriorityMsgContent = "middle"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
contribMetadata.PriorityMetadataKey: "5",
},
@ -356,7 +356,7 @@ func TestPublishWithPriority(t *testing.T) {
require.NoError(t, err)
const lowPriorityMsgContent = "low"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
contribMetadata.PriorityMetadataKey: "1",
},
@ -365,7 +365,7 @@ func TestPublishWithPriority(t *testing.T) {
require.NoError(t, err)
const highPriorityMsgContent = "high"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
contribMetadata.PriorityMetadataKey: "10",
},
@ -416,7 +416,7 @@ func TestPublishWithHeaders(t *testing.T) {
logger := logger.NewLogger("test")
r := NewRabbitMQ(logger).(*RabbitMQ)
err := r.Init(context.Background(), metadata)
err := r.Init(t.Context(), metadata)
require.NoError(t, err)
// Assert that if waited too long, we won't see any message
@ -429,7 +429,7 @@ func TestPublishWithHeaders(t *testing.T) {
defer ch.Close()
const msgContent = "some content"
_, err = r.Invoke(context.Background(), &bindings.InvokeRequest{
_, err = r.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{
"custom_header1": "some value",
"custom_header2": "some other value",

View File

@ -14,7 +14,6 @@ limitations under the License.
package redis
import (
"context"
"testing"
"time"
@ -44,10 +43,10 @@ func TestInvokeCreate(t *testing.T) {
logger: logger.NewLogger("test"),
}
_, err := c.DoRead(context.Background(), "GET", testKey)
_, err := c.DoRead(t.Context(), "GET", testKey)
assert.Equal(t, redis.Nil, err)
bindingRes, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
bindingRes, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte(testData),
Metadata: map[string]string{"key": testKey},
Operation: bindings.CreateOperation,
@ -55,9 +54,9 @@ func TestInvokeCreate(t *testing.T) {
require.NoError(t, err)
assert.Nil(t, bindingRes)
getRes, err := c.DoRead(context.Background(), "GET", testKey)
getRes, err := c.DoRead(t.Context(), "GET", testKey)
require.NoError(t, err)
assert.Equal(t, testData, getRes)
assert.JSONEq(t, testData, getRes.(string))
}
func TestInvokeGetWithoutDeleteFlag(t *testing.T) {
@ -69,24 +68,24 @@ func TestInvokeGetWithoutDeleteFlag(t *testing.T) {
logger: logger.NewLogger("test"),
}
err := c.DoWrite(context.Background(), "SET", testKey, testData)
err := c.DoWrite(t.Context(), "SET", testKey, testData)
require.NoError(t, err)
bindingRes, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
bindingRes, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.GetOperation,
})
require.NoError(t, err)
assert.Equal(t, testData, string(bindingRes.Data))
assert.JSONEq(t, testData, string(bindingRes.Data))
bindingResGet, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
bindingResGet, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.GetOperation,
})
require.NoError(t, err)
assert.Equal(t, testData, string(bindingResGet.Data))
assert.JSONEq(t, testData, string(bindingResGet.Data))
}
func TestInvokeGetWithDeleteFlag(t *testing.T) {
@ -98,17 +97,17 @@ func TestInvokeGetWithDeleteFlag(t *testing.T) {
logger: logger.NewLogger("test"),
}
err := c.DoWrite(context.Background(), "SET", testKey, testData)
err := c.DoWrite(t.Context(), "SET", testKey, testData)
require.NoError(t, err)
bindingRes, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
bindingRes, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey, "delete": "true"},
Operation: bindings.GetOperation,
})
require.NoError(t, err)
assert.Equal(t, testData, string(bindingRes.Data))
assert.JSONEq(t, testData, string(bindingRes.Data))
bindingResGet, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
bindingResGet, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.GetOperation,
})
@ -127,21 +126,21 @@ func TestInvokeDelete(t *testing.T) {
logger: logger.NewLogger("test"),
}
err := c.DoWrite(context.Background(), "SET", testKey, testData)
err := c.DoWrite(t.Context(), "SET", testKey, testData)
require.NoError(t, err)
getRes, err := c.DoRead(context.Background(), "GET", testKey)
getRes, err := c.DoRead(t.Context(), "GET", testKey)
require.NoError(t, err)
assert.Equal(t, testData, getRes)
assert.JSONEq(t, testData, getRes.(string))
_, err = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
_, err = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.DeleteOperation,
})
require.NoError(t, err)
rgetRep, err := c.DoRead(context.Background(), "GET", testKey)
rgetRep, err := c.DoRead(t.Context(), "GET", testKey)
assert.Equal(t, redis.Nil, err)
assert.Nil(t, rgetRep)
}
@ -154,35 +153,35 @@ func TestCreateExpire(t *testing.T) {
client: c,
logger: logger.NewLogger("test"),
}
_, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
_, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey, metadata.TTLMetadataKey: "1"},
Operation: bindings.CreateOperation,
Data: []byte(testData),
})
require.NoError(t, err)
rgetRep, err := c.DoRead(context.Background(), "TTL", testKey)
rgetRep, err := c.DoRead(t.Context(), "TTL", testKey)
require.NoError(t, err)
assert.Equal(t, int64(1), rgetRep)
res, err2 := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
res, err2 := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.GetOperation,
})
require.NoError(t, err2)
assert.Equal(t, res.Data, []byte(testData))
assert.JSONEq(t, testData, string(res.Data))
// wait for ttl to expire
s.FastForward(2 * time.Second)
res, err2 = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
res, err2 = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.GetOperation,
})
require.NoError(t, err2)
assert.Equal(t, []byte(nil), res.Data)
_, err = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
_, err = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": testKey},
Operation: bindings.DeleteOperation,
})
@ -197,30 +196,30 @@ func TestIncrement(t *testing.T) {
client: c,
logger: logger.NewLogger("test"),
}
_, err := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
_, err := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": "incKey"},
Operation: IncrementOperation,
})
require.NoError(t, err)
res, err2 := bind.Invoke(context.TODO(), &bindings.InvokeRequest{
res, err2 := bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": "incKey"},
Operation: bindings.GetOperation,
})
assert.Nil(t, nil, err2)
require.NoError(t, err2)
assert.Equal(t, res.Data, []byte("1"))
_, err = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
_, err = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": "incKey", metadata.TTLMetadataKey: "5"},
Operation: IncrementOperation,
})
require.NoError(t, err)
rgetRep, err := c.DoRead(context.Background(), "TTL", "incKey")
rgetRep, err := c.DoRead(t.Context(), "TTL", "incKey")
require.NoError(t, err)
assert.Equal(t, int64(5), rgetRep)
res, err2 = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
res, err2 = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": "incKey"},
Operation: bindings.GetOperation,
})
@ -230,14 +229,14 @@ func TestIncrement(t *testing.T) {
// wait for ttl to expire
s.FastForward(10 * time.Second)
res, err2 = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
res, err2 = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": "incKey"},
Operation: bindings.GetOperation,
})
require.NoError(t, err2)
assert.Equal(t, []byte(nil), res.Data)
_, err = bind.Invoke(context.TODO(), &bindings.InvokeRequest{
_, err = bind.Invoke(t.Context(), &bindings.InvokeRequest{
Metadata: map[string]string{"key": "incKey"},
Operation: bindings.DeleteOperation,
})

View File

@ -71,10 +71,10 @@ func TestBinding(t *testing.T) {
}}
b := getNewRethinkActorBinding()
err := b.Init(context.Background(), m)
err := b.Init(t.Context(), m)
require.NoErrorf(t, err, "error initializing")
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
err = b.Read(ctx, func(_ context.Context, res *bindings.ReadResponse) ([]byte, error) {
assert.NotNil(t, res)
t.Logf("state change event:\n%s", string(res.Data))

View File

@ -35,7 +35,7 @@ func TestInputBindingRead(t *testing.T) { //nolint:paralleltest
m := bindings.Metadata{} //nolint:exhaustivestruct
m.Properties = getTestMetadata()
r := NewRocketMQ(logger.NewLogger("test"))
err := r.Init(context.Background(), m)
err := r.Init(t.Context(), m)
require.NoError(t, err)
var count int32
@ -45,13 +45,13 @@ func TestInputBindingRead(t *testing.T) { //nolint:paralleltest
return nil, nil
}
err = r.Read(context.Background(), handler)
err = r.Read(t.Context(), handler)
require.NoError(t, err)
time.Sleep(5 * time.Second)
atomic.StoreInt32(&count, 0)
req := &bindings.InvokeRequest{Data: []byte("hello"), Operation: bindings.CreateOperation, Metadata: map[string]string{}}
_, err = r.Invoke(context.Background(), req)
_, err = r.Invoke(t.Context(), req)
require.NoError(t, err)
time.Sleep(10 * time.Second)

View File

@ -176,7 +176,7 @@ func (s *Mailer) parseMetadata(meta bindings.Metadata) (Metadata, error) {
}
// Helper to merge config and request metadata.
func (metadata Metadata) mergeWithRequestMetadata(req *bindings.InvokeRequest) (Metadata, error) {
func (metadata *Metadata) mergeWithRequestMetadata(req *bindings.InvokeRequest) (*Metadata, error) {
merged := metadata
if emailFrom := req.Metadata["emailFrom"]; emailFrom != "" {
@ -226,7 +226,7 @@ func (metadata *Metadata) parsePriority(req string) error {
return nil
}
func (metadata Metadata) parseAddresses(addresses string) []string {
func (metadata *Metadata) parseAddresses(addresses string) []string {
return strings.Split(addresses, mailSeparator)
}

View File

@ -71,7 +71,7 @@ func TestParseMetadataWithOptionalNames(t *testing.T) {
assert.Equal(t, "test2@example.net", sgMeta.EmailTo)
assert.Equal(t, "test 2", sgMeta.EmailToName)
assert.Equal(t, "hello", sgMeta.Subject)
assert.Equal(t, `{"name":{"first":"MyFirst","last":"MyLast"}}`, sgMeta.DynamicTemplateData)
assert.JSONEq(t, `{"name":{"first":"MyFirst","last":"MyLast"}}`, sgMeta.DynamicTemplateData)
assert.Equal(t, "456", sgMeta.DynamicTemplateID)
})

View File

@ -14,7 +14,6 @@ limitations under the License.
package sms
import (
"context"
"errors"
"io"
"net/http"
@ -53,7 +52,7 @@ func TestInit(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{"toNumber": "toNumber", "fromNumber": "fromNumber"}
tw := NewSMS(logger.NewLogger("test"))
err := tw.Init(context.Background(), m)
err := tw.Init(t.Context(), m)
require.Error(t, err)
}
@ -66,7 +65,7 @@ func TestParseDuration(t *testing.T) {
"authToken": "authToken", "timeout": "badtimeout",
}
tw := NewSMS(logger.NewLogger("test"))
err := tw.Init(context.Background(), m)
err := tw.Init(t.Context(), m)
require.Error(t, err)
}
@ -85,12 +84,12 @@ func TestWriteShouldSucceed(t *testing.T) {
tw.httpClient = &http.Client{
Transport: httpTransport,
}
err := tw.Init(context.Background(), m)
err := tw.Init(t.Context(), m)
require.NoError(t, err)
t.Run("Should succeed with expected url and headers", func(t *testing.T) {
httpTransport.reset()
_, err := tw.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := tw.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
toNumber: "toNumber",
@ -123,12 +122,12 @@ func TestWriteShouldFail(t *testing.T) {
tw.httpClient = &http.Client{
Transport: httpTransport,
}
err := tw.Init(context.Background(), m)
err := tw.Init(t.Context(), m)
require.NoError(t, err)
t.Run("Missing 'to' should fail", func(t *testing.T) {
httpTransport.reset()
_, err := tw.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := tw.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{},
})
@ -140,7 +139,7 @@ func TestWriteShouldFail(t *testing.T) {
httpTransport.reset()
httpErr := errors.New("twilio fake error")
httpTransport.errToReturn = httpErr
_, err := tw.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := tw.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
toNumber: "toNumber",
@ -154,7 +153,7 @@ func TestWriteShouldFail(t *testing.T) {
t.Run("Twilio call returns status not >=200 and <300", func(t *testing.T) {
httpTransport.reset()
httpTransport.response.StatusCode = 401
_, err := tw.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := tw.Invoke(t.Context(), &bindings.InvokeRequest{
Data: []byte("hello world"),
Metadata: map[string]string{
toNumber: "toNumber",
@ -180,13 +179,13 @@ func TestMessageBody(t *testing.T) {
tw.httpClient = &http.Client{
Transport: httpTransport,
}
err := tw.Init(context.Background(), m)
err := tw.Init(t.Context(), m)
require.NoError(t, err)
tester := func(reqData []byte, expectBody string) func(t *testing.T) {
return func(t *testing.T) {
httpTransport.reset()
_, err := tw.Invoke(context.Background(), &bindings.InvokeRequest{
_, err := tw.Invoke(t.Context(), &bindings.InvokeRequest{
Data: reqData,
Metadata: map[string]string{
toNumber: "toNumber",

View File

@ -15,7 +15,6 @@ package wasm
import (
"bytes"
"context"
"fmt"
"io"
"testing"
@ -34,7 +33,7 @@ func BenchmarkExample(b *testing.B) {
output := NewWasmOutput(l)
defer output.(io.Closer).Close()
ctx := context.Background()
ctx := b.Context()
err := output.Init(ctx, bindings.Metadata{Base: md})
if err != nil {
b.Fatal(err)
@ -46,7 +45,7 @@ func BenchmarkExample(b *testing.B) {
expected := []byte("main")
b.ResetTimer()
for i := 0; i < b.N; i++ {
for range b.N {
if resp, err := output.Invoke(ctx, request); err != nil {
b.Fatal(err)
} else if !bytes.Equal(expected, resp.Data) {

View File

@ -76,7 +76,7 @@ func Test_outputBinding_Init(t *testing.T) {
output := NewWasmOutput(logger.NewLogger(t.Name())).(*outputBinding)
defer output.Close()
err := output.Init(context.Background(), bindings.Metadata{Base: tc.metadata})
err := output.Init(t.Context(), bindings.Metadata{Base: tc.metadata})
if tc.expectedErr == "" {
require.NoError(t, err)
require.NotNil(t, output.runtime)
@ -89,7 +89,7 @@ func Test_outputBinding_Init(t *testing.T) {
}
func Test_Invoke(t *testing.T) {
canceledCtx, cancel := context.WithCancel(context.Background())
canceledCtx, cancel := context.WithCancel(t.Context())
cancel()
type testCase struct {
@ -160,7 +160,7 @@ func Test_Invoke(t *testing.T) {
output := NewWasmOutput(l)
defer output.(io.Closer).Close()
ctx := context.Background()
ctx := t.Context()
err := output.Init(ctx, bindings.Metadata{Base: meta})
require.NoError(t, err)
@ -244,7 +244,7 @@ func Test_InvokeHttp(t *testing.T) {
output := NewWasmOutput(l)
defer output.(io.Closer).Close()
ctx := context.Background()
ctx := t.Context()
err := output.Init(ctx, bindings.Metadata{Base: meta})
require.NoError(t, err)
@ -284,7 +284,7 @@ func TestEnsureConcurrency(t *testing.T) {
output := NewWasmOutput(l)
defer output.(io.Closer).Close()
ctx := context.Background()
ctx := t.Context()
err := output.Init(ctx, bindings.Metadata{Base: meta})
require.NoError(t, err)

View File

@ -107,7 +107,7 @@ func TestActivateJobs(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: ActivateJobsOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingJobType)
})
@ -120,7 +120,7 @@ func TestActivateJobs(t *testing.T) {
cmd := ZeebeCommand{logger: testLogger}
req := &bindings.InvokeRequest{Data: data, Operation: ActivateJobsOperation}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingMaxJobsToActivate)
})
@ -137,7 +137,7 @@ func TestActivateJobs(t *testing.T) {
var mc mockActivateJobsClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, payload.JobType, mc.cmd1.jobType)
@ -160,7 +160,7 @@ func TestActivateJobs(t *testing.T) {
var mc mockActivateJobsClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, payload.JobType, mc.cmd1.jobType)

View File

@ -70,7 +70,7 @@ func TestCancelInstance(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: CancelInstanceOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingProcessInstanceKey)
})
@ -86,7 +86,7 @@ func TestCancelInstance(t *testing.T) {
var mc mockCancelInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.ProcessInstanceKey, mc.cmd1.cmd2.processInstanceKey)

View File

@ -14,7 +14,6 @@ limitations under the License.
package command
import (
"context"
"errors"
"testing"
@ -58,7 +57,7 @@ func TestInit(t *testing.T) {
}
cmd := ZeebeCommand{clientFactory: mcf, logger: testLogger}
err := cmd.Init(context.Background(), metadata)
err := cmd.Init(t.Context(), metadata)
require.ErrorIs(t, err, errParsing)
})
@ -67,7 +66,7 @@ func TestInit(t *testing.T) {
mcf := &mockClientFactory{}
cmd := ZeebeCommand{clientFactory: mcf, logger: testLogger}
err := cmd.Init(context.Background(), metadata)
err := cmd.Init(t.Context(), metadata)
require.NoError(t, err)
@ -85,7 +84,7 @@ func TestInvoke(t *testing.T) {
t.Run("operation must be supported", func(t *testing.T) {
cmd := ZeebeCommand{logger: testLogger}
req := &bindings.InvokeRequest{Operation: bindings.DeleteOperation}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.EqualError(t, err, ErrUnsupportedOperation(bindings.DeleteOperation).Error())
})
}

View File

@ -84,7 +84,7 @@ func TestCompleteJob(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: CompleteJobOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingJobKey)
})
@ -103,7 +103,7 @@ func TestCompleteJob(t *testing.T) {
var mc mockCompleteJobClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.JobKey, mc.cmd1.jobKey)

View File

@ -114,7 +114,7 @@ func TestCreateInstance(t *testing.T) {
var mc mockCreateInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrAmbiguousCreationVars)
})
@ -128,7 +128,7 @@ func TestCreateInstance(t *testing.T) {
var mc mockCreateInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingCreationVars)
})
@ -145,7 +145,7 @@ func TestCreateInstance(t *testing.T) {
var mc mockCreateInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, payload.BpmnProcessID, mc.cmd1.bpmnProcessID)
@ -164,7 +164,7 @@ func TestCreateInstance(t *testing.T) {
var mc mockCreateInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, payload.BpmnProcessID, mc.cmd1.bpmnProcessID)
@ -183,7 +183,7 @@ func TestCreateInstance(t *testing.T) {
var mc mockCreateInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.ProcessDefinitionKey, mc.cmd1.processDefinitionKey)
@ -204,7 +204,7 @@ func TestCreateInstance(t *testing.T) {
var mc mockCreateInstanceClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.ProcessDefinitionKey, mc.cmd1.processDefinitionKey)

View File

@ -14,7 +14,6 @@ limitations under the License.
package command
import (
"context"
"testing"
"github.com/stretchr/testify/require"
@ -29,7 +28,7 @@ func TestDeployResource(t *testing.T) {
t.Run("fileName is mandatory", func(t *testing.T) {
cmd := ZeebeCommand{logger: testLogger}
req := &bindings.InvokeRequest{Operation: DeployResourceOperation}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingFileName)
})
}

View File

@ -91,7 +91,7 @@ func TestFailJob(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: FailJobOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingJobKey)
})
@ -104,7 +104,7 @@ func TestFailJob(t *testing.T) {
cmd := ZeebeCommand{logger: testLogger}
req := &bindings.InvokeRequest{Data: data, Operation: FailJobOperation}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingRetries)
})
@ -122,7 +122,7 @@ func TestFailJob(t *testing.T) {
var mc mockFailJobClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.JobKey, mc.cmd1.jobKey)

View File

@ -108,7 +108,7 @@ func TestPublishMessage(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: PublishMessageOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingMessageName)
})
@ -124,7 +124,7 @@ func TestPublishMessage(t *testing.T) {
var mc mockPublishMessageClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, payload.MessageName, mc.cmd1.messageName)
@ -149,7 +149,7 @@ func TestPublishMessage(t *testing.T) {
var mc mockPublishMessageClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, payload.MessageName, mc.cmd1.messageName)

View File

@ -70,7 +70,7 @@ func TestResolveIncident(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: ResolveIncidentOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingIncidentKey)
})
@ -86,7 +86,7 @@ func TestResolveIncident(t *testing.T) {
var mc mockResolveIncidentClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.IncidentKey, mc.cmd1.incidentKey)

View File

@ -91,7 +91,7 @@ func TestSetVariables(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: SetVariablesOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingElementInstanceKey)
})
@ -104,7 +104,7 @@ func TestSetVariables(t *testing.T) {
cmd := ZeebeCommand{logger: testLogger}
req := &bindings.InvokeRequest{Data: data, Operation: SetVariablesOperation}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingVariables)
})
@ -123,7 +123,7 @@ func TestSetVariables(t *testing.T) {
var mc mockSetVariableClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.ElementInstanceKey, mc.cmd1.elementInstanceKey)
@ -147,7 +147,7 @@ func TestSetVariables(t *testing.T) {
var mc mockSetVariableClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.ElementInstanceKey, mc.cmd1.elementInstanceKey)

View File

@ -91,7 +91,7 @@ func TestThrowError(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: ThrowErrorOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingJobKey)
})
@ -104,7 +104,7 @@ func TestThrowError(t *testing.T) {
cmd := ZeebeCommand{logger: testLogger}
req := &bindings.InvokeRequest{Data: data, Operation: ThrowErrorOperation}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingErrorCode)
})
@ -122,7 +122,7 @@ func TestThrowError(t *testing.T) {
var mc mockThrowErrorClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.JobKey, mc.cmd1.jobKey)

View File

@ -77,7 +77,7 @@ func TestUpdateJobRetries(t *testing.T) {
data, marshalErr := json.Marshal(payload)
require.NoError(t, marshalErr)
req := &bindings.InvokeRequest{Operation: UpdateJobRetriesOperation, Data: data}
_, err := cmd.Invoke(context.TODO(), req)
_, err := cmd.Invoke(t.Context(), req)
require.ErrorIs(t, err, ErrMissingJobKey)
})
@ -94,7 +94,7 @@ func TestUpdateJobRetries(t *testing.T) {
var mc mockUpdateJobRetriesClient
cmd := ZeebeCommand{logger: testLogger, client: &mc}
_, err = cmd.Invoke(context.TODO(), req)
_, err = cmd.Invoke(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, *payload.JobKey, mc.cmd1.jobKey)

View File

@ -14,7 +14,6 @@ limitations under the License.
package jobworker
import (
"context"
"errors"
"testing"
@ -60,7 +59,7 @@ func TestInit(t *testing.T) {
var mcf mockClientFactory
jobWorker := ZeebeJobWorker{clientFactory: &mcf, logger: testLogger, closeCh: make(chan struct{})}
err := jobWorker.Init(context.Background(), metadata)
err := jobWorker.Init(t.Context(), metadata)
require.ErrorIs(t, err, ErrMissingJobType)
require.NoError(t, jobWorker.Close())
@ -74,7 +73,7 @@ func TestInit(t *testing.T) {
metadata: metadata,
}
jobWorker := ZeebeJobWorker{clientFactory: mcf, logger: testLogger, closeCh: make(chan struct{})}
err := jobWorker.Init(context.Background(), metadata)
err := jobWorker.Init(t.Context(), metadata)
require.NoError(t, err)
@ -95,7 +94,7 @@ func TestInit(t *testing.T) {
}
jobWorker := ZeebeJobWorker{clientFactory: mcf, logger: testLogger, closeCh: make(chan struct{})}
err := jobWorker.Init(context.Background(), metadata)
err := jobWorker.Init(t.Context(), metadata)
require.Error(t, err, errParsing.Error())
require.NoError(t, jobWorker.Close())
})
@ -109,7 +108,7 @@ func TestInit(t *testing.T) {
}
jobWorker := ZeebeJobWorker{clientFactory: mcf, logger: testLogger, closeCh: make(chan struct{})}
err := jobWorker.Init(context.Background(), metadata)
err := jobWorker.Init(t.Context(), metadata)
require.NoError(t, err)

View File

@ -115,7 +115,7 @@ func TestSqsClients_QueueURL(t *testing.T) {
Sqs: mockSQS,
}
url, err := client.QueueURL(context.Background(), tt.queueName)
url, err := client.QueueURL(t.Context(), tt.queueName)
if tt.expectError {
require.Error(t, err)
@ -171,7 +171,7 @@ func TestKinesisClients_Stream(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.kinesisClient.Stream(context.Background(), tt.streamName)
got, err := tt.kinesisClient.Stream(t.Context(), tt.streamName)
if tt.expectedErr != nil {
require.Error(t, err)
assert.Equal(t, tt.expectedErr.Error(), err.Error())
@ -251,7 +251,7 @@ func TestKinesisClients_WorkerCfg(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := tt.kinesisClient.WorkerCfg(context.Background(), tt.streamName, tt.consumer, tt.mode)
cfg := tt.kinesisClient.WorkerCfg(t.Context(), tt.streamName, tt.consumer, tt.mode)
if tt.expectedConfig == nil {
assert.Equal(t, tt.expectedConfig, cfg)
return

View File

@ -92,13 +92,15 @@ func TestGetX509Client(t *testing.T) {
var fetches atomic.Int32
s := spiffe.New(spiffe.Options{
Log: logger.NewLogger("test"),
RequestSVIDFn: func(context.Context, []byte) ([]*cryptoX509.Certificate, error) {
RequestSVIDFn: func(context.Context, []byte) (*spiffe.SVIDResponse, error) {
fetches.Add(1)
return respCert, respErr
return &spiffe.SVIDResponse{
X509Certificates: respCert,
}, respErr
},
})
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
errCh := make(chan error)
go func() {

View File

@ -187,7 +187,7 @@ func TestGetMSI(t *testing.T) {
}
func TestFallbackToMSI(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -203,7 +203,7 @@ func TestFallbackToMSI(t *testing.T) {
}
func TestAuthorizorWithMSI(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -222,7 +222,7 @@ func TestAuthorizorWithMSI(t *testing.T) {
}
func TestFallbackToMSIbutAzureAuthDisallowed(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -239,7 +239,7 @@ func TestFallbackToMSIbutAzureAuthDisallowed(t *testing.T) {
}
func TestFallbackToMSIandInAllowedList(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -259,7 +259,7 @@ func TestFallbackToMSIandInAllowedList(t *testing.T) {
}
func TestFallbackToMSIandNotInAllowedList(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -276,7 +276,7 @@ func TestFallbackToMSIandNotInAllowedList(t *testing.T) {
}
func TestFallbackToMSIandInvalidAuthMethod(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -296,7 +296,7 @@ func TestFallbackToMSIandInvalidAuthMethod(t *testing.T) {
}
func TestAuthorizorWithMSIAndUserAssignedID(t *testing.T) {
os.Setenv("MSI_ENDPOINT", "test")
t.Setenv("MSI_ENDPOINT", "test")
defer os.Unsetenv("MSI_ENDPOINT")
settings, err := NewEnvironmentSettings(
map[string]string{
@ -333,7 +333,7 @@ func TestFallbackToCLI(t *testing.T) {
runTest := false
cred, credErr := azidentity.NewAzureCLICredential(nil)
if credErr == nil {
ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
ctx, cancelFunc := context.WithTimeout(t.Context(), 5*time.Second)
defer cancelFunc()
token, err := cred.GetToken(ctx, policy.TokenRequestOptions{})
if err == nil && token.Token != "" {
@ -345,7 +345,7 @@ func TestFallbackToCLI(t *testing.T) {
spt, err := settings.GetTokenCredential()
require.NoError(t, err)
token, _ := spt.GetToken(context.Background(), policy.TokenRequestOptions{})
token, _ := spt.GetToken(t.Context(), policy.TokenRequestOptions{})
assert.NotNil(t, token)
assert.NotEmpty(t, token.Token)
} else {

View File

@ -17,6 +17,8 @@ import (
"context"
"errors"
"fmt"
"net/url"
"strings"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
@ -32,6 +34,13 @@ import (
// PostgresAuthMetadata contains authentication metadata for PostgreSQL components.
type PostgresAuthMetadata struct {
ConnectionString string `mapstructure:"connectionString" mapstructurealiases:"url"`
Host string `mapstructure:"host"`
HostAddr string `mapstructure:"hostaddr"`
Port string `mapstructure:"port"`
Database string `mapstructure:"database"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
SslRootCert string `mapstructure:"sslRootCert"`
ConnectionMaxIdleTime time.Duration `mapstructure:"connectionMaxIdleTime"`
MaxConns int `mapstructure:"maxConns"`
UseAzureAD bool `mapstructure:"useAzureAD"`
@ -45,6 +54,13 @@ type PostgresAuthMetadata struct {
// Reset the object.
func (m *PostgresAuthMetadata) Reset() {
m.ConnectionString = ""
m.Host = ""
m.HostAddr = ""
m.Port = ""
m.Database = ""
m.User = ""
m.Password = ""
m.SslRootCert = ""
m.ConnectionMaxIdleTime = 0
m.MaxConns = 0
m.UseAzureAD = false
@ -62,8 +78,9 @@ type InitWithMetadataOpts struct {
// This is different from the "useAzureAD" property from the user, which is provided by the user and instructs the component to authenticate using Azure AD.
func (m *PostgresAuthMetadata) InitWithMetadata(meta map[string]string, opts InitWithMetadataOpts) (err error) {
// Validate input
if m.ConnectionString == "" {
return errors.New("missing connection string")
_, err = m.buildConnectionString()
if err != nil {
return err
}
switch {
case opts.AzureADEnabled && m.UseAzureAD:
@ -87,6 +104,118 @@ func (m *PostgresAuthMetadata) InitWithMetadata(meta map[string]string, opts Ini
return nil
}
// buildConnectionString builds the connection string from the metadata.
// It supports both DSN-style and URL-style connection strings.
// Metadata fields override existing values in the connection string.
func (m *PostgresAuthMetadata) buildConnectionString() (string, error) {
metadata := m.getConnectionStringMetadata()
if strings.HasPrefix(m.ConnectionString, "postgres://") || strings.HasPrefix(m.ConnectionString, "postgresql://") {
return m.buildURLConnectionString(metadata)
}
return m.buildDSNConnectionString(metadata)
}
func (m *PostgresAuthMetadata) buildDSNConnectionString(metadata map[string]string) (string, error) {
connectionString := ""
parts := strings.Split(m.ConnectionString, " ")
for _, part := range parts {
kv := strings.SplitN(part, "=", 2)
if len(kv) == 2 {
key := kv[0]
if value, ok := metadata[key]; ok {
connectionString += fmt.Sprintf("%s=%s ", key, value)
delete(metadata, key)
} else {
connectionString += fmt.Sprintf("%s=%s ", key, kv[1])
}
}
}
for k, v := range metadata {
connectionString += fmt.Sprintf("%s=%s ", k, v)
}
if connectionString == "" {
return "", errors.New("failed to build connection string")
}
return strings.TrimSpace(connectionString), nil
}
func (m *PostgresAuthMetadata) getConnectionStringMetadata() map[string]string {
metadata := make(map[string]string)
if m.User != "" {
metadata["user"] = m.User
}
if m.Host != "" {
metadata["host"] = m.Host
}
if m.HostAddr != "" {
metadata["hostaddr"] = m.HostAddr
}
if m.Port != "" {
metadata["port"] = m.Port
}
if m.Database != "" {
metadata["database"] = m.Database
}
if m.Password != "" {
metadata["password"] = m.Password
}
if m.SslRootCert != "" {
metadata["sslrootcert"] = m.SslRootCert
}
return metadata
}
func (m *PostgresAuthMetadata) buildURLConnectionString(metadata map[string]string) (string, error) {
u, err := url.Parse(m.ConnectionString)
if err != nil {
return "", fmt.Errorf("invalid URL connection string: %w", err)
}
var username string
var password string
if u.User != nil {
username = u.User.Username()
pw, set := u.User.Password()
if set {
password = pw
}
}
if val, ok := metadata["user"]; ok {
username = val
}
if val, ok := metadata["password"]; ok {
password = val
}
if username != "" {
u.User = url.UserPassword(username, password)
}
if val, ok := metadata["host"]; ok {
u.Host = val
}
if val, ok := metadata["hostaddr"]; ok {
u.Host = val
}
if m.Port != "" {
u.Host = fmt.Sprintf("%s:%s", u.Host, m.Port)
}
if val, ok := metadata["database"]; ok {
u.Path = "/" + strings.TrimPrefix(val, "/")
}
q := u.Query()
if val, ok := metadata["sslrootcert"]; ok {
q.Set("sslrootcert", val)
}
u.RawQuery = q.Encode()
return u.String(), nil
}
func (m *PostgresAuthMetadata) BuildAwsIamOptions(logger logger.Logger, properties map[string]string) (*aws.Options, error) {
awsRegion, _ := metadata.GetMetadataProperty(m.awsEnv.Metadata, "AWSRegion")
region, _ := metadata.GetMetadataProperty(m.awsEnv.Metadata, "region")
@ -132,8 +261,11 @@ func (m *PostgresAuthMetadata) BuildAwsIamOptions(logger logger.Logger, properti
// GetPgxPoolConfig returns the pgxpool.Config object that contains the credentials for connecting to PostgreSQL.
func (m *PostgresAuthMetadata) GetPgxPoolConfig() (*pgxpool.Config, error) {
// Get the config from the connection string
config, err := pgxpool.ParseConfig(m.ConnectionString)
connectionString, err := m.buildConnectionString()
if err != nil {
return nil, err
}
config, err := pgxpool.ParseConfig(connectionString)
if err != nil {
return nil, fmt.Errorf("failed to parse connection string: %w", err)
}

View File

@ -0,0 +1,174 @@
package postgresql
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestBuildConnectionString(t *testing.T) {
tc := []struct {
name string
metadata PostgresAuthMetadata
expected string
expectError bool
}{
{
name: "empty metadata",
metadata: PostgresAuthMetadata{},
expected: "",
expectError: true,
},
{
name: "valid DSN connection string",
metadata: PostgresAuthMetadata{
ConnectionString: "host=localhost user=postgres password=example port=5432 connect_timeout=10 database=my_db",
},
expected: "host=localhost user=postgres password=example port=5432 connect_timeout=10 database=my_db",
expectError: false,
},
{
name: "invalid DSN string with metadata",
metadata: PostgresAuthMetadata{
ConnectionString: "this is not a valid connection string",
},
expected: "",
expectError: true,
},
{
name: "DSN string overridden by metadata",
metadata: PostgresAuthMetadata{
ConnectionString: "host=localhost user=postgres password=example",
User: "overrideUser",
Password: "overridePass",
},
expected: "host=localhost user=overrideUser password=overridePass",
expectError: false,
},
{
name: "DSN missing user, added by metadata",
metadata: PostgresAuthMetadata{
ConnectionString: "host=localhost port=5432",
User: "fromMetadata",
},
expected: "host=localhost port=5432 user=fromMetadata",
expectError: false,
},
{
name: "URL connection string no metadata",
metadata: PostgresAuthMetadata{
ConnectionString: "postgres://user:pass@localhost:5432/mydb?sslmode=disable",
},
expected: "postgres://user:pass@localhost:5432/mydb?sslmode=disable",
expectError: false,
},
{
name: "URL connection string overridden by metadata",
metadata: PostgresAuthMetadata{
ConnectionString: "postgres://original:secret@localhost:5432/mydb?sslmode=disable",
User: "newuser",
Password: "newpass",
Host: "newhost",
Port: "5433",
Database: "newdb",
SslRootCert: "/certs/root.pem",
},
expected: "postgres://newuser:newpass@newhost:5433/newdb?sslmode=disable&sslrootcert=%2Fcerts%2Froot.pem",
expectError: false,
},
{
name: "URL connection string overridden by metadata with hostaddr",
metadata: PostgresAuthMetadata{
ConnectionString: "postgres://original:secret@localhost:5432/mydb?sslmode=disable",
User: "newuser",
Password: "newpass",
Host: "newhost",
HostAddr: "127.0.0.1",
Port: "5433",
Database: "newdb",
SslRootCert: "/certs/root.pem",
},
expected: "postgres://newuser:newpass@127.0.0.1:5433/newdb?sslmode=disable&sslrootcert=%2Fcerts%2Froot.pem",
expectError: false,
},
{
name: "URL connection string adds sslrootcert via metadata",
metadata: PostgresAuthMetadata{
ConnectionString: "postgres://user:pass@localhost:5432/mydb?sslmode=verify-full",
SslRootCert: "/certs/root.pem",
},
expected: "postgres://user:pass@localhost:5432/mydb?sslmode=verify-full&sslrootcert=%2Fcerts%2Froot.pem",
expectError: false,
},
{
name: "URL connection string adds sslrootcert via metadata with hostaddr",
metadata: PostgresAuthMetadata{
ConnectionString: "postgres://user:pass@localhost:5432/mydb?sslmode=verify-full",
SslRootCert: "/certs/root.pem",
HostAddr: "127.0.0.1",
Port: "5433",
},
expected: "postgres://user:pass@127.0.0.1:5433/mydb?sslmode=verify-full&sslrootcert=%2Fcerts%2Froot.pem",
expectError: false,
},
}
for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
actual, err := tt.metadata.buildConnectionString()
if tt.expectError {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.expected, actual)
}
})
}
}
func TestURLBuildConnectionStringOnlyWithMetadata(t *testing.T) {
metadata := PostgresAuthMetadata{
ConnectionString: "postgres://original:secret@localhost:5432/mydb?sslmode=disable",
User: "postgres",
Password: "example",
Host: "localhost",
Port: "5432",
Database: "my_db",
SslRootCert: "/certs/root.pem",
}
actual, err := metadata.buildConnectionString()
require.NoError(t, err)
require.Equal(t, "postgres://postgres:example@localhost:5432/my_db?sslmode=disable&sslrootcert=%2Fcerts%2Froot.pem", actual)
}
func TestDSNBuildConnectionStringOnlyWithMetadata(t *testing.T) {
metadata := PostgresAuthMetadata{
User: "postgres",
Password: "example",
Host: "localhost",
Port: "5432",
Database: "my_db",
SslRootCert: "/certs/root.pem",
}
actual, err := metadata.buildConnectionString()
require.NoError(t, err)
parts := strings.Split(actual, " ")
for _, part := range parts {
kv := strings.Split(part, "=")
require.Len(t, kv, 2)
switch kv[0] {
case "host":
require.Equal(t, "localhost", kv[1])
case "user":
require.Equal(t, "postgres", kv[1])
case "password":
require.Equal(t, "example", kv[1])
case "port":
require.Equal(t, "5432", kv[1])
case "database":
require.Equal(t, "my_db", kv[1])
case "sslrootcert":
require.Equal(t, "/certs/root.pem", kv[1])
}
}
}

View File

@ -65,7 +65,7 @@ func (m *SqliteAuthMetadata) Validate() error {
}
// IsInMemoryDB returns true if the connection string is for an in-memory database.
func (m SqliteAuthMetadata) IsInMemoryDB() bool {
func (m *SqliteAuthMetadata) IsInMemoryDB() bool {
lc := strings.ToLower(m.ConnectionString)
return strings.HasPrefix(lc, ":memory:") || strings.HasPrefix(lc, "file::memory:")
}

View File

@ -96,7 +96,7 @@ func (m *SQLServerAuthMetadata) GetConnector(setDatabase bool) (*mssql.Connector
conn, err := mssql.NewSecurityTokenConnector(config, func(ctx context.Context) (string, error) {
at, err := tokenCred.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string{
m.azureEnv.Cloud.Services[azure.ServiceAzureSQL].Audience,
m.azureEnv.Cloud.Services[azure.ServiceAzureSQL].Audience + "/.default",
},
})
if err != nil {

View File

@ -15,7 +15,6 @@ package blobstorage
import (
"bytes"
"context"
"testing"
"github.com/stretchr/testify/assert"
@ -46,7 +45,7 @@ func TestClientInitFailures(t *testing.T) {
for name, s := range scenarios {
t.Run(name, func(t *testing.T) {
_, _, err := CreateContainerStorageClient(context.Background(), log, s.metadata)
_, _, err := CreateContainerStorageClient(t.Context(), log, s.metadata)
assert.Contains(t, err.Error(), s.expectedFailureSubString)
})
}

View File

@ -26,7 +26,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs"
"github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/checkpoints"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
"golang.org/x/exp/maps"
"github.com/dapr/components-contrib/bindings"
azauth "github.com/dapr/components-contrib/common/authentication/azure"
@ -447,7 +446,7 @@ func (aeh *AzureEventHubs) Close() (err error) {
}(producer)
}
wg.Wait()
maps.Clear(aeh.producers)
clear(aeh.producers)
// Remove the cached checkpoint store and metadata
aeh.checkpointStoreCache = nil

View File

@ -22,7 +22,6 @@ import (
servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
sbadmin "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/admin"
"github.com/cenkalti/backoff/v4"
"golang.org/x/exp/maps"
azauth "github.com/dapr/components-contrib/common/authentication/azure"
"github.com/dapr/kit/logger"
@ -192,7 +191,7 @@ func (c *Client) CloseAllSenders(log logger.Logger) {
close(workersCh)
// Clear the map
maps.Clear(c.senders)
clear(c.senders)
}
// Close the client and every sender or consumer created by the connnection.
@ -212,7 +211,7 @@ func (c *Client) Close(log logger.Logger) {
}
// Clear the map of senders
maps.Clear(c.senders)
clear(c.senders)
}
// EnsureTopic creates the topic if it doesn't exist.

View File

@ -331,7 +331,7 @@ func (s *Subscription) doRenewLocks(ctx context.Context, receiver *MessageReceiv
err error
errored int
)
for range len(msgs) {
for range msgs {
// This is a nop if the received error is nil
if multierr.AppendInto(&err, <-errCh) {
errored++

View File

@ -110,7 +110,7 @@ func (m *BaseMetadata) Validate() error {
}
// CreateToken creates a JWT token for authorizing requests
func (m BaseMetadata) CreateToken() (string, error) {
func (m *BaseMetadata) CreateToken() (string, error) {
now := time.Now()
token, err := jwt.NewBuilder().
Audience([]string{m.WorkerName}).

View File

@ -96,7 +96,7 @@ func (w *Base) SetMetadata(metadata *BaseMetadata) {
}
// Client returns the HTTP client.
func (w Base) Client() *http.Client {
func (w *Base) Client() *http.Client {
return w.client
}

View File

@ -154,6 +154,8 @@ func (k *Kafka) Init(ctx context.Context, metadata map[string]string) error {
config.Consumer.Group.Session.Timeout = meta.SessionTimeout
config.ChannelBufferSize = meta.channelBufferSize
config.Producer.Compression = meta.internalCompression
config.Net.KeepAlive = meta.ClientConnectionKeepAliveInterval
config.Metadata.RefreshFrequency = meta.ClientConnectionTopicMetadataRefreshInterval

View File

@ -188,7 +188,7 @@ func TestSerializeValueCachingDisabled(t *testing.T) {
act, err := k.SerializeValue("my-topic", valJSON, map[string]string{})
require.Equal(t, valJSON, act)
require.JSONEq(t, string(valJSON), string(act))
require.NoError(t, err)
})
@ -197,7 +197,7 @@ func TestSerializeValueCachingDisabled(t *testing.T) {
act, err := k.SerializeValue("my-topic", valJSON, map[string]string{"valueSchemaType": "None"})
require.Equal(t, valJSON, act)
require.JSONEq(t, string(valJSON), string(act))
require.NoError(t, err)
})
@ -206,7 +206,7 @@ func TestSerializeValueCachingDisabled(t *testing.T) {
act, err := k.SerializeValue("my-topic", valJSON, map[string]string{"valueSchemaType": "NONE"})
require.Equal(t, valJSON, act)
require.JSONEq(t, string(valJSON), string(act))
require.NoError(t, err)
})
@ -262,7 +262,7 @@ func TestSerializeValueCachingEnabled(t *testing.T) {
t.Run("valueSchemaType not set, leave value as is", func(t *testing.T) {
valJSON, _ := json.Marshal(testValue1)
act, err := k.SerializeValue("my-topic", valJSON, map[string]string{})
require.Equal(t, valJSON, act)
require.JSONEq(t, string(valJSON), string(act))
require.NoError(t, err)
})

View File

@ -38,7 +38,6 @@ const (
certificateAuthType = "certificate"
clientCert = "clientCert"
clientKey = "clientKey"
consumeRetryEnabled = "consumeRetryEnabled"
consumeRetryInterval = "consumeRetryInterval"
authType = "authType"
passwordAuthType = "password"
@ -50,6 +49,7 @@ const (
consumerFetchDefault = "consumerFetchDefault"
channelBufferSize = "channelBufferSize"
valueSchemaType = "valueSchemaType"
compression = "compression"
// Kafka client config default values.
// Refresh interval < keep alive time so that way connection can be kept alive indefinitely if desired.
@ -102,6 +102,10 @@ type KafkaMetadata struct {
consumerFetchMin int32 `mapstructure:"-"`
consumerFetchDefault int32 `mapstructure:"-"`
// configs for kafka producer
Compression string `mapstructure:"compression"`
internalCompression sarama.CompressionCodec `mapstructure:"-"`
// schema registry
SchemaRegistryURL string `mapstructure:"schemaRegistryURL"`
SchemaRegistryAPIKey string `mapstructure:"schemaRegistryAPIKey"`
@ -149,6 +153,7 @@ func (k *Kafka) getKafkaMetadata(meta map[string]string) (*KafkaMetadata, error)
ConsumeRetryEnabled: k.DefaultConsumeRetryEnabled,
ConsumeRetryInterval: 100 * time.Millisecond,
internalVersion: sarama.V2_0_0_0, //nolint:nosnakecase
internalCompression: sarama.CompressionNone,
channelBufferSize: 256,
consumerFetchMin: 1,
consumerFetchDefault: 1024 * 1024,
@ -282,7 +287,7 @@ func (k *Kafka) getKafkaMetadata(meta map[string]string) (*KafkaMetadata, error)
if err != nil {
return nil, fmt.Errorf("kafka error: invalid value for '%s' attribute: %w", consumeRetryInterval, err)
}
m.ConsumeRetryInterval = time.Duration(intVal) * time.Millisecond //nolint:gosec
m.ConsumeRetryInterval = time.Duration(intVal) * time.Millisecond
}
}
@ -294,6 +299,14 @@ func (k *Kafka) getKafkaMetadata(meta map[string]string) (*KafkaMetadata, error)
m.internalVersion = version
}
if m.Compression != "" {
compression, err := parseCompression(m.Compression)
if err != nil {
return nil, err
}
m.internalCompression = compression
}
if val, ok := meta[channelBufferSize]; ok && val != "" {
v, err := strconv.Atoi(val)
if err != nil {

View File

@ -397,6 +397,7 @@ func TestMetadataProducerValues(t *testing.T) {
require.NoError(t, err)
require.Equal(t, defaultClientConnectionTopicMetadataRefreshInterval, meta.ClientConnectionTopicMetadataRefreshInterval)
require.Equal(t, defaultClientConnectionKeepAliveInterval, meta.ClientConnectionKeepAliveInterval)
require.Equal(t, sarama.CompressionNone, meta.internalCompression)
})
t.Run("setting producer values explicitly", func(t *testing.T) {
@ -404,11 +405,13 @@ func TestMetadataProducerValues(t *testing.T) {
m := getCompleteMetadata()
m[clientConnectionTopicMetadataRefreshInterval] = "3m0s"
m[clientConnectionKeepAliveInterval] = "4m0s"
m[compression] = "gzip"
meta, err := k.getKafkaMetadata(m)
require.NoError(t, err)
require.Equal(t, 3*time.Minute, meta.ClientConnectionTopicMetadataRefreshInterval)
require.Equal(t, 4*time.Minute, meta.ClientConnectionKeepAliveInterval)
require.Equal(t, sarama.CompressionGZIP, meta.internalCompression)
})
t.Run("setting producer invalid values so defaults take over", func(t *testing.T) {
@ -422,6 +425,17 @@ func TestMetadataProducerValues(t *testing.T) {
require.Equal(t, defaultClientConnectionTopicMetadataRefreshInterval, meta.ClientConnectionTopicMetadataRefreshInterval)
require.Equal(t, defaultClientConnectionKeepAliveInterval, meta.ClientConnectionKeepAliveInterval)
})
t.Run("setting producer invalid compression value", func(t *testing.T) {
k := getKafka()
m := getCompleteMetadata()
m[compression] = "invalid"
meta, err := k.getKafkaMetadata(m)
require.Error(t, err)
require.Nil(t, meta)
require.Equal(t, "kafka error: invalid compression: invalid", err.Error())
})
}
func TestMetadataChannelBufferSize(t *testing.T) {

View File

@ -1,7 +1,6 @@
package kafka
import (
"context"
"testing"
"github.com/IBM/sarama"
@ -47,7 +46,7 @@ func createMessageAsserter(t *testing.T, expectedKey sarama.Encoder, expectedHea
}
func TestPublish(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
t.Run("produce message without partition key", func(t *testing.T) {
// arrange
@ -98,7 +97,7 @@ func TestPublish(t *testing.T) {
}
func TestBulkPublish(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
metadata := map[string]string{
"common": "common",
}

View File

@ -32,7 +32,7 @@ import (
func Test_reloadConsumerGroup(t *testing.T) {
t.Run("if reload called with no topics and not closed, expect return and cancel called", func(t *testing.T) {
var consumeCalled atomic.Bool
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
t.Cleanup(cancel)
cg := mocks.NewConsumerGroup().WithConsumeFn(func(context.Context, []string, sarama.ConsumerGroupHandler) error {
@ -56,7 +56,7 @@ func Test_reloadConsumerGroup(t *testing.T) {
t.Run("if reload called with topics but is closed, expect return and cancel called", func(t *testing.T) {
var consumeCalled atomic.Bool
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
t.Cleanup(cancel)
cg := mocks.NewConsumerGroup().WithConsumeFn(func(context.Context, []string, sarama.ConsumerGroupHandler) error {
@ -255,7 +255,7 @@ func Test_Subscribe(t *testing.T) {
subscribeTopics: make(TopicHandlerConfig),
}
k.Subscribe(context.Background(), SubscriptionHandlerConfig{})
k.Subscribe(t.Context(), SubscriptionHandlerConfig{})
assert.Nil(t, k.consumerCancel)
assert.Equal(t, int64(0), consumeCalled.Load())
@ -282,7 +282,7 @@ func Test_Subscribe(t *testing.T) {
k.closed.Store(true)
k.Subscribe(context.Background(), SubscriptionHandlerConfig{}, "abc")
k.Subscribe(t.Context(), SubscriptionHandlerConfig{}, "abc")
assert.Nil(t, k.consumerCancel)
assert.Equal(t, int64(0), consumeCalled.Load())
@ -309,7 +309,7 @@ func Test_Subscribe(t *testing.T) {
subscribeTopics: make(TopicHandlerConfig),
}
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
k.Subscribe(ctx, SubscriptionHandlerConfig{}, "abc")
assert.Eventually(t, func() bool {
@ -347,7 +347,7 @@ func Test_Subscribe(t *testing.T) {
subscribeTopics: make(TopicHandlerConfig),
}
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
k.Subscribe(ctx, SubscriptionHandlerConfig{}, "abc")
assert.Eventually(t, func() bool {
@ -398,7 +398,7 @@ func Test_Subscribe(t *testing.T) {
consumeRetryInterval: time.Millisecond,
}
k.Subscribe(context.Background(), SubscriptionHandlerConfig{}, "foo")
k.Subscribe(t.Context(), SubscriptionHandlerConfig{}, "foo")
assert.Equal(t, TopicHandlerConfig{"foo": SubscriptionHandlerConfig{}}, k.subscribeTopics)
assert.Eventually(t, func() bool {
return consumeCalled.Load() == 5
@ -428,7 +428,7 @@ func Test_Subscribe(t *testing.T) {
consumeRetryInterval: time.Millisecond,
}
ctx1, cancel1 := context.WithCancel(context.Background())
ctx1, cancel1 := context.WithCancel(t.Context())
k.Subscribe(ctx1, SubscriptionHandlerConfig{}, "abc")
assert.Eventually(t, func() bool {
return consumeCalled.Load() == 1
@ -436,7 +436,7 @@ func Test_Subscribe(t *testing.T) {
assert.ElementsMatch(t, []string{"abc"}, consumeTopics.Load())
assert.Equal(t, int64(0), cancelCalled.Load())
ctx2, cancel2 := context.WithCancel(context.Background())
ctx2, cancel2 := context.WithCancel(t.Context())
k.Subscribe(ctx2, SubscriptionHandlerConfig{}, "def")
assert.Eventually(t, func() bool {
return consumeCalled.Load() == 2
@ -444,7 +444,7 @@ func Test_Subscribe(t *testing.T) {
assert.ElementsMatch(t, []string{"abc", "def"}, consumeTopics.Load())
assert.Equal(t, int64(1), cancelCalled.Load())
ctx3, cancel3 := context.WithCancel(context.Background())
ctx3, cancel3 := context.WithCancel(t.Context())
k.Subscribe(ctx3, SubscriptionHandlerConfig{}, "123")
assert.Eventually(t, func() bool {
return consumeCalled.Load() == 3
@ -459,7 +459,7 @@ func Test_Subscribe(t *testing.T) {
assert.ElementsMatch(t, []string{"abc", "123"}, consumeTopics.Load())
assert.Equal(t, int64(3), cancelCalled.Load())
ctx2, cancel2 = context.WithCancel(context.Background())
ctx2, cancel2 = context.WithCancel(t.Context())
k.Subscribe(ctx2, SubscriptionHandlerConfig{}, "456")
assert.Eventually(t, func() bool {
return consumeCalled.Load() == 5
@ -502,7 +502,7 @@ func Test_Subscribe(t *testing.T) {
consumeRetryInterval: time.Millisecond,
}
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
for i := range 100 {
go func(i int) {
k.Subscribe(ctx, SubscriptionHandlerConfig{}, strconv.Itoa(i))

View File

@ -54,6 +54,22 @@ func parseInitialOffset(value string) (initialOffset int64, err error) {
return initialOffset, err
}
// parseCompression parses the compression codec from the given string.
// If the string is empty, it returns the default compression codec.
// If the string is not empty, it returns the parsed compression codec.
// If the string is not empty and not a valid compression codec, it returns an error.
// Supported compression codecs are: none, gzip, snappy, lz4, zstd.
func parseCompression(value string) (compression sarama.CompressionCodec, err error) {
compression = sarama.CompressionNone // Default
if value != "" {
unmarshalErr := compression.UnmarshalText([]byte(value))
if unmarshalErr != nil {
return sarama.CompressionNone, fmt.Errorf("kafka error: invalid compression: %s", value)
}
}
return compression, err
}
// isValidPEM validates the provided input has PEM formatted block.
func isValidPEM(val string) bool {
block, _ := pem.Decode([]byte(val))
@ -64,7 +80,7 @@ func isValidPEM(val string) bool {
// TopicHandlerConfig is the map of topics and sruct containing handler and their config.
type TopicHandlerConfig map[string]SubscriptionHandlerConfig
// // TopicList returns the list of topics
// TopicList returns the list of topics
func (tbh TopicHandlerConfig) TopicList() []string {
topics := make([]string, len(tbh))
i := 0

View File

@ -39,7 +39,7 @@ func TestMetadata(t *testing.T) {
t.Run("has connection string", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
}
opts := postgresql.InitWithMetadataOpts{}
@ -50,7 +50,7 @@ func TestMetadata(t *testing.T) {
t.Run("default table name", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
}
opts := postgresql.InitWithMetadataOpts{}
@ -62,7 +62,7 @@ func TestMetadata(t *testing.T) {
t.Run("custom table name", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"tableName": "mytable",
}
@ -75,7 +75,7 @@ func TestMetadata(t *testing.T) {
t.Run("default timeout", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
}
opts := postgresql.InitWithMetadataOpts{}
@ -87,7 +87,7 @@ func TestMetadata(t *testing.T) {
t.Run("invalid timeout", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"timeout": "NaN",
}
@ -99,7 +99,7 @@ func TestMetadata(t *testing.T) {
t.Run("positive timeout", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"timeout": "42",
}
@ -112,7 +112,7 @@ func TestMetadata(t *testing.T) {
t.Run("zero timeout", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"timeout": "0",
}
@ -124,7 +124,7 @@ func TestMetadata(t *testing.T) {
t.Run("default cleanupInterval", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
}
opts := postgresql.InitWithMetadataOpts{}
@ -137,7 +137,7 @@ func TestMetadata(t *testing.T) {
t.Run("invalid cleanupInterval", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupInterval": "NaN",
}
@ -149,7 +149,7 @@ func TestMetadata(t *testing.T) {
t.Run("positive cleanupInterval", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupInterval": "42",
}
@ -163,7 +163,7 @@ func TestMetadata(t *testing.T) {
t.Run("positive cleanupIntervalInSeconds", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupIntervalInSeconds": "42",
}
@ -177,7 +177,7 @@ func TestMetadata(t *testing.T) {
t.Run("positive cleanupInterval as duration", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupInterval": "42m",
}
@ -191,7 +191,7 @@ func TestMetadata(t *testing.T) {
t.Run("positive cleanupIntervalInseconds as duration", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupIntervalInseconds": "42m",
}
@ -205,7 +205,7 @@ func TestMetadata(t *testing.T) {
t.Run("zero cleanupInterval", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupInterval": "0",
}
@ -218,7 +218,7 @@ func TestMetadata(t *testing.T) {
t.Run("zero cleanupIntervalInSeconds", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupIntervalInSeconds": "0",
}
@ -231,7 +231,7 @@ func TestMetadata(t *testing.T) {
t.Run("empty cleanupInterval", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupInterval": "",
}
@ -245,7 +245,7 @@ func TestMetadata(t *testing.T) {
t.Run("empty cleanupIntervalInSeconds", func(t *testing.T) {
m := pgMetadata{}
props := map[string]string{
"connectionString": "foo",
"connectionString": "foo=bar",
"cleanupIntervalInSeconds": "",
}

View File

@ -45,7 +45,7 @@ func TestMultiWithNoRequests(t *testing.T) {
defer m.db.Close()
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: nil,
})
@ -69,7 +69,7 @@ func TestValidSetRequest(t *testing.T) {
WillReturnResult(pgxmock.NewResult("INSERT", 1))
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})
@ -92,7 +92,7 @@ func TestValidSetRequest(t *testing.T) {
m.db.ExpectRollback()
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})
@ -114,7 +114,7 @@ func TestInvalidMultiSetRequestNoKey(t *testing.T) {
}
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})
@ -137,7 +137,7 @@ func TestValidMultiDeleteRequest(t *testing.T) {
WillReturnResult(pgxmock.NewResult("DELETE", 1))
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})
@ -160,7 +160,7 @@ func TestValidMultiDeleteRequest(t *testing.T) {
m.db.ExpectRollback()
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})
@ -180,7 +180,7 @@ func TestInvalidMultiDeleteRequestNoKey(t *testing.T) {
operations := []state.TransactionalStateOperation{state.DeleteRequest{}, state.DeleteRequest{}} // Delete request without key is not valid for Delete operation
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})
@ -210,7 +210,7 @@ func TestMultiOperationOrder(t *testing.T) {
m.db.ExpectRollback()
// Act
err := m.pg.Multi(context.Background(), &state.TransactionalStateRequest{
err := m.pg.Multi(t.Context(), &state.TransactionalStateRequest{
Operations: operations,
})

View File

@ -82,7 +82,7 @@ type RedisClient interface {
ConfigurationSubscribe(ctx context.Context, args *ConfigurationSubscribeArgs)
SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) (*bool, error)
EvalInt(ctx context.Context, script string, keys []string, args ...interface{}) (*int, error, error)
XAdd(ctx context.Context, stream string, maxLenApprox int64, values map[string]interface{}) (string, error)
XAdd(ctx context.Context, stream string, maxLenApprox int64, streamTTL string, values map[string]interface{}) (string, error)
XGroupCreateMkStream(ctx context.Context, stream string, group string, start string) error
XAck(ctx context.Context, stream string, group string, messageID string) error
XReadGroupResult(ctx context.Context, group string, consumer string, streams []string, count int64, block time.Duration) ([]RedisXStream, error)

View File

@ -102,6 +102,9 @@ type Settings struct {
// The max len of stream
MaxLenApprox int64 `mapstructure:"maxLenApprox" mdonly:"pubsub"`
// The TTL of stream entries
StreamTTL time.Duration `mapstructure:"streamTTL" mdonly:"pubsub"`
// EntraID / AzureAD Authentication based on the shared code which essentially uses the DefaultAzureCredential
// from the official Azure Identity SDK for Go
UseEntraID bool `mapstructure:"useEntraID" mapstructurealiases:"useAzureAD"`
@ -127,6 +130,15 @@ func (s *Settings) SetCertificate(fn func(cert *tls.Certificate)) error {
return nil
}
func (s *Settings) GetMinID(now time.Time) string {
// If StreamTTL is not set, return empty string (no trimming)
if s.StreamTTL == 0 {
return ""
}
return fmt.Sprintf("%d-1", now.Add(-s.StreamTTL).UnixMilli())
}
type Duration time.Duration
func (r *Duration) DecodeString(value string) error {

View File

@ -3,6 +3,7 @@ package redis
import (
"crypto/tls"
"testing"
"time"
"github.com/stretchr/testify/require"
)
@ -39,4 +40,34 @@ func TestSettings(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, c)
})
t.Run("stream TTL", func(t *testing.T) {
fixedTime := time.Date(2025, 3, 14, 0o1, 59, 26, 0, time.UTC)
tests := []struct {
name string
streamTTL time.Duration
want string
}{
{
name: "with one hour TTL",
streamTTL: time.Hour,
want: "1741913966000-1",
},
{
name: "with zero TTL",
streamTTL: 0,
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
settings := &Settings{
StreamTTL: tt.streamTTL,
}
require.Equal(t, tt.want, settings.GetMinID(fixedTime))
})
}
})
}

View File

@ -161,7 +161,7 @@ func (c v8Client) SetNX(ctx context.Context, key string, value interface{}, expi
return &val, nx.Err()
}
func (c v8Client) XAdd(ctx context.Context, stream string, maxLenApprox int64, values map[string]interface{}) (string, error) {
func (c v8Client) XAdd(ctx context.Context, stream string, maxLenApprox int64, minIDApprox string, values map[string]interface{}) (string, error) {
var writeCtx context.Context
if c.writeTimeout > 0 {
timeoutCtx, cancel := context.WithTimeout(ctx, time.Duration(c.writeTimeout))
@ -171,9 +171,11 @@ func (c v8Client) XAdd(ctx context.Context, stream string, maxLenApprox int64, v
writeCtx = ctx
}
return c.client.XAdd(writeCtx, &v8.XAddArgs{
Stream: stream,
Values: values,
MaxLenApprox: maxLenApprox,
Stream: stream,
Values: values,
MaxLen: maxLenApprox,
MinID: minIDApprox,
Approx: true,
}).Result()
}

View File

@ -161,7 +161,7 @@ func (c v9Client) SetNX(ctx context.Context, key string, value interface{}, expi
return &val, nx.Err()
}
func (c v9Client) XAdd(ctx context.Context, stream string, maxLenApprox int64, values map[string]interface{}) (string, error) {
func (c v9Client) XAdd(ctx context.Context, stream string, maxLenApprox int64, minIDApprox string, values map[string]interface{}) (string, error) {
var writeCtx context.Context
if c.writeTimeout > 0 {
timeoutCtx, cancel := context.WithTimeout(ctx, time.Duration(c.writeTimeout))
@ -174,6 +174,7 @@ func (c v9Client) XAdd(ctx context.Context, stream string, maxLenApprox int64, v
Stream: stream,
Values: values,
MaxLen: maxLenApprox,
MinID: minIDApprox,
Approx: true,
}).Result()
}

View File

@ -124,7 +124,7 @@ func (m *Migrations) GetConn() *sql.Conn {
}
// Returns true if a table exists
func (m Migrations) tableExists(parentCtx context.Context, db commonsql.DatabaseSQLConn, tableName string) (bool, error) {
func (m *Migrations) tableExists(parentCtx context.Context, db commonsql.DatabaseSQLConn, tableName string) (bool, error) {
ctx, cancel := context.WithTimeout(parentCtx, 30*time.Second)
defer cancel()
@ -138,7 +138,7 @@ func (m Migrations) tableExists(parentCtx context.Context, db commonsql.Database
return exists == "1", err
}
func (m Migrations) createMetadataTable(ctx context.Context, db commonsql.DatabaseSQLConn) error {
func (m *Migrations) createMetadataTable(ctx context.Context, db commonsql.DatabaseSQLConn) error {
m.Logger.Infof("Creating metadata table '%s' if it doesn't exist", m.MetadataTableName)
// Add an "IF NOT EXISTS" in case another Dapr sidecar is creating the same table at the same time
// In the next step we'll acquire a lock so there won't be issues with concurrency

View File

@ -132,7 +132,7 @@ WHEN NOT MATCHED THEN
return nil
}
func (m Migrations) ensureMetadataTable(ctx context.Context) error {
func (m *Migrations) ensureMetadataTable(ctx context.Context) error {
m.Logger.Infof("Ensuring metadata table '%s' exists", m.tableName)
_, err := m.DB.ExecContext(ctx, fmt.Sprintf(`
IF OBJECT_ID('%[1]s', 'U') IS NULL

View File

@ -66,7 +66,7 @@ func TestMigration(t *testing.T) {
_, err = db.Exec(fmt.Sprintf("CREATE SCHEMA [%s]", schema))
require.NoError(t, err, "Failed to create schema")
t.Cleanup(func() {
err = commonsqlserver.DropSchema(context.Background(), db, schema)
err = commonsqlserver.DropSchema(t.Context(), db, schema)
require.NoError(t, err, "Failed to drop schema")
})
@ -80,14 +80,14 @@ func TestMigration(t *testing.T) {
}
t.Run("Create new", func(t *testing.T) {
err = m.Perform(context.Background(), []commonsql.MigrationFn{})
err = m.Perform(t.Context(), []commonsql.MigrationFn{})
require.NoError(t, err)
assertTableExists(t, db, schema, "metadata_1")
})
t.Run("Already exists", func(t *testing.T) {
err = m.Perform(context.Background(), []commonsql.MigrationFn{})
err = m.Perform(t.Context(), []commonsql.MigrationFn{})
require.NoError(t, err)
assertTableExists(t, db, schema, "metadata_1")
@ -109,7 +109,7 @@ func TestMigration(t *testing.T) {
}
t.Run("First migration", func(t *testing.T) {
err = m.Perform(context.Background(), []commonsql.MigrationFn{fn1})
err = m.Perform(t.Context(), []commonsql.MigrationFn{fn1})
require.NoError(t, err)
assertTableExists(t, db, schema, "TestTable")
@ -124,7 +124,7 @@ func TestMigration(t *testing.T) {
return nil
}
err = m.Perform(context.Background(), []commonsql.MigrationFn{fn1, fn2})
err = m.Perform(t.Context(), []commonsql.MigrationFn{fn1, fn2})
require.NoError(t, err)
assert.True(t, called)
@ -139,7 +139,7 @@ func TestMigration(t *testing.T) {
return nil
}
err = m.Perform(context.Background(), []commonsql.MigrationFn{fn1, fn2})
err = m.Perform(t.Context(), []commonsql.MigrationFn{fn1, fn2})
require.NoError(t, err)
assert.False(t, called)
@ -174,7 +174,7 @@ func TestMigration(t *testing.T) {
MetadataKey: "migrations_concurrent",
}
migrateErr := m.Perform(context.Background(), []commonsql.MigrationFn{fn})
migrateErr := m.Perform(t.Context(), []commonsql.MigrationFn{fn})
if migrateErr != nil {
errs <- fmt.Errorf("migration failed in handler %d: %w", i, migrateErr)
}

View File

@ -19,12 +19,13 @@
package v2
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
durationpb "google.golang.org/protobuf/types/known/durationpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (

View File

@ -69,7 +69,7 @@ func TestWasmHTTPFetch(t *testing.T) {
ts := httptest.NewServer(tc.handler)
defer ts.Close()
c := newHTTPCLient(http.DefaultTransport)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second)
defer cancel()
parse, err := url.Parse(ts.URL)
require.NoError(t, err)

View File

@ -38,7 +38,7 @@ const (
var binArgs []byte
func TestGetInitMetadata(t *testing.T) {
testCtx, cancel := context.WithCancel(context.Background())
testCtx, cancel := context.WithCancel(t.Context())
t.Cleanup(cancel)
type testCase struct {
@ -184,7 +184,7 @@ func TestNewModuleConfig(t *testing.T) {
},
}
ctx := context.Background()
ctx := t.Context()
rt := wazero.NewRuntime(ctx)
defer rt.Close(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, rt)

View File

@ -110,7 +110,7 @@ func Test_getConfigurationWithProvidedKeys(t *testing.T) {
Keys: []string{"testKey"},
Metadata: map[string]string{},
}
res, err := s.Get(context.Background(), &req)
res, err := s.Get(t.Context(), &req)
require.NoError(t, err)
assert.Len(t, res.Items, 1)
})
@ -129,13 +129,13 @@ func Test_subscribeConfigurationWithProvidedKeys(t *testing.T) {
Keys: []string{"testKey"},
Metadata: metadata,
}
subID, err := s.Subscribe(context.Background(), &req, updateEventHandler)
subID, err := s.Subscribe(t.Context(), &req, updateEventHandler)
assert.NotEmpty(t, subID)
require.NoError(t, err)
unReq := &configuration.UnsubscribeRequest{
ID: subID,
}
s.Unsubscribe(context.Background(), unReq)
s.Unsubscribe(t.Context(), unReq)
})
t.Run("call subscribe w/o sentinel key", func(t *testing.T) {
@ -143,7 +143,7 @@ func Test_subscribeConfigurationWithProvidedKeys(t *testing.T) {
Keys: []string{"testKey"},
Metadata: make(map[string]string),
}
_, err := s.Subscribe(context.Background(), &req, updateEventHandler)
_, err := s.Subscribe(t.Context(), &req, updateEventHandler)
require.Error(t, err)
})
}
@ -152,7 +152,7 @@ func Test_unsubscribeConfigurationWithProvidedKeys(t *testing.T) {
s := NewAzureAppConfigurationStore(logger.NewLogger("test")).(*ConfigurationStore)
s.client = &MockConfigurationStore{}
cancelContext, cancel := context.WithCancel(context.Background())
cancelContext, cancel := context.WithCancel(t.Context())
s.cancelMap.Store("id1", cancel)
t.Run("call unsubscribe with incorrect subId", func(t *testing.T) {
@ -186,7 +186,7 @@ func Test_getConfigurationWithNoProvidedKeys(t *testing.T) {
Keys: []string{},
Metadata: map[string]string{},
}
res, err := s.Get(context.Background(), &req)
res, err := s.Get(t.Context(), &req)
require.NoError(t, err)
assert.Len(t, res.Items, 2)
})
@ -207,7 +207,7 @@ func TestInit(t *testing.T) {
Properties: testProperties,
}}
err := s.Init(context.Background(), m)
err := s.Init(t.Context(), m)
require.NoError(t, err)
cs, ok := s.(*ConfigurationStore)
assert.True(t, ok)
@ -232,7 +232,7 @@ func TestInit(t *testing.T) {
Properties: testProperties,
}}
err := s.Init(context.Background(), m)
err := s.Init(t.Context(), m)
require.NoError(t, err)
cs, ok := s.(*ConfigurationStore)
assert.True(t, ok)

View File

@ -122,3 +122,38 @@ metadata:
- "simple_protocol"
example: "cache_describe"
default: ""
- name: host
required: false
description: The host of the PostgreSQL database
example: "localhost"
type: string
- name: hostaddr
required: false
description: The host address of the PostgreSQL database
example: "127.0.0.1"
type: string
- name: port
required: false
description: The port of the PostgreSQL database
example: "5432"
type: string
- name: database
required: false
description: The database of the PostgreSQL database
example: "postgres"
type: string
- name: user
required: false
description: The user of the PostgreSQL database
example: "postgres"
type: string
- name: password
required: false
description: The password of the PostgreSQL database
example: "password"
type: string
- name: sslRootCert
required: false
description: The path to the SSL root certificate file
example: "/path/to/ssl/root/cert.pem"
type: string

View File

@ -14,7 +14,6 @@ limitations under the License.
package postgres
import (
"context"
"regexp"
"testing"
@ -98,7 +97,7 @@ func TestConnectAndQuery(t *testing.T) {
[]string{"exists"}).
AddRow(string("t")),
)
rows := mock.QueryRow(context.Background(), query)
rows := mock.QueryRow(t.Context(), query)
var id string
err = rows.Scan(&id)
require.NoError(t, err, "error in scan")

Some files were not shown because too many files have changed in this diff Show More